From 0dd57ae901e8cab95a1de397e17b845d6bfca1d3 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 9 Apr 2021 21:18:30 -0700 Subject: [PATCH 001/122] Adding mutex to ImageProcessingBus --- .../Code/Include/Atom/ImageProcessing/ImageProcessingBus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingBus.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingBus.h index 318f43016d..b8deb50cc5 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingBus.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingBus.h @@ -25,6 +25,7 @@ namespace ImageProcessingAtom // EBusTraits overrides static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + typedef AZStd::recursive_mutex MutexType; ////////////////////////////////////////////////////////////////////////// // Loads an image from a source file path From 5fc4aeaf09c0aa29f5537c248cde5f166014bec1 Mon Sep 17 00:00:00 2001 From: hultonha Date: Mon, 12 Apr 2021 11:03:46 +0100 Subject: [PATCH 002/122] add alias for AZStd::vector before potential change --- Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h | 7 +++++-- Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h | 6 +++--- .../Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp | 4 +++- .../Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp | 4 ++-- .../Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h | 8 ++++---- Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp | 8 ++++---- Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h | 2 +- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h index f47c5c6b0e..5b8d384774 100644 --- a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h +++ b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h @@ -102,6 +102,9 @@ namespace WhiteBox //! Alias for a collection of faces. using Faces = AZStd::vector; + //! Underlying representation of the White Box mesh (serialized halfedge data). + using WhiteBoxMeshStream = AZStd::vector; + //! Represents the vertex handles to be used to form a new face. struct FaceVertHandles { @@ -729,7 +732,7 @@ namespace WhiteBox //! Take an input stream of bytes and create a white box mesh from the deserialized data. //! @return Will return false if any error was encountered during deserialization, true otherwise. //! @note A white box mesh must have been created first. - bool ReadMesh(WhiteBoxMesh& whiteBox, const AZStd::vector& input); + bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); //! Take an input stream and create a white box mesh from the deserialized data. //! @return Will return false if any error was encountered during deserialization, true otherwise. @@ -738,7 +741,7 @@ namespace WhiteBox //! Take a white box mesh and write it out to a stream of bytes. //! @return Will return false if any error was encountered during serialization, true otherwise. - bool WriteMesh(const WhiteBoxMesh& whiteBox, AZStd::vector& output); + bool WriteMesh(const WhiteBoxMesh& whiteBox, WhiteBoxMeshStream& output); //! Clones the white box mesh object into a new mesh. //! @return Will return null if any error was encountered during serialization, otherwise the cloned mesh. diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h index f5915d033b..d25af2fed2 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h @@ -51,12 +51,12 @@ namespace WhiteBox return AZStd::move(m_mesh); } - void SetWhiteBoxData(AZStd::vector whiteBoxData) + void SetWhiteBoxData(Api::WhiteBoxMeshStream whiteBoxData) { m_whiteBoxData = AZStd::move(whiteBoxData); } - const AZStd::vector& GetWhiteBoxData() const + const Api::WhiteBoxMeshStream& GetWhiteBoxData() const { return m_whiteBoxData; } @@ -73,7 +73,7 @@ namespace WhiteBox } Api::WhiteBoxMeshPtr m_mesh; - AZStd::vector m_whiteBoxData; //! Data used for creating undo commands. + Api::WhiteBoxMeshStream m_whiteBoxData; //! Data used for creating undo commands. }; } // namespace Pipeline } // namespace WhiteBox diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index a64c552bb6..72a754f05f 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -112,7 +112,9 @@ namespace WhiteBox const auto size = stream->GetLength(); - AZStd::vector whiteBoxData(size); + Api::WhiteBoxMeshStream whiteBoxData; + whiteBoxData.reserve(size); + stream->Read(size, whiteBoxData.data()); auto whiteBoxMesh = WhiteBox::Api::CreateWhiteBoxMesh(); diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp index ef11b8d47d..19cbc802dd 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp @@ -29,12 +29,12 @@ namespace WhiteBox m_asset = asset; } - void WhiteBoxMeshAssetUndoCommand::SetUndoState(const AZStd::vector& undoState) + void WhiteBoxMeshAssetUndoCommand::SetUndoState(const Api::WhiteBoxMeshStream& undoState) { m_undoState = undoState; } - void WhiteBoxMeshAssetUndoCommand::SetRedoState(const AZStd::vector& redoState) + void WhiteBoxMeshAssetUndoCommand::SetRedoState(const Api::WhiteBoxMeshStream& redoState) { m_redoState = redoState; } diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h index eb657c5a85..3f6258c1b4 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h @@ -34,8 +34,8 @@ namespace WhiteBox ~WhiteBoxMeshAssetUndoCommand() override = default; void SetAsset(AZ::Data::Asset asset); - void SetUndoState(const AZStd::vector& undoState); - void SetRedoState(const AZStd::vector& redoState); + void SetUndoState(const Api::WhiteBoxMeshStream& undoState); + void SetRedoState(const Api::WhiteBoxMeshStream& redoState); // AzToolsFramework::UndoSystem::URSequencePoint ... void Undo() override; @@ -44,7 +44,7 @@ namespace WhiteBox protected: AZ::Data::Asset m_asset; - AZStd::vector m_undoState; - AZStd::vector m_redoState; + Api::WhiteBoxMeshStream m_undoState; + Api::WhiteBoxMeshStream m_redoState; }; } // namespace WhiteBox diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 49e713810e..fbab501e8f 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3379,7 +3379,7 @@ namespace WhiteBox CalculatePlanarUVs(whiteBox); } - bool WriteMesh(const WhiteBoxMesh& whiteBox, AZStd::vector& output) + bool WriteMesh(const WhiteBoxMesh& whiteBox, WhiteBoxMeshStream& output) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -3403,7 +3403,7 @@ namespace WhiteBox return false; } - bool ReadMesh(WhiteBoxMesh& whiteBox, const AZStd::vector& input) + bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -3437,7 +3437,7 @@ namespace WhiteBox { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); - AZStd::vector clonedData; + WhiteBoxMeshStream clonedData; if (!WriteMesh(whiteBox, clonedData)) { return nullptr; @@ -3461,7 +3461,7 @@ namespace WhiteBox bool SaveToWbm(const WhiteBoxMesh& whiteBox, AZ::IO::GenericStream& stream) { - AZStd::vector buffer; + WhiteBoxMeshStream buffer; const bool success = WhiteBox::Api::WriteMesh(whiteBox, buffer); const auto bytesWritten = stream.Write(buffer.size(), buffer.data()); diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h index 5d7ac3b303..02b50a9407 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h @@ -124,7 +124,7 @@ namespace WhiteBox AZStd::optional> m_renderMesh; //!< The render mesh to use for the White Box mesh data. AZ::Transform m_worldFromLocal = AZ::Transform::CreateIdentity(); //!< Cached world transform of Entity. - AZStd::vector m_whiteBoxData; //!< Serialized White Box mesh data. + Api::WhiteBoxMeshStream m_whiteBoxData; //!< Serialized White Box mesh data. //! Holds a reference to an optional WhiteBoxMeshAsset and manages the lifecycle of adding/removing an asset. EditorWhiteBoxMeshAsset* m_editorMeshAsset = nullptr; AZStd::optional m_worldAabb; //!< Cached world aabb (used for selection/view determination). From 8ee92978f4e96a91b3ef1350d009b2ddaa45bbca Mon Sep 17 00:00:00 2001 From: greerdv Date: Mon, 12 Apr 2021 13:07:40 +0100 Subject: [PATCH 003/122] setting max value for scale --- .../AzCore/AzCore/Component/NonUniformScaleBus.h | 3 --- Code/Framework/AzCore/AzCore/Math/Transform.h | 7 +++++++ .../AzFramework/Components/NonUniformScaleComponent.cpp | 5 +++-- .../ToolsComponents/EditorNonUniformScaleComponent.cpp | 9 ++++++--- .../ToolsComponents/TransformComponent.cpp | 1 - .../ToolsComponents/TransformScalePropertyHandler.cpp | 5 +++-- .../EditorTransformComponentSelection.cpp | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h b/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h index af2fe20a50..9b52fc1794 100644 --- a/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h +++ b/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h @@ -19,9 +19,6 @@ namespace AZ { class Vector3; - //! Do not allow the scale to be zero to avoid problems with inverting scale. - static constexpr float MinNonUniformScale = 1e-3f; - using NonUniformScaleChangedEvent = AZ::Event; //! Requests for working with non-uniform scale. diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.h b/Code/Framework/AzCore/AzCore/Math/Transform.h index 6c96a9a6a6..eb1a12a912 100644 --- a/Code/Framework/AzCore/AzCore/Math/Transform.h +++ b/Code/Framework/AzCore/AzCore/Math/Transform.h @@ -38,6 +38,13 @@ namespace AZ bool CompareValueData(const void* lhs, const void* rhs) override; }; + //! Limits for transform scale values. + //! The scale should not be zero to avoid problems with inverting. + //! @{ + static constexpr float MinTransformScale = 1e-2f; + static constexpr float MaxTransformScale = 1e9f; + //! @} + //! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation. //! By design, cannot represent skew transformations. class Transform diff --git a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp index 630dbb0322..095d986fa1 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -81,13 +82,13 @@ namespace AzFramework void NonUniformScaleComponent::SetScale(const AZ::Vector3& scale) { - if (scale.GetMinElement() >= AZ::MinNonUniformScale) + if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale) { m_scale = scale; } else { - AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale)); + AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); AZ_Warning("Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s", AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str()); m_scale = clampedScale; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp index 7c4d72dbbf..5e928a382a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace AzToolsFramework @@ -44,7 +45,9 @@ namespace AzToolsFramework ->DataElement( AZ::Edit::UIHandlers::Default, &EditorNonUniformScaleComponent::m_scale, "Non-uniform Scale", "Non-uniform scale for this entity only (does not propagate through hierarchy)") - ->Attribute(AZ::Edit::Attributes::Min, AZ::MinNonUniformScale) + ->Attribute(AZ::Edit::Attributes::Min, AZ::MinTransformScale) + ->Attribute(AZ::Edit::Attributes::Max, AZ::MaxTransformScale) + ->Attribute(AZ::Edit::Attributes::Step, 0.1f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorNonUniformScaleComponent::OnScaleChanged) ; } @@ -106,13 +109,13 @@ namespace AzToolsFramework void EditorNonUniformScaleComponent::SetScale(const AZ::Vector3& scale) { - if (scale.GetMinElement() >= AZ::MinNonUniformScale) + if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale) { m_scale = scale; } else { - AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale)); + AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); AZ_Warning("Editor Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s", AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str()); m_scale = clampedScale; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index 2ceb97adfd..7ce11e5957 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -1276,7 +1276,6 @@ namespace AzToolsFramework Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)-> DataElement(TransformScaleHandler, &EditorTransform::m_scale, "Scale", "Local Scale")-> Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Min, 0.01f)-> Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked) ; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp index 0105d9bbad..94d0113bcf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp @@ -12,6 +12,7 @@ #include "AzToolsFramework_precompiled.h" #include +#include #include namespace AzToolsFramework @@ -36,8 +37,8 @@ namespace AzToolsFramework AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestWrite, newCtrl); }); - newCtrl->setMinimum(0.01f); - newCtrl->setMaximum(std::numeric_limits::max()); + newCtrl->setMinimum(AZ::MinTransformScale); + newCtrl->setMaximum(AZ::MaxTransformScale); return newCtrl; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 27222e9aac..83632708d9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1603,7 +1603,7 @@ namespace AzToolsFramework const AZ::Vector3 uniformScale = AZ::Vector3(action.m_start.m_sign * sumVectorElements(action.LocalScaleOffset())); const AZ::Vector3 scale = (AZ::Vector3::CreateOne() + - (uniformScale / initialScale)).GetMax(AZ::Vector3(0.01f)); + (uniformScale / initialScale)).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); const AZ::Transform scaleTransform = AZ::Transform::CreateScale(scale); if (action.m_modifiers.Alt()) From 77d06ecef7f31f2314c907b6ac79059b1f01359b Mon Sep 17 00:00:00 2001 From: jackalbe Date: Mon, 12 Apr 2021 12:30:30 -0500 Subject: [PATCH 004/122] ATOM-14889: Fix for scriptProcessorRule doesn't save with field empty * removed the script rule from the Editor, now will only be supported via a script or JSON manual edits * Mesh Serialization - scriptProcessorRule doesn't save with field empty, but produces no error * added a test to make sure Script Processor Rule operates with an empty filename Jira: https://jira.agscollab.com/browse/ATOM-14889 Tests: Launched the Editor to removed the script rule from the Editor --- .../UnitTest/Mocks/MockSettingsRegistry.h | 59 +++++++++++++++++++ .../AzCore/azcoretestcommon_files.cmake | 1 + Code/Tools/SceneAPI/SceneCore/DllMain.cpp | 2 + .../Behaviors/ScriptProcessorRuleBehavior.h | 9 +-- .../SceneData/ManifestMetaInfoHandler.cpp | 2 - .../SceneManifest/SceneManifestRuleTests.cpp | 56 +++++++++++++++++- 6 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h new file mode 100644 index 0000000000..f4abbd9867 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -0,0 +1,59 @@ +/* +* 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 +{ + class MockSettingsRegistry; + using NiceSettingsRegistrySimpleMock = ::testing::NiceMock; + + class MockSettingsRegistry + : public AZ::SettingsRegistryInterface + { + public: + MOCK_CONST_METHOD1(GetType, Type(AZStd::string_view)); + MOCK_CONST_METHOD2(Visit, bool(Visitor&, AZStd::string_view)); + MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view)); + MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&)); + MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&)); + + MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view)); + MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view)); + MOCK_CONST_METHOD2(Get, bool(u64&, AZStd::string_view)); + MOCK_CONST_METHOD2(Get, bool(double&, AZStd::string_view)); + MOCK_CONST_METHOD2(Get, bool(AZStd::string&, AZStd::string_view)); + MOCK_CONST_METHOD2(Get, bool(FixedValueString&, AZStd::string_view)); + MOCK_CONST_METHOD3(GetObject, bool(void*, Uuid, AZStd::string_view)); + + MOCK_METHOD2(Set, bool(AZStd::string_view, bool)); + MOCK_METHOD2(Set, bool(AZStd::string_view, s64)); + MOCK_METHOD2(Set, bool(AZStd::string_view, u64)); + MOCK_METHOD2(Set, bool(AZStd::string_view, double)); + MOCK_METHOD2(Set, bool(AZStd::string_view, AZStd::string_view)); + MOCK_METHOD2(Set, bool(AZStd::string_view, const char*)); + MOCK_METHOD3(SetObject, bool(AZStd::string_view, const void*, Uuid)); + + MOCK_METHOD1(Remove, bool(AZStd::string_view)); + + MOCK_METHOD3(MergeCommandLineArgument, bool(AZStd::string_view, AZStd::string_view, const CommandLineArgumentSettings&)); + MOCK_METHOD2(MergeSettings, bool(AZStd::string_view, Format)); + MOCK_METHOD4(MergeSettingsFile, bool(AZStd::string_view, Format, AZStd::string_view, AZStd::vector*)); + MOCK_METHOD5( + MergeSettingsFolder, + bool(AZStd::string_view, const Specializations&, AZStd::string_view, AZStd::string_view, AZStd::vector*)); + }; +} // namespace AZ + diff --git a/Code/Framework/AzCore/AzCore/azcoretestcommon_files.cmake b/Code/Framework/AzCore/AzCore/azcoretestcommon_files.cmake index 86fb964197..a2ce93f68b 100644 --- a/Code/Framework/AzCore/AzCore/azcoretestcommon_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcoretestcommon_files.cmake @@ -15,4 +15,5 @@ set(FILES UnitTest/UnitTest.h UnitTest/TestTypes.h UnitTest/Mocks/MockFileIOBase.h + UnitTest/Mocks/MockSettingsRegistry.h ) diff --git a/Code/Tools/SceneAPI/SceneCore/DllMain.cpp b/Code/Tools/SceneAPI/SceneCore/DllMain.cpp index 49cea83dff..52976f9e56 100644 --- a/Code/Tools/SceneAPI/SceneCore/DllMain.cpp +++ b/Code/Tools/SceneAPI/SceneCore/DllMain.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -168,6 +169,7 @@ namespace AZ context->Class()->Version(1); context->Class()->Version(1); context->Class()->Version(1); + context->Class()->Version(1); // Register graph data interfaces context->Class()->Version(1); context->Class()->Version(1); diff --git a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h index 338f8d1896..b9cc17b99a 100644 --- a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h +++ b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h @@ -12,6 +12,7 @@ #pragma once +#include #include #include #include @@ -27,7 +28,7 @@ namespace AZ { namespace Behaviors { - class ScriptProcessorRuleBehavior + class SCENE_DATA_CLASS ScriptProcessorRuleBehavior : public SceneCore::BehaviorComponent , public Events::AssetImportRequestBus::Handler { @@ -36,12 +37,12 @@ namespace AZ ~ScriptProcessorRuleBehavior() override = default; - void Activate() override; - void Deactivate() override; + SCENE_DATA_API void Activate() override; + SCENE_DATA_API void Deactivate() override; static void Reflect(ReflectContext* context); // AssetImportRequestBus::Handler - Events::ProcessingResult UpdateManifest( + SCENE_DATA_API Events::ProcessingResult UpdateManifest( Containers::Scene& scene, ManifestAction action, RequestingApplication requester) override; diff --git a/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp b/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp index b7347c0c91..b01dc80d44 100644 --- a/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp +++ b/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +54,6 @@ namespace AZ { AZ_TraceContext("Object Type", target.RTTI_GetTypeName()); modifiers.push_back(SceneData::CommentRule::TYPEINFO_Uuid()); - modifiers.push_back(SceneData::ScriptProcessorRule::TYPEINFO_Uuid()); if (target.RTTI_IsTypeOf(DataTypes::IMeshGroup::TYPEINFO_Uuid())) { diff --git a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp index 17a1b0d19a..a5994dd272 100644 --- a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp +++ b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp @@ -13,19 +13,23 @@ #include #include +#include +#include #include #include +#include +#include #include #include #include -#include #include +#include #include #include +#include #include #include -#include namespace AZ { @@ -94,6 +98,19 @@ namespace AZ m_jsonSystemComponent = AZStd::make_unique(); m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); + + m_data.reset(new DataMembers); + + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + + ON_CALL(m_data->m_settings, Get(::testing::Matcher(::testing::_), testing::_)) + .WillByDefault([](FixedValueString& value, AZStd::string_view) -> bool + { + value = "mock_path"; + return true; + }); + + AZ::SettingsRegistry::Register(&m_data->m_settings); } void TearDown() override @@ -106,9 +123,19 @@ namespace AZ m_jsonRegistrationContext.reset(); m_jsonSystemComponent.reset(); + AZ::SettingsRegistry::Unregister(&m_data->m_settings); + m_data.reset(); + AZ::NameDictionary::Destroy(); UnitTest::AllocatorsFixture::TearDown(); } + + struct DataMembers + { + AZ::NiceSettingsRegistrySimpleMock m_settings; + }; + + AZStd::unique_ptr m_data; }; TEST_F(SceneManifest_JSON, LoadFromString_BlankManifest_HasDefaultParts) @@ -223,5 +250,30 @@ namespace AZ EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(3.0)")); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("scale": 10.0)")); } + + TEST_F(SceneManifest_JSON, ScriptProcessorRule_LoadWithEmptyScriptFilename_ReturnsEarly) + { + using namespace SceneAPI::Containers; + using namespace SceneAPI::Events; + + constexpr const char* jsonManifest = { R"JSON( + { + "values": [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "" + } + ] + })JSON" }; + + auto scene = AZ::SceneAPI::Containers::Scene("mock"); + auto result = scene.GetManifest().LoadFromString(jsonManifest, m_serializeContext.get(), m_jsonRegistrationContext.get()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_FALSE(scene.GetManifest().IsEmpty()); + + auto scriptProcessorRuleBehavior = AZ::SceneAPI::Behaviors::ScriptProcessorRuleBehavior(); + auto update = scriptProcessorRuleBehavior.UpdateManifest(scene, AssetImportRequest::Update, AssetImportRequest::Generic); + EXPECT_EQ(update, ProcessingResult::Ignored); + } } } From f188e1c9a7b77ce41ff83bc1e13169e01d677529 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Mon, 12 Apr 2021 16:03:10 -0700 Subject: [PATCH 005/122] Fixing ShaderVariantAsyncLoader shutdown not releasing it's assets --- .../Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp | 1 + 1 file changed, 1 insertion(+) 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 5b58e6ec6c..fa4fd241df 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp @@ -174,6 +174,7 @@ namespace AZ m_serviceThread.join(); Data::AssetBus::MultiHandler::BusDisconnect(); + m_newShaderVariantPendingRequests.clear(); m_shaderVariantTreePendingRequests.clear(); m_shaderVariantPendingRequests.clear(); m_shaderVariantData.clear(); From ea7b8309b513b3f64fbf8f8e5185beefb242a30f Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Tue, 13 Apr 2021 00:43:33 -0500 Subject: [PATCH 006/122] Updating the FOLDER filtering in the LyTestWrappers.cmake custom targets to remove leading '..' from the VS folder filter --- cmake/LYTestWrappers.cmake | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 4f8d0bc169..73a212ee0b 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -213,8 +213,14 @@ function(ly_add_test) add_custom_target(${unaliased_test_name} COMMAND ${CMAKE_COMMAND} -E true ${args_TEST_COMMAND} ${args_TEST_ARGUMENTS}) file(RELATIVE_PATH project_path ${LY_ROOT_FOLDER} ${CMAKE_CURRENT_SOURCE_DIR}) + set(ide_path ${project_path}) + # Visual Studio doesn't support a folder layout that starts with ".." + # So strip away the parent directory of a relative path + if (${project_path} MATCHES [[^(\.\./)+(.*)]]) + set(ide_path "${CMAKE_MATCH_2}") + endif() set_target_properties(${unaliased_test_name} PROPERTIES - FOLDER "${project_path}" + FOLDER "${ide_path}" VS_DEBUGGER_COMMAND ${test_command} VS_DEBUGGER_COMMAND_ARGUMENTS "${test_arguments_line}" ) From a99786fe5919d977d9bc762aef9e4c92a5853d6b Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 09:00:33 +0100 Subject: [PATCH 007/122] fixing bug with visibility aabb for non-uniformly scaled polygon prism at activation --- Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp index 28056c6e60..89c5028e93 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp @@ -217,6 +217,7 @@ namespace LmbrCentral AZ::TransformBus::EventResult(m_currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM); m_currentNonUniformScale = AZ::Vector3::CreateOne(); AZ::NonUniformScaleRequestBus::EventResult(m_currentNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); + m_polygonPrism->SetNonUniformScale(m_currentNonUniformScale); m_intersectionDataCache.InvalidateCache(InvalidateShapeCacheReason::ShapeChange); AZ::TransformNotificationBus::Handler::BusConnect(entityId); From 87a3dfc968d6b8debf53d58bb4c5a429ffb2adc4 Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 09:04:13 +0100 Subject: [PATCH 008/122] fixing bug in editor bodies for rigid bodies with non-uniformly scaled asset colliders with position offsets --- Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index eff1997473..d5ce38d389 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -36,7 +36,7 @@ namespace PhysX const bool hasNonUniformScaleComponent = (AZ::NonUniformScaleRequestBus::FindFirstHandler(entity->GetId()) != nullptr); - const AZStd::vector colliders = entity->FindComponents(); + const AZStd::vector colliders = entity->FindComponents(); for (const EditorColliderComponent* collider : colliders) { const EditorProxyShapeConfig& shapeConfigurationProxy = collider->GetShapeConfiguration(); @@ -45,12 +45,14 @@ namespace PhysX continue; } - const Physics::ColliderConfiguration colliderConfiguration = collider->GetColliderConfigurationScaled(); + const Physics::ColliderConfiguration colliderConfigurationScaled = collider->GetColliderConfigurationScaled(); + const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration(); + if (shapeConfigurationProxy.IsAssetConfig()) { AZStd::vector> shapes; Utils::GetShapesFromAsset(shapeConfigurationProxy.m_physicsAsset.m_configuration, - colliderConfiguration, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes); + colliderConfigurationUnscaled, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes); for (const auto& shape : shapes) { @@ -64,7 +66,7 @@ namespace PhysX if (!hasNonUniformScaleComponent) { AZStd::shared_ptr shape = AZ::Interface::Get()->CreateShape( - colliderConfiguration, shapeConfiguration); + colliderConfigurationScaled, shapeConfiguration); AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!"); if (shape) { @@ -73,7 +75,6 @@ namespace PhysX } else { - const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration(); auto convexConfig = Utils::CreateConvexFromPrimitive(colliderConfigurationUnscaled, shapeConfiguration, shapeConfigurationProxy.m_subdivisionLevel, shapeConfiguration.m_scale); auto colliderConfigurationNoOffset = colliderConfigurationUnscaled; @@ -377,7 +378,7 @@ namespace PhysX configuration.m_kinematic = m_config.m_kinematic; configuration.m_colliderAndShapeData = Internal::GetCollisionShapes(GetEntity()); - if (auto* sceneInterface = AZ::Interface::Get()) + if (auto* sceneInterface = AZ::Interface::Get()) { m_rigidBodyHandle = sceneInterface->AddSimulatedBody(m_editorSceneHandle, &configuration); m_editorBody = azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_rigidBodyHandle)); From 90e52d69bc465519707c89d22c0568882fcc6637 Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 10:50:07 +0100 Subject: [PATCH 009/122] fixing bug with subdivision level for runtime asset colliders and adding caching for collider aabbs --- .../Physics/ShapeConfiguration.cpp | 1 + .../AzFramework/Physics/ShapeConfiguration.h | 1 + .../Code/Source/BaseColliderComponent.cpp | 7 +++---- .../Code/Source/EditorColliderComponent.cpp | 20 ++++++++++++++----- .../Code/Source/EditorColliderComponent.h | 2 ++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp index 44c24758f3..f01e42a443 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp @@ -142,6 +142,7 @@ namespace Physics ->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset) ->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale) ->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset) + ->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel) ; if (auto editContext = serializeContext->GetEditContext()) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h index 8afe6851b7..b3d04a10c9 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h @@ -141,6 +141,7 @@ namespace Physics AZ::Data::Asset m_asset{ AZ::Data::AssetLoadBehavior::PreLoad }; AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne(); bool m_useMaterialsFromAsset = true; + AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling. }; class NativeShapeConfiguration : public ShapeConfiguration diff --git a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp index f4bc86ef93..c67cc105d8 100644 --- a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp @@ -330,10 +330,9 @@ namespace PhysX } const bool hasNonUniformScale = (AZ::NonUniformScaleRequestBus::FindFirstHandler(GetEntityId()) != nullptr); - // the value for the subdivision level doesn't matter in the runtime, because any approximation of primitives will already have - // happened in the editor, so can pass an arbitrary value here - AZ::u8 subdivisionLevel = 0; - Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, subdivisionLevel, m_shapes); + AZ::u8 subdivisionLevel = physicsAssetConfiguration.m_subdivisionLevel; + Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, + physicsAssetConfiguration.m_subdivisionLevel, m_shapes); return true; } diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 974ce23810..8c31746931 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -513,6 +513,8 @@ namespace PhysX break; case Physics::ShapeType::PhysicsAsset: colliderComponent = gameEntity->CreateComponent(); + + m_shapeConfiguration.m_physicsAsset.m_configuration.m_subdivisionLevel = m_shapeConfiguration.m_subdivisionLevel; colliderComponent->SetShapeConfigurationList({ AZStd::make_pair(sharedColliderConfig, AZStd::make_shared(m_shapeConfiguration.m_physicsAsset.m_configuration)) }); @@ -560,6 +562,8 @@ namespace PhysX void EditorColliderComponent::CreateStaticEditorCollider() { + m_cachedAabbDirty = true; + // Don't create static rigid body in the editor if current entity components // don't allow creation of runtime static rigid body component if (!StaticRigidBodyUtils::CanCreateRuntimeComponent(*GetEntity())) @@ -1014,11 +1018,17 @@ namespace PhysX // PhysX::ColliderShapeBus AZ::Aabb EditorColliderComponent::GetColliderShapeAabb() { - return PhysX::Utils::GetColliderAabb(GetWorldTM() - , m_hasNonUniformScale - , m_shapeConfiguration.m_subdivisionLevel - , m_shapeConfiguration.GetCurrent() - , m_configuration); + if (m_cachedAabbDirty) + { + m_cachedAabb = PhysX::Utils::GetColliderAabb(GetWorldTM() + , m_hasNonUniformScale + , m_shapeConfiguration.m_subdivisionLevel + , m_shapeConfiguration.GetCurrent() + , m_configuration); + m_cachedAabbDirty = false; + } + + return m_cachedAabb; } void EditorColliderComponent::UpdateShapeConfigurationScale() diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 65c7a9c67f..f179525802 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -261,6 +261,8 @@ namespace PhysX bool m_hasNonUniformScale = false; //!< Whether there is a non-uniform scale component on this entity. AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale. mutable AZStd::optional m_scaledPrimitive; //!< Approximation for non-uniformly scaled primitive. + AZ::Aabb m_cachedAabb = AZ::Aabb::CreateNull(); //!< Cache the Aabb to avoid recalculating it. + bool m_cachedAabbDirty = true; //!< Track whether the cached Aabb needs to be recomputed. AZ::ComponentDescriptor::StringWarningArray m_componentWarnings; }; From 8846e159e09694d16af388dec6b6abb7c412d1c6 Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 13 Apr 2021 11:54:22 +0100 Subject: [PATCH 010/122] Add new ByteStream serializer to support storing binary data in json (for now) --- .../Json/ByteStreamSerializer.cpp | 99 +++++++++++++++++++ .../Serialization/Json/ByteStreamSerializer.h | 38 +++++++ .../Json/JsonSystemComponent.cpp | 3 + .../AzCore/AzCore/azcore_files.cmake | 2 + 4 files changed, 142 insertions(+) create mode 100644 Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp create mode 100644 Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp new file mode 100644 index 0000000000..59c2d1b7e0 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -0,0 +1,99 @@ +/* + * 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 "ByteStreamSerializer.h" + +#include +#include +#include + +namespace AZ +{ + namespace ByteSerializerInternal + { + static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + using JsonSerializationResult::Outcomes; + using JsonSerializationResult::Tasks; + + AZ_Assert(outputValue, "Expected a valid pointer to load from json value."); + + switch (inputValue.GetType()) + { + case rapidjson::kStringType: { + JsonByteStream* valAsByteStream = reinterpret_cast(outputValue); + JsonByteStream buffer; + buffer.resize(inputValue.GetStringLength()); + AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); + *valAsByteStream = AZStd::move(buffer); + return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + } + case rapidjson::kArrayType: + case rapidjson::kObjectType: + case rapidjson::kNullType: + case rapidjson::kFalseType: + case rapidjson::kTrueType: + case rapidjson::kNumberType: + return context.Report( + Tasks::ReadField, Outcomes::Unsupported, + "Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers."); + default: + return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value."); + } + } + + static JsonSerializationResult::Result StoreWithDefault( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context) + { + using JsonSerializationResult::Outcomes; + using JsonSerializationResult::Tasks; + + const JsonByteStream& valAsByteStream = *reinterpret_cast(inputValue); + if (context.ShouldKeepDefaults() || !defaultValue || + (valAsByteStream != *reinterpret_cast(defaultValue))) + { + outputValue.SetString( + reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), + context.GetJsonAllocator()); + return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored."); + } + + return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used."); + } + } // namespace ByteSerializerInternal + + AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonByteStreamSerializer::Load( + void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) + { + AZ_Assert( + azrtti_typeid() == outputValueTypeId, + "Unable to deserialize AZStd::vector> to json because the provided type is %s", + outputValueTypeId.ToString().c_str()); + + return ByteSerializerInternal::Load(outputValue, inputValue, context); + } + + JsonSerializationResult::Result JsonByteStreamSerializer::Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId, + JsonSerializerContext& context) + { + AZ_Assert( + azrtti_typeid() == valueTypeId, + "Unable to serialize AZStd::vector to json because the provided type is %s", + valueTypeId.ToString().c_str()); + + return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context); + } +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h new file mode 100644 index 0000000000..4f01e28319 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h @@ -0,0 +1,38 @@ +/* + * 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 +{ + using JsonByteStream = AZStd::vector; //!< Alias for AZStd::vector. + + //! Serialize a stream of bytes (usually binary data) as a json string value. + //! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo> - see AZStdContainers.inl for more + //! details). + class JsonByteStreamSerializer : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + JsonSerializationResult::Result Load( + void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + JsonSerializationResult::Result Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, + JsonSerializerContext& context) override; + }; +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp index e33466d8dc..e5a1f5e6bb 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ namespace AZ jsonContext->Serializer()->HandlesType(); jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType>(); + jsonContext->Serializer() ->HandlesType() ->HandlesType() diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 97b86f2432..e100b240c2 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -505,6 +505,8 @@ set(FILES Serialization/Json/BasicContainerSerializer.cpp Serialization/Json/BoolSerializer.h Serialization/Json/BoolSerializer.cpp + Serialization/Json/ByteStreamSerializer.h + Serialization/Json/ByteStreamSerializer.cpp Serialization/Json/CastingHelpers.h Serialization/Json/DoubleSerializer.h Serialization/Json/DoubleSerializer.cpp From 063b8a6d5476bdba1077703c6825d6c437c335a1 Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 13 Apr 2021 12:16:55 +0100 Subject: [PATCH 011/122] update some reinterpret_cast calls to static_cast --- .../AzCore/Serialization/Json/ByteStreamSerializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 59c2d1b7e0..2da71ba68a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -30,7 +30,7 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kStringType: { - JsonByteStream* valAsByteStream = reinterpret_cast(outputValue); + JsonByteStream* valAsByteStream = static_cast(outputValue); JsonByteStream buffer; buffer.resize(inputValue.GetStringLength()); AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); @@ -57,9 +57,9 @@ namespace AZ using JsonSerializationResult::Outcomes; using JsonSerializationResult::Tasks; - const JsonByteStream& valAsByteStream = *reinterpret_cast(inputValue); + const JsonByteStream& valAsByteStream = *static_cast(inputValue); if (context.ShouldKeepDefaults() || !defaultValue || - (valAsByteStream != *reinterpret_cast(defaultValue))) + (valAsByteStream != *static_cast(defaultValue))) { outputValue.SetString( reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), From eb6d586a928d1c4e188c5ff388dda54b3d6f55fa Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 13 Apr 2021 15:29:35 +0100 Subject: [PATCH 012/122] Test file. Will be deleted --- Gems/Multiplayer/test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 Gems/Multiplayer/test.txt diff --git a/Gems/Multiplayer/test.txt b/Gems/Multiplayer/test.txt new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/Gems/Multiplayer/test.txt @@ -0,0 +1 @@ +test From b68d07ff8838d67c9386c3954eea09575777b856 Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 13 Apr 2021 16:17:42 +0100 Subject: [PATCH 013/122] Deleted temp test file --- Gems/Multiplayer/test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Gems/Multiplayer/test.txt diff --git a/Gems/Multiplayer/test.txt b/Gems/Multiplayer/test.txt deleted file mode 100644 index 9daeafb986..0000000000 --- a/Gems/Multiplayer/test.txt +++ /dev/null @@ -1 +0,0 @@ -test From 16ba08c9179aa88a1816506340a2591d5aee6622 Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 13 Apr 2021 11:03:27 -0700 Subject: [PATCH 014/122] Mac compile fixes, Fix imgui rendering, Introduce a new RHI::BufferBindFlag, Fix a crash in AsyncStreaming, Fix shader build errors --- .../UI/Outliner/EntityOutlinerWidget.cpp | 2 +- .../AzslShaderBuilderSystemComponent.cpp | 6 ++--- .../Common/Code/Source/ImGui/ImGuiPass.cpp | 4 +-- .../Atom/RHI.Reflect/BufferDescriptor.h | 26 +++++++++++-------- .../RHI.Reflect/ReflectSystemComponent.cpp | 3 ++- .../Code/Source/RHI/BufferMemoryAllocator.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/BufferPool.cpp | 3 ++- .../RHI.Builders/ShaderPlatformInterface.cpp | 13 +++++++--- .../Code/Source/RHI/AsyncUploadQueue.cpp | 2 +- .../RHI/Metal/Code/Source/RHI/Conversions.cpp | 5 ++++ .../RHI/Vulkan/Code/Source/RHI/BufferPool.cpp | 1 + .../RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 6 ++--- .../DefaultDynInputBufferPool.resourcepool | 4 +-- .../RPI.Public/DynamicDraw/DynamicBuffer.h | 2 +- .../Code/Source/RPI.Public/Buffer/Buffer.cpp | 6 +++-- .../Source/RPI.Public/Buffer/BufferSystem.cpp | 2 +- .../DynamicDraw/DynamicBufferAllocator.cpp | 1 + .../Source/RPI.Public/Pass/PassAttachment.cpp | 2 +- 18 files changed, 56 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index ad16423143..54d7dca292 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -807,7 +807,7 @@ namespace AzToolsFramework #ifdef Q_OS_MAC // "Alt+Return" translates to Option+Return on macOS m_actionToRenameSelection->setShortcut(tr("Alt+Return")); -#elseif Q_OS_WIN + #elif Q_OS_WIN m_actionToRenameSelection->setShortcut(tr("F2")); #endif m_actionToRenameSelection->setShortcutContext(Qt::WidgetWithChildrenShortcut); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index 0a85d463e5..528121fa56 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -102,7 +102,7 @@ namespace AZ // Register Shader Resource Group Layout Builder AssetBuilderSDK::AssetBuilderDesc srgLayoutBuilderDescriptor; srgLayoutBuilderDescriptor.m_name = "Shader Resource Group Layout Builder"; - srgLayoutBuilderDescriptor.m_version = 51; // SPEC-6065 + srgLayoutBuilderDescriptor.m_version = 52; // ATOM-15196 srgLayoutBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.azsl", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); srgLayoutBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.azsli", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); srgLayoutBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", SrgLayoutBuilder::MergedPartialSrgsExtension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); @@ -117,7 +117,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 96; // SPEC-6065 + shaderAssetBuilderDescriptor.m_version = 97; // ATOM-15196 // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); @@ -132,7 +132,7 @@ namespace AZ shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder"; // Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update // ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder". - shaderVariantAssetBuilderDescriptor.m_version = 17; // SPEC-6065 + shaderVariantAssetBuilderDescriptor.m_version = 18; // ATOM-15196 shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid(); shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index 2628eb9dc4..fef0e2af7b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -646,8 +646,8 @@ namespace AZ return 0; // Nothing to draw. } - auto vertexBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(totalVtxBufferSize); - auto indexBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(totalIdxBufferSize); + auto vertexBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(totalVtxBufferSize, RHI::Alignment::InputAssembly); + auto indexBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(totalIdxBufferSize, RHI::Alignment::InputAssembly); if (!vertexBuffer || !indexBuffer) { diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h index 4c0a490b70..f5ec9feebb 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h @@ -30,38 +30,42 @@ namespace AZ { None = 0, - /// Supports input assembly access through a IndexBufferView or StreamBufferView. + /// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are not updated often InputAssembly = AZ_BIT(0), - + + /// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are updated perf frame + DynamicInputAssembly = AZ_BIT(1), + /// Supports constant access through a ShaderResourceGroup. - Constant = AZ_BIT(1), + Constant = AZ_BIT(2), /// Supports read access through a ShaderResourceGroup. - ShaderRead = AZ_BIT(2), + ShaderRead = AZ_BIT(3), /// Supports write access through ShaderResourceGroup. - ShaderWrite = AZ_BIT(3), + ShaderWrite = AZ_BIT(4), /// Supports read-write access through a ShaderResourceGroup. ShaderReadWrite = ShaderRead | ShaderWrite, /// Supports read access for GPU copy operations. - CopyRead = AZ_BIT(4), + CopyRead = AZ_BIT(5), /// Supports write access for GPU copy operations. - CopyWrite = AZ_BIT(5), + CopyWrite = AZ_BIT(6), /// Supports predication access for conditional rendering. - Predication = AZ_BIT(6), + Predication = AZ_BIT(7), /// Supports indirect buffer access for indirect draw/dispatch. - Indirect = AZ_BIT(7), + Indirect = AZ_BIT(8), /// Supports ray tracing acceleration structure usage. - RayTracingAccelerationStructure = AZ_BIT(8), + RayTracingAccelerationStructure = AZ_BIT(9), /// Supports ray tracing shader table usage. - RayTracingShaderTable = AZ_BIT(9) + RayTracingShaderTable = AZ_BIT(10) + }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::RHI::BufferBindFlags); diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp index 841183d96a..09a9a8316d 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp @@ -54,7 +54,7 @@ namespace AZ if (SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2); + ->Version(3); } ReflectNamedEnums(context); @@ -264,6 +264,7 @@ namespace AZ serializeContext->Enum() ->Value("None", BufferBindFlags::None) ->Value("InputAssembly", BufferBindFlags::InputAssembly) + ->Value("DynamicInputAssembly", BufferBindFlags::DynamicInputAssembly) ->Value("Constant", BufferBindFlags::Constant) ->Value("CopyRead", BufferBindFlags::CopyRead) ->Value("CopyWrite", BufferBindFlags::CopyWrite) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferMemoryAllocator.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferMemoryAllocator.cpp index 50f4f736cc..b2c1a5fcaf 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferMemoryAllocator.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferMemoryAllocator.cpp @@ -39,7 +39,7 @@ namespace AZ // needs to be a multiple of elementsize as well as divisible by DX12::Alignment types. m_usePageAllocator = false; - if (!RHI::CheckBitsAny(descriptor.m_bindFlags, RHI::BufferBindFlags::ShaderWrite | RHI::BufferBindFlags::CopyWrite | RHI::BufferBindFlags::InputAssembly)) + if (!RHI::CheckBitsAny(descriptor.m_bindFlags, RHI::BufferBindFlags::ShaderWrite | RHI::BufferBindFlags::CopyWrite | RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { m_usePageAllocator = true; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp index 7134621d87..ca1c1ae56e 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp @@ -39,7 +39,8 @@ namespace AZ { m_device = &device; - if (RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::InputAssembly)) + if (RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::InputAssembly) || + RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::DynamicInputAssembly)) { m_readOnlyState |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER | D3D12_RESOURCE_STATE_INDEX_BUFFER; } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index b2219754aa..866c355dad 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -670,7 +670,13 @@ namespace AZ } else { - result &= AddExistingResourceEntry("texture", resourceStartPos, regId, argBufferStr); + bool isAdditionSuccessfull = AddExistingResourceEntry("texture", resourceStartPos, regId, argBufferStr); + if(!isAdditionSuccessfull) + { + //In metal depth textures use keyword depth2d/depth2d_array/depthcube/depthcube_array/depth2d_ms/depth2d_ms_array + isAdditionSuccessfull |= AddExistingResourceEntry("depth", resourceStartPos, regId, argBufferStr); + } + result &= isAdditionSuccessfull; } } return result; @@ -827,10 +833,11 @@ namespace AZ AZStd::string& argBufferStr) const { size_t prevEndOfLine = argBufferStr.rfind("\n", resourceStartPos); + size_t nextEndOfLine = argBufferStr.find("\n", resourceStartPos); size_t startOfEntryPos = argBufferStr.find(resourceStr, prevEndOfLine); - if(startOfEntryPos == AZStd::string::npos) + if(startOfEntryPos == AZStd::string::npos || startOfEntryPos > nextEndOfLine) { - AZ_Error(MetalShaderPlatformName, false, "Entry-> %s not found within Descriptor set %s", resourceStr, argBufferStr.c_str()); + AZ_Error(MetalShaderPlatformName, startOfEntryPos != AZStd::string::npos, "Entry-> %s not found within Descriptor set %s", resourceStr, argBufferStr.c_str()); return false; } else diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp index f831c3a9b0..891f9ea2f3 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp @@ -295,7 +295,7 @@ namespace AZ const RHI::Size sourceSize = RHI::Size(subresourceLayout.m_size.m_width, heightToCopy, 1); const RHI::Origin sourceOrigin = RHI::Origin(0, destHeight, depth); - CopyBufferToImage(framePacket, image, stagingRowPitch, stagingSlicePitch, + CopyBufferToImage(framePacket, image, stagingRowPitch, bytesCopied, curMip, arraySlice, sourceSize, sourceOrigin); framePacket->m_dataOffset += stagingSize; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index fbd50661cb..d6b2b2c906 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -210,6 +210,11 @@ namespace AZ { return GetCPUGPUMemoryMode(); } + + if (RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::DynamicInputAssembly)) + { + return MTLStorageModeShared; + } return GetCPUGPUMemoryMode(); } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferPool.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferPool.cpp index b9d146d84e..081469b39a 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferPool.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferPool.cpp @@ -107,6 +107,7 @@ namespace AZ bool forceUnique = RHI::CheckBitsAny( bufferDescriptor.m_bindFlags, RHI::BufferBindFlags::InputAssembly | + RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::RayTracingAccelerationStructure | RHI::BufferBindFlags::RayTracingShaderTable); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 6ac761a929..accc18b5ec 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -685,7 +685,7 @@ namespace AZ using BindFlags = RHI::BufferBindFlags; VkBufferUsageFlags usageFlags{ 0 }; - if (RHI::CheckBitsAny(bindFlags, BindFlags::InputAssembly)) + if (RHI::CheckBitsAny(bindFlags, BindFlags::InputAssembly | BindFlags::DynamicInputAssembly)) { usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT | @@ -932,7 +932,7 @@ namespace AZ VkPipelineStageFlags GetResourcePipelineStateFlags(const RHI::BufferBindFlags& bindFlags) { VkPipelineStageFlags stagesFlags = {}; - if (RHI::CheckBitsAny(bindFlags, RHI::BufferBindFlags::InputAssembly)) + if (RHI::CheckBitsAny(bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { stagesFlags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; } @@ -1042,7 +1042,7 @@ namespace AZ VkAccessFlags GetResourceAccessFlags(const RHI::BufferBindFlags& bindFlags) { VkAccessFlags accessFlags = {}; - if (RHI::CheckBitsAny(bindFlags, RHI::BufferBindFlags::InputAssembly)) + if (RHI::CheckBitsAny(bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { accessFlags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT; } diff --git a/Gems/Atom/RPI/Assets/ResourcePools/DefaultDynInputBufferPool.resourcepool b/Gems/Atom/RPI/Assets/ResourcePools/DefaultDynInputBufferPool.resourcepool index c80734cc38..0f2cb48580 100644 --- a/Gems/Atom/RPI/Assets/ResourcePools/DefaultDynInputBufferPool.resourcepool +++ b/Gems/Atom/RPI/Assets/ResourcePools/DefaultDynInputBufferPool.resourcepool @@ -8,6 +8,6 @@ "BudgetInBytes": 25165824, "BufferPoolHeapMemoryLevel": "Host", "BufferPoolhostMemoryAccess": "Write", - "BufferPoolBindFlags": "InputAssembly" + "BufferPoolBindFlags": "DynamicInputAssembly" } -} \ No newline at end of file +} diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h index 9b6caeeaef..a1bbcd8d78 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h @@ -36,7 +36,7 @@ namespace AZ //! buffer->Write(data, size); //! // Use the buffer view for DrawItem or etc. //! } - //! Note: DynamicBuffer should only be used for InputAssembly buffer or Constant buffer (not supported yet). + //! Note: DynamicBuffer should only be used for DynamicInputAssembly buffer or Constant buffer (not supported yet). class DynamicBuffer : public AZStd::intrusive_base { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp index 7bfcc588f1..cb2ad7d2ed 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp @@ -74,7 +74,8 @@ namespace AZ const RHI::BufferView* Buffer::GetBufferView() const { - if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly) + if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly || + m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::DynamicInputAssembly) { AZ_Assert(false, "Input assembly buffer doesn't need a regular buffer view, it requires a stream or index buffer view."); return nullptr; @@ -203,7 +204,8 @@ namespace AZ void Buffer::InitBufferView() { // Skip buffer view creation for input assembly buffers - if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly) + if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly || + m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::DynamicInputAssembly) { return; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp index 5f279ba533..fd2d029ddb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp @@ -105,7 +105,7 @@ namespace AZ bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; case CommonBufferPoolType::DynamicInputAssembly: - bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly; + bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly; bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host; bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicBufferAllocator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicBufferAllocator.cpp index e4599901a9..e79aa2e1bb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicBufferAllocator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicBufferAllocator.cpp @@ -63,6 +63,7 @@ namespace AZ // [GFX TODO][ATOM-13182] Add unit tests for DynamicBufferAllocator's Allocate function RHI::Ptr DynamicBufferAllocator::Allocate(uint32_t size, [[maybe_unused]]uint32_t alignment) { + size = RHI::AlignUp(size, alignment); uint32_t allocatePosition = 0; //m_ringBufferStartAddress can be null for Null back end diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp index d0262f7f83..a5082c5ee6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp @@ -174,7 +174,7 @@ namespace AZ } else if (GetAttachmentType() == RHI::AttachmentType::Buffer) { - bool isInputAssembly = RHI::CheckBitsAny(m_descriptor.m_buffer.m_bindFlags, RHI::BufferBindFlags::InputAssembly); + bool isInputAssembly = RHI::CheckBitsAny(m_descriptor.m_buffer.m_bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly); bool isConstant = RHI::CheckBitsAny(m_descriptor.m_buffer.m_bindFlags, RHI::BufferBindFlags::Constant); // Since InputAssembly and Constant cannot be inferred they are set manually. If those flags are set we don't want to add inferred flags on top as it may have a performance penalty From 0f841656e3a627c656233d58c1e231553dbf81f0 Mon Sep 17 00:00:00 2001 From: mbalfour Date: Tue, 13 Apr 2021 13:03:43 -0500 Subject: [PATCH 015/122] [LYN-2878] Attempt to fix deadlocks that occur when the Editor loads surface tag assets. I wasn't able to reproduce the deadlock, but from the reported callstack, the following lock inversion happens: * EditorSurfaceDataSystemComponent::OnCatalogLoaded locked the AssetCatalogRequestBus mutex by calling EnumerateAssets, and then locked m_assetMutex inside GetAsset->FindOrCreateAsset inside the enumerate callback. * Loading threads would lock m_assetMutex in AssetManager::ValidateAndRegisterAssetLoading, then lock the AssetCatalogRequestBus inside the Asset copy constructor when calling UpdateDebugStatus when the constructor calls SetData->UpgradeAssetInfo->UpdateAssetInfo->AssetCatalogRequestBus::GetAssetInfoById This should solve the lock inversion on both sides of the problem: * UpdateDebugStatus now takes in a const ref instead of a copy, so the copy constructor isn't called. * EditorSurfaceDataSystemComponent::OnCatalogLoaded is rewritten to call GetAsset outside of the enumeration call. As a bonus, this also removes the blocking load call. The rest of the code already supports asynchronous refreshes as the list assets are added / modified / removed, so this code was changed to leverage the asynchronous refreshes as well. --- .../AzCore/AzCore/Asset/AssetManager.cpp | 2 +- .../AzCore/AzCore/Asset/AssetManager.h | 2 +- .../EditorSurfaceDataSystemComponent.cpp | 26 ++++++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index 9d11eef6fc..87c5c6cb03 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -1117,7 +1117,7 @@ namespace AZ return asset; } - void AssetManager::UpdateDebugStatus(AZ::Data::Asset asset) + void AssetManager::UpdateDebugStatus(const AZ::Data::Asset& asset) { if(!m_debugAssetEvents) { diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.h b/Code/Framework/AzCore/AzCore/Asset/AssetManager.h index 7df2972a3d..81568d936e 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.h +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.h @@ -358,7 +358,7 @@ namespace AZ Asset GetAssetInternal(const AssetId& assetId, const AssetType& assetType, AssetLoadBehavior assetReferenceLoadBehavior, const AssetLoadParameters& loadParams = AssetLoadParameters{}, AssetInfo assetInfo = AssetInfo(), bool signalLoaded = false); - void UpdateDebugStatus(AZ::Data::Asset asset); + void UpdateDebugStatus(const AZ::Data::Asset& asset); /** * Gets a root asset and dependencies as individual async loads if necessary. diff --git a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp index 4f62550216..4dcc969434 100644 --- a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp @@ -145,24 +145,36 @@ namespace SurfaceData void EditorSurfaceDataSystemComponent::OnCatalogLoaded(const char* /*catalogFile*/) { - //automatically register all surface tag list assets + //automatically register all existing surface tag list assets at Editor startup - // First run through all the assets and trigger loads on them. + AZStd::vector surfaceTagAssetIds; + + // First run through all the assets and gather up the asset IDs for all surface tag list assets AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, - [this](const AZ::Data::AssetId assetId, const AZ::Data::AssetInfo& assetInfo) { + [&surfaceTagAssetIds](const AZ::Data::AssetId assetId, const AZ::Data::AssetInfo& assetInfo) { const auto assetType = azrtti_typeid(); if (assetInfo.m_assetType == assetType) { - m_surfaceTagNameAssets[assetId] = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::Default); + surfaceTagAssetIds.emplace_back(assetId); } }, nullptr); - // After all the loads are triggered, block to make sure they've all completed. - for (auto& asset : m_surfaceTagNameAssets) + // Next, trigger all the loads. This is done outside of EnumerateAssets to ensure that we don't have any deadlocks caused by + // lock inversion. If this thread locks AssetCatalogRequestBus mutex with EnumerateAssets, then locks m_assetMutex in + // AssetManager::FindOrCreateAsset, it's possible for those locks to get locked in reverse on a loading thread, causing a deadlock. + for (auto& assetId : surfaceTagAssetIds) { - asset.second.BlockUntilLoadComplete(); + m_surfaceTagNameAssets[assetId] = AZ::Data::AssetManager::Instance().GetAsset( + assetId, azrtti_typeid(), AZ::Data::AssetLoadBehavior::Default); + + // If any assets are still loading (which they likely will be), listen for the OnAssetReady event and refresh the Editor + // UI as each one finishes loading. + if (!m_surfaceTagNameAssets[assetId].IsReady()) + { + AZ::Data::AssetBus::MultiHandler::BusConnect(assetId); + } } } From f6e98d501443908973341eac9d02c646ae1d0b3e Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 13 Apr 2021 11:08:22 -0700 Subject: [PATCH 016/122] Fix viewport context menu hiding cursor and sometimes popping up repeatedly --- .../AzToolsFramework/Viewport/EditorContextMenu.cpp | 2 +- Code/Sandbox/Editor/LegacyViewportCameraController.cpp | 1 - Code/Sandbox/Editor/ViewportManipulatorController.cpp | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/EditorContextMenu.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/EditorContextMenu.cpp index 300820c2df..7fa9724d65 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/EditorContextMenu.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/EditorContextMenu.cpp @@ -65,7 +65,7 @@ namespace AzToolsFramework if (!contextMenu.m_menu->isEmpty()) { - contextMenu.m_menu->popup(QCursor::pos()); + contextMenu.m_menu->exec(QCursor::pos()); } } } diff --git a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp index 0c34706e24..44b722d222 100644 --- a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp +++ b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp @@ -342,7 +342,6 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra m_inRotateMode = true; } - shouldConsumeEvent = true; shouldCaptureCursor = true; } else if (state == InputChannel::State::Ended) diff --git a/Code/Sandbox/Editor/ViewportManipulatorController.cpp b/Code/Sandbox/Editor/ViewportManipulatorController.cpp index b45dc711ee..910d037670 100644 --- a/Code/Sandbox/Editor/ViewportManipulatorController.cpp +++ b/Code/Sandbox/Editor/ViewportManipulatorController.cpp @@ -21,8 +21,8 @@ #include -static const auto ManipulatorPriority = AzFramework::ViewportControllerPriority::Highest; -static const auto InteractionPriority = AzFramework::ViewportControllerPriority::High; +static const auto ManipulatorPriority = AzFramework::ViewportControllerPriority::High; +static const auto InteractionPriority = AzFramework::ViewportControllerPriority::Low; namespace SandboxEditor { From 78cadfd1d07c97e2b002aec258587fc1bb42021b Mon Sep 17 00:00:00 2001 From: shiranj Date: Tue, 13 Apr 2021 11:24:31 -0700 Subject: [PATCH 017/122] Convert daily metrics pipeline script to use BlueOcean API --- .../build/tools/jenkins_pipeline_metrics.py | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 scripts/build/tools/jenkins_pipeline_metrics.py diff --git a/scripts/build/tools/jenkins_pipeline_metrics.py b/scripts/build/tools/jenkins_pipeline_metrics.py new file mode 100644 index 0000000000..b84f55a8a0 --- /dev/null +++ b/scripts/build/tools/jenkins_pipeline_metrics.py @@ -0,0 +1,159 @@ +# +# 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. +# + +import os +import json +import requests +import traceback +import csv +import sys +from datetime import datetime, timezone +from requests.auth import HTTPBasicAuth + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(os.path.dirname(cur_dir), 'package')) +from util import * + + +class JenkinsAPIClient: + def __init__(self, jenkins_base_url, jenkins_username, jenkins_api_token): + self.jenkins_base_url = jenkins_base_url.rstrip('/') + self.jenkins_username = jenkins_username + self.jenkins_api_token = jenkins_api_token + self.blueocean_api_path = '/blue/rest/organizations/jenkins/pipelines' + + def get_request(self, url): + try: + response = requests.get(url, auth=HTTPBasicAuth(self.jenkins_username, self.jenkins_api_token)) + if response.ok: + return response.json() + except Exception: + traceback.print_exc() + error(f'Get request {url} failed, see exception for more details.') + + def get_builds(self, pipeline_name, branch_name=''): + url = self.jenkins_base_url + self.blueocean_api_path + f'/{pipeline_name}/{branch_name}/runs' + return self.get_request(url) + + def get_stages(self, build_number, pipeline_name, branch_name=''): + url = self.jenkins_base_url + self.blueocean_api_path + f'/{pipeline_name}/{branch_name}/runs/{build_number}/nodes' + return self.get_request(url) + + +def generate_build_metrics_csv(env, target_date): + output = [] + jenkins_client = JenkinsAPIClient(env['JENKINS_URL'], env['JENKINS_USERNAME'], env['JENKINS_API_TOKEN']) + pipeline_name = env['PIPELINE_NAME'] + builds = jenkins_client.get_builds(pipeline_name) + days_to_collect = env['DAYS_TO_COLLECT'] + for build in builds: + build_time = datetime.strptime(build['startTime'], '%Y-%m-%dT%H:%M:%S.%f%z') + # Convert startTime to local timezone to compare, because Jenkins server may use a different timezone. + build_date = build_time.astimezone().date() + date_diff = target_date - build_date + # Only collect build result of past {days_to_collect} days. + if date_diff.days > int(days_to_collect): + break + stages = jenkins_client.get_stages(build['id'], pipeline_name) + stage_dict = {} + parallel_stages = [] + # Build stage_dict and find all parallel stages + for stage in stages: + stage_dict[stage['id']] = stage + if stage['type'] == 'PARALLEL': + parallel_stages.append(stage) + # Calculate build metrics grouped by parallel stage + def stage_duration_sum(stage): + duration_sum = stage['durationInMillis'] + for edge in stage['edges']: + downstream_stage = stage_dict[edge['id']] + duration_sum += stage_duration_sum(downstream_stage) + return duration_sum + for parallel_stage in parallel_stages: + try: + build_info = { + 'job_name': parallel_stage['displayName'], + 'view_name': env['BRANCH_NAME'] + } + # UTC datetime is required by BI team + build_info['build_time'] = datetime.fromtimestamp(build_time.timestamp(), timezone.utc) + build_info['build_number'] = build['id'] + build_info['job_duration'] = stage_duration_sum(parallel_stage) / 1000 / 60 + build_info['status'] = parallel_stage['result'] + build_info['clean_build'] = 'True' + print(build_info) + output.append(build_info) + except Exception: + traceback.print_exc() + + if output: + with open('spectra_build_metrics.csv', 'w', newline='') as csvfile: + fieldnames = list(output[0].keys()) + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + writer.writerows(output) + + +def generate_build_metrics_manifest(csv_s3_location): + data = { + "entries": [ + { + "url": csv_s3_location + } + ] + } + with open('spectra_build_metrics.manifest', 'w') as manifest: + json.dump(data, manifest) + + +def upload_files_to_s3(env, formatted_date): + csv_s3_prefix = f"{env['CSV_PREFIX'].rstrip('/')}/{formatted_date}" + manifest_s3_prefix = f"{env['MANIFEST_PREFIX'].rstrip('/')}/{formatted_date}" + upload_to_s3_script_path = os.path.join(cur_dir, 'upload_to_s3.py') + engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + if sys.platform == 'win32': + python = os.path.join(engine_root, 'python', 'python.cmd') + else: + python = os.path.join(engine_root, 'python', 'python.sh') + upload_csv_cmd = [python, upload_to_s3_script_path, '--base_dir', cur_dir, '--file_regex', env['CSV_REGEX'], '--bucket', env['BUCKET'], '--key_prefix', csv_s3_prefix] + execute_system_call(upload_csv_cmd) + upload_manifest_cmd = [python, upload_to_s3_script_path, '--base_dir', cur_dir, '--file_regex', env['MANIFEST_REGEX'], '--bucket', env['BUCKET'], '--key_prefix', manifest_s3_prefix] + execute_system_call(upload_manifest_cmd) + + +def get_required_env(env, keys): + success = True + for key in keys: + try: + env[key] = os.environ[key].strip() + except KeyError: + error(f'{key} is not set in environment variable') + success = False + return success + + +def main(): + env = {} + required_env_list = ['JENKINS_URL', 'PIPELINE_NAME', 'BRANCH_NAME', 'JENKINS_USERNAME', 'JENKINS_API_TOKEN', 'BUCKET', 'CSV_REGEX', 'CSV_PREFIX', 'MANIFEST_REGEX', 'MANIFEST_PREFIX', 'DAYS_TO_COLLECT'] + if not get_required_env(env, required_env_list): + error('Required environment variable is not set, see log for more details.') + + target_date = datetime.today().date() + formatted_date = f'{target_date.year}/{target_date:%m}/{target_date:%d}' + csv_s3_location = f"s3://{env['BUCKET']}/{env['CSV_PREFIX'].rstrip('/')}/{formatted_date}/spectra_build_metrics.csv" + + generate_build_metrics_csv(env, target_date) + generate_build_metrics_manifest(csv_s3_location) + upload_files_to_s3(env, formatted_date) + + +if __name__ == "__main__": + main() From f3d0666a632760b68858391698f8253b2072249b Mon Sep 17 00:00:00 2001 From: shiranj Date: Tue, 13 Apr 2021 11:52:42 -0700 Subject: [PATCH 018/122] Add retry to get request --- .../build/tools/jenkins_pipeline_metrics.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/build/tools/jenkins_pipeline_metrics.py b/scripts/build/tools/jenkins_pipeline_metrics.py index b84f55a8a0..c40cd33d18 100644 --- a/scripts/build/tools/jenkins_pipeline_metrics.py +++ b/scripts/build/tools/jenkins_pipeline_metrics.py @@ -30,22 +30,24 @@ class JenkinsAPIClient: self.jenkins_api_token = jenkins_api_token self.blueocean_api_path = '/blue/rest/organizations/jenkins/pipelines' - def get_request(self, url): - try: - response = requests.get(url, auth=HTTPBasicAuth(self.jenkins_username, self.jenkins_api_token)) - if response.ok: - return response.json() - except Exception: - traceback.print_exc() - error(f'Get request {url} failed, see exception for more details.') + def get_request(self, url, retry=1): + for i in range(retry): + try: + response = requests.get(url, auth=HTTPBasicAuth(self.jenkins_username, self.jenkins_api_token)) + if response.ok: + return response.json() + except Exception: + traceback.print_exc() + print(f'WARN: Get request {url} failed, retying....') + error(f'Get request {url} failed, see exception for more details.') def get_builds(self, pipeline_name, branch_name=''): url = self.jenkins_base_url + self.blueocean_api_path + f'/{pipeline_name}/{branch_name}/runs' - return self.get_request(url) + return self.get_request(url, retry=3) def get_stages(self, build_number, pipeline_name, branch_name=''): url = self.jenkins_base_url + self.blueocean_api_path + f'/{pipeline_name}/{branch_name}/runs/{build_number}/nodes' - return self.get_request(url) + return self.get_request(url, retry=3) def generate_build_metrics_csv(env, target_date): From d399d0d8f16b599889e1a1213e13ad8f3ecc1ed0 Mon Sep 17 00:00:00 2001 From: shiranj Date: Tue, 13 Apr 2021 12:15:51 -0700 Subject: [PATCH 019/122] Move jenkins_pipeline_metrics.py to ascripts/build/Jenkins/tools --- scripts/build/{ => Jenkins}/tools/jenkins_pipeline_metrics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename scripts/build/{ => Jenkins}/tools/jenkins_pipeline_metrics.py (97%) diff --git a/scripts/build/tools/jenkins_pipeline_metrics.py b/scripts/build/Jenkins/tools/jenkins_pipeline_metrics.py similarity index 97% rename from scripts/build/tools/jenkins_pipeline_metrics.py rename to scripts/build/Jenkins/tools/jenkins_pipeline_metrics.py index c40cd33d18..80ab3fc60f 100644 --- a/scripts/build/tools/jenkins_pipeline_metrics.py +++ b/scripts/build/Jenkins/tools/jenkins_pipeline_metrics.py @@ -19,7 +19,7 @@ from datetime import datetime, timezone from requests.auth import HTTPBasicAuth cur_dir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(os.path.dirname(cur_dir), 'package')) +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(cur_dir)), 'package')) from util import * @@ -120,7 +120,7 @@ def upload_files_to_s3(env, formatted_date): csv_s3_prefix = f"{env['CSV_PREFIX'].rstrip('/')}/{formatted_date}" manifest_s3_prefix = f"{env['MANIFEST_PREFIX'].rstrip('/')}/{formatted_date}" upload_to_s3_script_path = os.path.join(cur_dir, 'upload_to_s3.py') - engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) if sys.platform == 'win32': python = os.path.join(engine_root, 'python', 'python.cmd') else: From d7f10e9d6021e824f54bbace6dbaff8e368766b1 Mon Sep 17 00:00:00 2001 From: mbalfour Date: Tue, 13 Apr 2021 13:03:43 -0500 Subject: [PATCH 020/122] [LYN-2878] Attempt to fix deadlocks that occur when the Editor loads surface tag assets. I wasn't able to reproduce the deadlock, but from the reported callstack, the following lock inversion happens: * EditorSurfaceDataSystemComponent::OnCatalogLoaded locked the AssetCatalogRequestBus mutex by calling EnumerateAssets, and then locked m_assetMutex inside GetAsset->FindOrCreateAsset inside the enumerate callback. * Loading threads would lock m_assetMutex in AssetManager::ValidateAndRegisterAssetLoading, then lock the AssetCatalogRequestBus inside the Asset copy constructor when calling UpdateDebugStatus when the constructor calls SetData->UpgradeAssetInfo->UpdateAssetInfo->AssetCatalogRequestBus::GetAssetInfoById This should solve the lock inversion on both sides of the problem: * UpdateDebugStatus now takes in a const ref instead of a copy, so the copy constructor isn't called. * EditorSurfaceDataSystemComponent::OnCatalogLoaded is rewritten to call GetAsset outside of the enumeration call. As a bonus, this also removes the blocking load call. The rest of the code already supports asynchronous refreshes as the list assets are added / modified / removed, so this code was changed to leverage the asynchronous refreshes as well. --- .../AzCore/AzCore/Asset/AssetManager.cpp | 2 +- .../AzCore/AzCore/Asset/AssetManager.h | 2 +- .../EditorSurfaceDataSystemComponent.cpp | 26 ++++++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index c2d0191fd6..214443142b 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -1117,7 +1117,7 @@ namespace AZ return asset; } - void AssetManager::UpdateDebugStatus(AZ::Data::Asset asset) + void AssetManager::UpdateDebugStatus(const AZ::Data::Asset& asset) { if(!m_debugAssetEvents) { diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.h b/Code/Framework/AzCore/AzCore/Asset/AssetManager.h index 7df2972a3d..81568d936e 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.h +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.h @@ -358,7 +358,7 @@ namespace AZ Asset GetAssetInternal(const AssetId& assetId, const AssetType& assetType, AssetLoadBehavior assetReferenceLoadBehavior, const AssetLoadParameters& loadParams = AssetLoadParameters{}, AssetInfo assetInfo = AssetInfo(), bool signalLoaded = false); - void UpdateDebugStatus(AZ::Data::Asset asset); + void UpdateDebugStatus(const AZ::Data::Asset& asset); /** * Gets a root asset and dependencies as individual async loads if necessary. diff --git a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp index 4f62550216..4dcc969434 100644 --- a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp @@ -145,24 +145,36 @@ namespace SurfaceData void EditorSurfaceDataSystemComponent::OnCatalogLoaded(const char* /*catalogFile*/) { - //automatically register all surface tag list assets + //automatically register all existing surface tag list assets at Editor startup - // First run through all the assets and trigger loads on them. + AZStd::vector surfaceTagAssetIds; + + // First run through all the assets and gather up the asset IDs for all surface tag list assets AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, - [this](const AZ::Data::AssetId assetId, const AZ::Data::AssetInfo& assetInfo) { + [&surfaceTagAssetIds](const AZ::Data::AssetId assetId, const AZ::Data::AssetInfo& assetInfo) { const auto assetType = azrtti_typeid(); if (assetInfo.m_assetType == assetType) { - m_surfaceTagNameAssets[assetId] = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::Default); + surfaceTagAssetIds.emplace_back(assetId); } }, nullptr); - // After all the loads are triggered, block to make sure they've all completed. - for (auto& asset : m_surfaceTagNameAssets) + // Next, trigger all the loads. This is done outside of EnumerateAssets to ensure that we don't have any deadlocks caused by + // lock inversion. If this thread locks AssetCatalogRequestBus mutex with EnumerateAssets, then locks m_assetMutex in + // AssetManager::FindOrCreateAsset, it's possible for those locks to get locked in reverse on a loading thread, causing a deadlock. + for (auto& assetId : surfaceTagAssetIds) { - asset.second.BlockUntilLoadComplete(); + m_surfaceTagNameAssets[assetId] = AZ::Data::AssetManager::Instance().GetAsset( + assetId, azrtti_typeid(), AZ::Data::AssetLoadBehavior::Default); + + // If any assets are still loading (which they likely will be), listen for the OnAssetReady event and refresh the Editor + // UI as each one finishes loading. + if (!m_surfaceTagNameAssets[assetId].IsReady()) + { + AZ::Data::AssetBus::MultiHandler::BusConnect(assetId); + } } } From e6c12499f73799bd96e3869418d7b3e51c7fdb87 Mon Sep 17 00:00:00 2001 From: alexpete Date: Tue, 13 Apr 2021 14:05:48 -0700 Subject: [PATCH 021/122] Added raytracingscenesrg.srgi to the default project template and AutomatedTesting project. Added assert to check for successful load of the raytracingscenesrg asset. --- .../ShaderLib/raytracingscenesrg.srgi | 28 +++++++++++++++++++ .../RayTracing/RayTracingFeatureProcessor.cpp | 1 + .../ShaderLib/raytracingscenesrg.srgi | 28 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 AutomatedTesting/ShaderLib/raytracingscenesrg.srgi create mode 100644 Templates/DefaultProject/Template/ShaderLib/raytracingscenesrg.srgi diff --git a/AutomatedTesting/ShaderLib/raytracingscenesrg.srgi b/AutomatedTesting/ShaderLib/raytracingscenesrg.srgi new file mode 100644 index 0000000000..ac1d663bb8 --- /dev/null +++ b/AutomatedTesting/ShaderLib/raytracingscenesrg.srgi @@ -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 + +// Please read README.md for an explanation on why scenesrg.srgi and viewsrg.srgi are +// located in this folder (And how you can optionally customize your own scenesrg.srgi +// and viewsrg.srgi in your game project). + +#include + +partial ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene +{ +/* Intentionally Empty. Helps define the SrgSemantic for RayTracingSceneSrg once.*/ +}; + +#define AZ_COLLECTING_PARTIAL_SRGS +#include +#undef AZ_COLLECTING_PARTIAL_SRGS diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 68de2b87bb..d4d71b5741 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -67,6 +67,7 @@ namespace AZ // load the RayTracingSceneSrg asset Data::Asset rayTracingSceneSrgAsset = RPI::AssetUtils::LoadAssetByProductPath("shaderlib/raytracingscenesrg_raytracingscenesrg.azsrg", RPI::AssetUtils::TraceLevel::Error); + AZ_Assert(rayTracingSceneSrgAsset.IsReady(), "Failed to load RayTracingSceneSrg asset"); m_rayTracingSceneSrg = RPI::ShaderResourceGroup::Create(rayTracingSceneSrgAsset); } diff --git a/Templates/DefaultProject/Template/ShaderLib/raytracingscenesrg.srgi b/Templates/DefaultProject/Template/ShaderLib/raytracingscenesrg.srgi new file mode 100644 index 0000000000..ac1d663bb8 --- /dev/null +++ b/Templates/DefaultProject/Template/ShaderLib/raytracingscenesrg.srgi @@ -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 + +// Please read README.md for an explanation on why scenesrg.srgi and viewsrg.srgi are +// located in this folder (And how you can optionally customize your own scenesrg.srgi +// and viewsrg.srgi in your game project). + +#include + +partial ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene +{ +/* Intentionally Empty. Helps define the SrgSemantic for RayTracingSceneSrg once.*/ +}; + +#define AZ_COLLECTING_PARTIAL_SRGS +#include +#undef AZ_COLLECTING_PARTIAL_SRGS From a532cc1217b2f67a025bae3205d16102ba4909d2 Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 13 Apr 2021 14:27:11 -0700 Subject: [PATCH 022/122] Compile fix --- .../AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 54d7dca292..f9c9431039 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -804,10 +804,10 @@ namespace AzToolsFramework addAction(m_actionToDeleteSelectionAndDescendants); m_actionToRenameSelection = new QAction(tr("Rename"), this); - #ifdef Q_OS_MAC + #if defined(Q_OS_MAC) // "Alt+Return" translates to Option+Return on macOS m_actionToRenameSelection->setShortcut(tr("Alt+Return")); - #elif Q_OS_WIN + #elif defined(Q_OS_WIN) m_actionToRenameSelection->setShortcut(tr("F2")); #endif m_actionToRenameSelection->setShortcutContext(Qt::WidgetWithChildrenShortcut); From 5050de260472c4db69e440008111824f64a0d565 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Tue, 13 Apr 2021 15:05:05 -0700 Subject: [PATCH 023/122] Adding "Open Material Editor" action to Material Component slot context menu --- .../Code/Source/Material/EditorMaterialComponentSlot.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 1a41594b5a..5c22a0974e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -172,6 +172,10 @@ namespace AZ { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, sourcePath); } + else + { + EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); + } } void EditorMaterialComponentSlot::Clear() @@ -273,6 +277,8 @@ namespace AZ QAction* action = nullptr; + menu.addAction("Open Material Editor", [this]() { OpenMaterialEditor(); }); + action = menu.addAction("Clear", [this]() { Clear(); }); action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); From 8469c9ca0a0b63202d526a6f8ba8d19d50381239 Mon Sep 17 00:00:00 2001 From: alexpete Date: Tue, 13 Apr 2021 17:18:57 -0700 Subject: [PATCH 024/122] Integrating github/staging through commit 5f214be --- .../AssetProcessorGamePlatformConfig.setreg | 14 + .../ap_external_project_setup_fixture.py | 2 +- .../ap_fast_scan_setting_backup_fixture.py | 4 +- .../ap_fixtures/ap_idle_fixture.py | 2 +- .../ap_missing_dependency_fixture.py | 2 +- .../ap_fixtures/ap_setup_fixture.py | 2 +- .../ap_fixtures/asset_processor_fixture.py | 4 +- .../bundler_batch_setup_fixture.py | 4 +- .../ap_fixtures/clear_moveoutput_fixture.py | 2 +- .../asset_builder_tests.py | 4 +- .../asset_bundler_batch_tests.py | 4 +- .../asset_processor_batch_dependency_tests.py | 4 +- ...asset_processor_batch_dependency_tests2.py | 4 +- .../asset_processor_batch_tests.py | 6 +- .../asset_processor_batch_tests_2.py | 8 +- .../asset_processor_gui_tests.py | 6 +- .../asset_processor_gui_tests_2.py | 4 +- .../asset_relocator_tests.py | 6 +- .../missing_dependency_tests.py | 6 +- .../auxiliary_content_tests.py | 2 +- .../assetpipeline/fbx_tests/fbx_tests.py | 6 +- .../asset_database_utils.py | 2 +- .../automatedtesting_shared/asset_utils.py | 2 +- .../automatedtesting_shared/base.py | 2 +- .../editor_entity_utils.py | 2 +- .../editor_test_helper.py | 2 +- .../hydra_editor_utils.py | 6 +- .../platform_setting.py | 2 +- .../AssetBrowser_SearchFiltering.py | 2 +- .../AssetBrowser_TreeNavigation.py | 2 +- .../ComponentCRUD_Add_Delete_Components.py | 2 +- .../InputBindings_Add_Remove_Input_Events.py | 2 +- ...rides_InstancesPlantAtSpecifiedAltitude.py | 2 +- ...ample_InstancesPlantAtSpecifiedAltitude.py | 2 +- ...binedDescriptorsExpressInConfiguredArea.py | 2 +- ...tSelector_InstancesExpressBasedOnWeight.py | 2 +- ...errides_InstancesPlantAtSpecifiedRadius.py | 2 +- ...nFilter_InstancesPlantAtSpecifiedRadius.py | 2 +- ...ynamicSliceInstanceSpawner_Embedded_E2E.py | 2 +- ...ynamicSliceInstanceSpawner_External_E2E.py | 2 +- ...anceSpawnerPriority_LayerAndSubPriority.py | 2 +- .../EditorScripts/LayerBlender_E2E_Editor.py | 2 +- ...locker_InstancesBlockedInConfiguredArea.py | 2 +- ...faceTagEmitter_DependentOnMeshComponent.py | 2 +- ...mitter_SurfaceTagsAddRemoveSuccessfully.py | 2 +- ...PositionModifier_AutoSnapToSurfaceWorks.py | 2 +- ...rrides_InstancesPlantAtSpecifiedOffsets.py | 2 +- ...ionFilter_InstancesPlantInAssignedShape.py | 2 +- ...AndOverrides_InstancesPlantOnValidSlope.py | 2 +- ...tipleDescriptorOverridesPlantAsExpected.py | 2 +- ...ClearingPinnedEntitySetsPreviewToOrigin.py | 2 +- ...GradientReferencesAddRemoveSuccessfully.py | 2 +- ...mitter_SurfaceTagsAddRemoveSuccessfully.py | 2 +- ...ponentIncompatibleWithExpectedGradients.py | 2 +- ...sform_ComponentIncompatibleWithSpawners.py | 2 +- ..._FrequencyZoomCanBeSetBeyondSliderRange.py | 2 +- ...ient_ProcessedImageAssignedSuccessfully.py | 2 +- .../C12712452_ScriptCanvas_CollisionEvents.py | 2 +- ...54_ScriptCanvas_OverlapNodeVerification.py | 2 +- ...2455_ScriptCanvas_ShapeCastVerification.py | 2 +- ...eRegion_DirectionHasNoAffectOnMagnitude.py | 2 +- ...580_ForceRegion_SplineModifiedTransform.py | 2 +- ...12905527_ForceRegion_MagnitudeDeviation.py | 2 +- ...5528_ForceRegion_WithNonTriggerCollider.py | 2 +- .../C13351703_COM_NotIncludeTriggerShapes.py | 2 +- .../physics/C13895144_Ragdoll_ChangeLevel.py | 2 +- .../C14195074_ScriptCanvas_PostUpdateEvent.py | 2 +- .../C14654882_Ragdoll_ragdollAPTest.py | 2 +- .../C14861500_DefaultSetting_ColliderShape.py | 4 +- ...01_PhysXCollider_RenderMeshAutoAssigned.py | 2 +- ...4861502_PhysXCollider_AssetAutoAssigned.py | 4 +- ...C14861504_RenderMeshAsset_WithNoPxAsset.py | 4 +- .../C14902097_ScriptCanvas_PreUpdateEvent.py | 2 +- ...14902098_ScriptCanvas_PostPhysicsUpdate.py | 2 +- .../C14976307_Gravity_SetGravityWorks.py | 2 +- ...criptCanvas_SetKinematicTargetTransform.py | 2 +- ...DefaultLibraryUpdatedAcrossLevels_after.py | 2 +- ...efaultLibraryUpdatedAcrossLevels_before.py | 2 +- ...735_Materials_DefaultLibraryConsistency.py | 2 +- ...096740_Material_LibraryUpdatedCorrectly.py | 4 +- .../physics/C15308217_NoCrash_LevelSwitch.py | 2 +- ...21_Material_ComponentsInSyncWithLibrary.py | 2 +- ...935_Material_LibraryUpdatedAcrossLevels.py | 2 +- ...al_AddModifyDeleteOnCharacterController.py | 2 +- ...5879_ForceRegion_HighLinearDampingForce.py | 2 +- .../C17411467_AddPhysxRagdollComponent.py | 2 +- ...18243580_Joints_Fixed2BodiesConstrained.py | 2 +- .../C18243581_Joints_FixedBreakable.py | 2 +- ...8243582_Joints_FixedLeadFollowerCollide.py | 2 +- ...18243583_Joints_Hinge2BodiesConstrained.py | 2 +- ...43584_Joints_HingeSoftLimitsConstrained.py | 2 +- ...8243585_Joints_HingeNoLimitsConstrained.py | 2 +- ...8243586_Joints_HingeLeadFollowerCollide.py | 2 +- .../C18243587_Joints_HingeBreakable.py | 2 +- ...C18243588_Joints_Ball2BodiesConstrained.py | 2 +- ...243589_Joints_BallSoftLimitsConstrained.py | 2 +- ...18243590_Joints_BallNoLimitsConstrained.py | 2 +- ...18243591_Joints_BallLeadFollowerCollide.py | 2 +- .../physics/C18243592_Joints_BallBreakable.py | 2 +- ...C18243593_Joints_GlobalFrameConstrained.py | 2 +- ...977601_Material_FrictionCombinePriority.py | 2 +- ...526_Material_RestitutionCombinePriority.py | 2 +- .../C19536274_GetCollisionName_PrintsName.py | 2 +- ...19536277_GetCollisionName_PrintsNothing.py | 2 +- ...78018_ShapeColliderWithNoShapeComponent.py | 4 +- .../C19578021_ShapeCollider_CanBeAdded.py | 4 +- ...19723164_ShapeColliders_WontCrashEditor.py | 4 +- .../C3510642_Terrain_NotCollideWithTerrain.py | 2 +- .../C3510644_Collider_CollisionGroups.py | 2 +- ...044455_Material_libraryChangesInstantly.py | 2 +- .../C4044456_Material_FrictionCombine.py | 2 +- .../C4044457_Material_RestitutionCombine.py | 2 +- .../C4044459_Material_DynamicFriction.py | 2 +- .../C4044460_Material_StaticFriction.py | 2 +- .../physics/C4044461_Material_Restitution.py | 2 +- ...044694_Material_EmptyLibraryUsesDefault.py | 2 +- ...695_PhysXCollider_AddMultipleSurfaceFbx.py | 2 +- ...4697_Material_PerfaceMaterialValidation.py | 2 +- ...8315_Material_AddModifyDeleteOnCollider.py | 2 +- ...577_Materials_MaterialAssignedToTerrain.py | 2 +- ...25579_Material_AddModifyDeleteOnTerrain.py | 2 +- .../C4925580_Material_RagdollBonesMaterial.py | 2 +- ..._Material_AddModifyDeleteOnRagdollBones.py | 2 +- ...4976194_RigidBody_PhysXComponentIsValid.py | 2 +- ...76195_RigidBodies_InitialLinearVelocity.py | 2 +- ...6197_RigidBodies_InitialAngularVelocity.py | 2 +- .../C4976201_RigidBody_MassIsAssigned.py | 2 +- ...igidBody_StopsWhenBelowKineticThreshold.py | 2 +- .../C4976204_Verify_Start_Asleep_Condition.py | 2 +- ...976206_RigidBodies_GravityEnabledActive.py | 2 +- ...6207_PhysXRigidBodies_KinematicBehavior.py | 2 +- .../physics/C4976209_RigidBody_ComputesCOM.py | 2 +- .../physics/C4976210_COM_ManualSetting.py | 2 +- .../physics/C4976227_Collider_NewGroup.py | 2 +- .../C4976236_AddPhysxColliderComponent.py | 2 +- ...on_SameCollisionlayerSameCollisiongroup.py | 2 +- ...n_SameCollisionGroupDiffCollisionLayers.py | 2 +- ...44_Collider_SameGroupSameLayerCollision.py | 2 +- ...976245_PhysXCollider_CollisionLayerTest.py | 2 +- ...982593_PhysXCollider_CollisionLayerTest.py | 2 +- ...82595_Collider_TriggerDisablesCollision.py | 2 +- .../C4982797_Collider_ColliderOffset.py | 2 +- ...4982798_Collider_ColliderRotationOffset.py | 2 +- ...982800_PhysXColliderShape_CanBeSelected.py | 4 +- ...982801_PhysXColliderShape_CanBeSelected.py | 4 +- ...982802_PhysXColliderShape_CanBeSelected.py | 4 +- .../physics/C4982803_Enable_PxMesh_Option.py | 4 +- ...5340400_RigidBody_ManualMomentOfInertia.py | 2 +- ...ysxterrain_AddPhysxterrainNoEditorCrash.py | 2 +- ..._MultipleTerrains_CheckWarningInConsole.py | 2 +- ...89528_Terrain_MultipleTerrainComponents.py | 2 +- ..._Verify_Terrain_RigidBody_Collider_Mesh.py | 2 +- ...31_Warning_TerrainSliceTerrainComponent.py | 2 +- ...932040_ForceRegion_CubeExertsWorldForce.py | 2 +- ...orceRegion_LocalSpaceForceOnRigidBodies.py | 2 +- ...C5932042_PhysXForceRegion_LinearDamping.py | 2 +- ...32044_ForceRegion_PointForceOnRigidBody.py | 2 +- .../physics/C5932045_ForceRegion_Spline.py | 2 +- ...760_PhysXForceRegion_PointForceExertion.py | 2 +- ...1_ForceRegion_PhysAssetExertsPointForce.py | 2 +- ...0_ForceRegion_ForceRegionCombinesForces.py | 2 +- ...5968760_ForceRegion_CheckNetForceChange.py | 2 +- ...032082_Terrain_MultipleResolutionsValid.py | 2 +- ...90546_ForceRegion_SliceFileInstantiates.py | 2 +- ...547_ForceRegion_ParentChildForceRegions.py | 2 +- ...550_ForceRegion_WorldSpaceForceNegative.py | 2 +- ...551_ForceRegion_LocalSpaceForceNegative.py | 2 +- ...90552_ForceRegion_LinearDampingNegative.py | 2 +- ...orceRegion_SimpleDragForceOnRigidBodies.py | 2 +- ...C6090554_ForceRegion_PointForceNegative.py | 2 +- ...5_ForceRegion_SplineFollowOnRigidBodies.py | 2 +- ...6131473_StaticSlice_OnDynamicSliceSpawn.py | 2 +- .../C6224408_ScriptCanvas_EntitySpawn.py | 2 +- .../C6274125_ScriptCanvas_TriggerEvents.py | 2 +- .../C6321601_Force_HighValuesDirectionAxes.py | 2 +- .../physics/Physmaterial_Editor.py | 4 +- .../physics/UtilTest_Physmaterial_Editor.py | 2 +- .../Gem/PythonTests/scripting/Docking_Pane.py | 4 +- .../scripting/Opening_Closing_Pane.py | 4 +- .../PythonTests/scripting/Resizing_Pane.py | 4 +- .../benchmark/asset_load_benchmark_test.py | 2 +- CMakeLists.txt | 25 +- Code/CryEngine/Cry3DEngine/3dEngine.cpp | 4 +- Code/CryEngine/Cry3DEngine/CZBufferCuller.cpp | 6 +- Code/CryEngine/Cry3DEngine/CZBufferCuller.h | 20 +- .../CryEngine/Cry3DEngine/MaterialHelpers.cpp | 1 - Code/CryEngine/Cry3DEngine/TimeOfDay.cpp | 2 +- Code/CryEngine/CryCommon/CryAssert_impl.h | 2 +- .../CryCommon/EngineSettingsBackendWin32.cpp | 4 +- Code/CryEngine/CryCommon/HMDBus.h | 2 +- Code/CryEngine/CryCommon/ISystem.h | 2 +- Code/CryEngine/CryFont/FFont.cpp | 5 +- Code/CryEngine/CrySystem/CrashHandler.rc | 2 +- Code/CryEngine/CrySystem/CryDLMalloc.c | 16 + Code/CryEngine/CrySystem/IDebugCallStack.cpp | 2 +- Code/CryEngine/CrySystem/MemoryManager.cpp | 20 +- Code/CryEngine/CrySystem/System.cpp | 12 +- Code/CryEngine/CrySystem/SystemInit.cpp | 10 +- Code/CryEngine/CrySystem/SystemRender.cpp | 2 +- Code/CryEngine/CrySystem/SystemWin32.cpp | 2 +- Code/CryEngine/CrySystem/XML/ReadXMLSink.cpp | 24 +- .../RenderDll/Common/RenderThread.cpp | 2 + .../CryEngine/RenderDll/Common/RendererDefs.h | 2 +- .../RenderDll/Common/Shaders/ShaderCache.cpp | 3 - .../Common/Shaders/ShaderTemplate.cpp | 1 - .../RenderDll/XRenderD3D9/CryRenderD3D11.rc | 2 +- .../RenderDll/XRenderD3D9/CryRenderGL.rc | 2 +- .../RenderDll/XRenderD3D9/D3DFXPipeline.cpp | 1 - .../DXGL/Implementation/GLContext.cpp | 4 +- .../DXGL/Implementation/GLDevice.cpp | 12 +- .../RenderDll/XRenderD3D9/DriverD3D.cpp | 10 +- .../RenderDll/XRenderD3D9/GPUTimer.cpp | 5 +- .../XRenderD3D9/MultiLayerAlphaBlendPass.cpp | 2 +- .../RenderDll/XRenderNULL/CryRenderNULL.rc | 2 +- .../AzCore/AzCore/Android/APKFileHandler.cpp | 19 +- .../Framework/AzCore/AzCore/Android/Utils.cpp | 23 +- Code/Framework/AzCore/AzCore/Android/Utils.h | 5 +- .../AzCore/Asset/AssetJsonSerializer.cpp | 5 +- .../AzCore/AzCore/Component/Component.h | 6 +- .../AzCore/Component/ComponentApplication.cpp | 107 +- .../AzCore/Component/ComponentApplication.h | 7 +- .../AzCore/AzCore/Component/Entity.h | 2 +- Code/Framework/AzCore/AzCore/EBus/BusImpl.h | 2 +- Code/Framework/AzCore/AzCore/EBus/EBus.h | 10 +- Code/Framework/AzCore/AzCore/IO/Path/Path.h | 22 +- .../AzCore/AzCore/IO/Streamer/BlockCache.cpp | 17 +- .../AzCore/IO/Streamer/DedicatedCache.cpp | 17 +- .../AzCore/IO/Streamer/StorageDrive.cpp | 25 +- .../AzCore/AzCore/Math/Matrix3x4.cpp | 4 +- .../AzCore/AzCore/Math/Matrix4x4.cpp | 2 +- Code/Framework/AzCore/AzCore/Math/Obb.cpp | 2 +- .../AzCore/AzCore/Math/Transform.cpp | 4 +- .../AzCore/AzCore/Memory/PoolSchema.cpp | 2 +- .../AzCore/AzCore/Script/ScriptContext.cpp | 4 +- .../Serialization/EditContextConstants.inl | 2 +- .../Serialization/Json/BaseJsonSerializer.cpp | 23 +- .../Serialization/Json/BaseJsonSerializer.h | 16 +- .../AzCore/Serialization/Json/JsonMerger.cpp | 28 +- .../AzCore/Serialization/Json/JsonMerger.h | 28 +- .../Serialization/Json/JsonSerialization.cpp | 90 +- .../Serialization/Json/JsonSerialization.h | 190 +++- .../Json/JsonSerializationMetadata.h | 10 +- .../Json/JsonSerializationMetadata.inl | 30 +- .../Settings/SettingsRegistryMergeUtils.cpp | 40 +- .../Settings/SettingsRegistryMergeUtils.h | 18 + .../AzCore/AzCore/Slice/SliceComponent.cpp | 2 +- .../AzCore/AzCore/StringFunc/StringFunc.h | 4 +- .../AzCore/AzCore/UnitTest/UnitTest.h | 2 +- .../Android/AzCore/AzCore_Traits_Android.h | 1 - .../Android/AzCore/IO/SystemFile_Android.cpp | 2 +- .../Linux/AzCore/AzCore_Traits_Linux.h | 1 - .../Platform/Mac/AzCore/AzCore_Traits_Mac.h | 1 - .../Windows/AzCore/AzCore_Traits_Windows.h | 1 - .../Platform/iOS/AzCore/AzCore_Traits_iOS.h | 1 - .../Framework/AzCore/Tests/AZStd/Optional.cpp | 2 +- Code/Framework/AzCore/Tests/Components.cpp | 6 +- .../AzCore/Tests/IO/Path/PathTests.cpp | 18 +- Code/Framework/AzCore/Tests/Math/ObbTests.cpp | 10 + .../Json/JsonSerializationMetadataTests.cpp | 6 +- .../Tests/SettingsRegistryMergeUtilsTests.cpp | 10 + .../AzFramework/Application/Application.cpp | 55 +- .../AzFramework/Archive/MissingFileReport.cpp | 2 +- .../AzFramework/Asset/AssetBundleManifest.h | 2 +- .../AzFramework/IO/LocalFileIO.cpp | 6 +- .../AzFramework/IO/RemoteStorageDrive.cpp | 25 +- .../AzFramework/Physics/Material.h | 2 +- .../AzFramework/Physics/RigidBody.h | 238 +++++ .../EntityVisibilityBoundsUnionSystem.cpp | 4 +- .../Visibility/EntityVisibilityQuery.cpp | 4 +- .../Visibility/IVisibilitySystem.h | 49 +- .../Visibility/OctreeSystemComponent.cpp | 263 +++-- .../Visibility/OctreeSystemComponent.h | 117 ++- .../AzFramework/IO/LocalFileIO_Android.cpp | 7 +- .../TargetManagementComponent_Windows.cpp | 2 +- .../Windowing/NativeWindow_Windows.cpp | 2 +- .../Devices/Motion/InputDeviceMotion_iOS.mm | 2 +- .../Application/GameApplication.cpp | 8 +- .../Application/GameApplication.h | 2 +- .../AzQtComponents/AzQtComponentsAPI.h | 12 +- .../Components/FilteredSearchWidget.cpp | 2 +- ...umberyardStylesheet.h => O3DEStylesheet.h} | 4 +- .../AzQtComponents/Components/Style.h | 2 +- .../AzQtComponents/Components/StyleManager.h | 2 +- .../Components/Widgets/ColorPicker/Palette.h | 2 +- .../Widgets/Internal/OverlayWidgetLayer.cpp | 4 +- .../Components/Widgets/MessageBox.h | 2 +- .../Components/WindowDecorationWrapper.cpp | 2 +- .../Gallery/AssetBrowserFolderPage.cpp | 2 +- .../Gallery/BreadCrumbsPage.cpp | 4 +- .../AzQtComponents/Gallery/BrowseEditPage.cpp | 2 +- .../AzQtComponents/Gallery/ButtonPage.cpp | 4 +- .../AzQtComponents/Gallery/CardPage.cpp | 2 +- .../AzQtComponents/Gallery/CheckBoxPage.cpp | 4 +- .../AzQtComponents/Gallery/ColorLabelPage.cpp | 2 +- .../Gallery/ColorPickerPage.cpp | 2 +- .../AzQtComponents/Gallery/ComboBoxPage.cpp | 2 +- .../Gallery/ComponentDemoWidget.cpp | 2 +- .../Gallery/DragAndDropPage.cpp | 2 +- .../Gallery/FilteredSearchWidgetPage.cpp | 2 +- .../AzQtComponents/Gallery/Gallery.ico | 3 + .../AzQtComponents/Gallery/Gallery.rc | 1 + .../Gallery/GradientSliderPage.cpp | 2 +- .../AzQtComponents/Gallery/HyperlinkPage.cpp | 2 +- .../AzQtComponents/Gallery/LineEditPage.cpp | 2 +- .../AzQtComponents/Gallery/MenuPage.cpp | 4 +- .../Gallery/ProgressIndicatorPage.cpp | 4 +- .../Gallery/RadioButtonPage.cpp | 4 +- .../Gallery/ReflectedPropertyEditorPage.cpp | 2 +- .../AzQtComponents/Gallery/ScrollBarPage.cpp | 2 +- .../Gallery/SegmentControlPage.cpp | 2 +- .../Gallery/SliderComboPage.cpp | 2 +- .../AzQtComponents/Gallery/SliderPage.cpp | 4 +- .../AzQtComponents/Gallery/SpinBoxPage.cpp | 2 +- .../AzQtComponents/Gallery/SplitterPage.cpp | 2 +- .../AzQtComponents/Gallery/StyleSheetPage.cpp | 2 +- .../Gallery/StyledDockWidgetPage.cpp | 2 +- .../AzQtComponents/Gallery/SvgLabelPage.cpp | 4 +- .../AzQtComponents/Gallery/TabWidgetPage.cpp | 2 +- .../AzQtComponents/Gallery/TableViewPage.cpp | 2 +- .../AzQtComponents/Gallery/TitleBarPage.cpp | 2 +- .../Gallery/ToggleSwitchPage.cpp | 4 +- .../AzQtComponents/Gallery/ToolBarPage.cpp | 2 +- .../AzQtComponents/Gallery/TreeViewPage.cpp | 2 +- .../AzQtComponents/Gallery/TypographyPage.cpp | 4 +- .../AzQtComponents/Gallery/main.cpp | 4 +- .../PropertyEditorStandalone/main.cpp | 2 +- .../StyleGallery/DeploymentsWidget.h | 2 +- .../StyleGallery/ViewportTitleDlg.cpp | 2 +- .../AzQtComponents/StyleGallery/main.cpp | 6 +- .../StyleGallery/mainwidget.cpp | 2 +- .../Utilities/ScreenGrabber_win.cpp | 2 +- .../AzQtComponents/azqtcomponents_files.cmake | 2 +- .../azqtcomponents_gallery_files.cmake | 1 + .../API/ToolsApplicationAPI.h | 2 +- .../Application/ToolsApplication.cpp | 2 +- .../Application/ToolsApplication.h | 2 +- .../AssetPicker/AssetPickerDialog.cpp | 2 +- .../AssetBrowser/Previewer/EmptyPreviewer.cpp | 4 +- .../AssetBrowser/Search/FilterByWidget.cpp | 4 +- .../Search/SearchAssetTypeSelectorWidget.cpp | 4 +- .../Search/SearchParametersWidget.cpp | 4 +- .../AssetBrowser/Views/AssetBrowserTreeView.h | 2 +- .../AssetEditor/AssetEditorWidget.cpp | 4 +- .../Entity/EditorEntityModel.cpp | 2 +- .../Manipulators/ManipulatorManager.h | 2 +- .../Prefab/Instance/InstanceEntityScrubber.h | 2 +- .../Prefab/Instance/InstanceSerializer.cpp | 7 +- .../Prefab/PrefabDomUtils.cpp | 21 +- .../AzToolsFramework/Slice/SliceUtilities.cpp | 6 +- .../SourceControl/PerforceComponent.cpp | 2 +- .../ToolsComponents/ComponentMimeData.cpp | 4 +- .../ToolsComponents/EditorComponentBase.h | 4 +- .../ToolsComponents/EditorLayerComponent.cpp | 5 +- .../ToolsComponents/EditorLayerComponent.h | 4 +- .../Core/EditorFrameworkApplication.cpp | 1 - .../UI/Logging/NewLogTabDialog.cpp | 4 +- .../UI/Outliner/EntityOutlinerWidget.cpp | 2 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 2 +- .../PropertyEditor/EntityPropertyEditor.cpp | 2 +- .../PropertyEditor/EntityPropertyEditor.hxx | 2 +- .../ReflectedPropertyEditor.hxx | 2 +- .../SliceOverridesNotificationWindow.cpp | 2 +- .../UI/UICore/OverwritePromptDialog.cpp | 4 +- .../UI/UICore/ProgressShield.cpp | 4 +- .../UI/UICore/SaveChangesDialog.cpp | 4 +- .../UnitTest/AzToolsFrameworkTestHelpers.cpp | 2 +- .../AzToolsFramework/Viewport/ViewportTypes.h | 8 +- .../GridMate/GridMate/Replica/DataSet.h | 2 +- .../Tests/OctreePerformanceTests.cpp | 41 +- Code/Framework/Tests/OctreeTests.cpp | 208 ++-- Code/LauncherUnified/CMakeLists.txt | 177 +--- .../FindLauncherGenerator.cmake | 14 + Code/LauncherUnified/Game.cpp | 2 +- Code/LauncherUnified/Launcher.cpp | 134 +-- Code/LauncherUnified/Launcher.h | 4 +- Code/LauncherUnified/LauncherProject.cpp | 2 +- .../Platform/Android/Launcher_Android.cpp | 2 +- .../Platform/Common/Apple/Launcher_Apple.h | 2 +- .../Platform/Common/Apple/Launcher_Apple.mm | 2 +- .../Common/UnixLike/Launcher_UnixLike.cpp | 2 +- .../Common/UnixLike/Launcher_UnixLike.h | 2 +- .../Platform/Linux/Launcher_Linux.cpp | 2 +- .../Platform/Mac/Launcher_Mac.mm | 12 +- ..._Mac.mm => O3DEApplicationDelegate_Mac.mm} | 6 +- ...pplication_Mac.h => O3DEApplication_Mac.h} | 8 +- ...Delegate_Mac.mm => O3DEApplication_Mac.mm} | 6 +- .../Platform/Mac/platform_mac_files.cmake | 6 +- .../Platform/Windows/Launcher_Windows.cpp | 2 +- .../Windows/launcher_project_windows.cmake | 2 +- .../Platform/iOS/Launcher_iOS.mm | 4 +- Code/LauncherUnified/Server.cpp | 2 +- .../Tests/LauncherUnifiedTests.cpp | 6 +- Code/LauncherUnified/Tests/Test.cpp | 2 +- Code/LauncherUnified/launcher_generator.cmake | 190 ++++ Code/Sandbox/Editor/AboutDialog.cpp | 2 +- Code/Sandbox/Editor/AboutDialog.ui | 4 +- .../Editor/Alembic/AlembicCompiler.cpp | 2 +- .../AzAssetBrowserRequestHandler.cpp | 8 +- Code/Sandbox/Editor/CMakeLists.txt | 2 +- .../Editor/Controls/ColorGradientCtrl.cpp | 4 - .../ReflectedPropertyCtrl.cpp | 1 - .../Editor/Core/LevelEditorMenuHandler.cpp | 12 +- .../Editor/Core/QtEditorApplication.cpp | 12 +- .../Sandbox/Editor/Core/QtEditorApplication.h | 4 +- Code/Sandbox/Editor/CryEdit.cpp | 34 +- Code/Sandbox/Editor/CryEdit.h | 2 +- Code/Sandbox/Editor/DatabaseFrameWnd.cpp | 8 +- Code/Sandbox/Editor/EditorCryEdit.rc | 2 +- Code/Sandbox/Editor/EditorPanelUtils.cpp | 4 +- .../Editor/EditorPreferencesPageGeneral.cpp | 4 +- .../Editor/FeedbackDialog/FeedbackDialog.cpp | 6 +- .../Sandbox/Editor/GraphicsSettingsDialog.cpp | 8 +- Code/Sandbox/Editor/IEditorImpl.cpp | 8 +- .../Editor/KeyboardCustomizationSettings.cpp | 10 +- .../LensFlareEditor/LensFlareAtomicList.cpp | 4 +- .../LensFlareEditor/LensFlareEditor.cpp | 6 +- .../LensFlareEditor/LensFlareElementTree.cpp | 14 +- Code/Sandbox/Editor/MainWindow.cpp | 8 +- Code/Sandbox/Editor/MainWindow.qrc | 2 +- .../Editor/Material/MaterialManager.cpp | 2 +- .../Editor/Material/MaterialPythonFuncs.cpp | 2 - Code/Sandbox/Editor/PluginManager.cpp | 2 +- Code/Sandbox/Editor/Resource.h | 2 +- Code/Sandbox/Editor/Settings.cpp | 2 +- Code/Sandbox/Editor/ShortcutDispatcher.h | 4 +- Code/Sandbox/Editor/StartupLogoDialog.cpp | 4 +- Code/Sandbox/Editor/ThumbnailGenerator.cpp | 41 +- Code/Sandbox/Editor/ToolbarManager.cpp | 2 +- .../Editor/TrackView/TrackViewDialog.cpp | 4 +- .../Editor/TrackView/TrackViewPythonFuncs.cpp | 2 - Code/Sandbox/Editor/Util/ImageUtil.cpp | 4 - Code/Sandbox/Editor/ViewportTitleDlg.cpp | 4 +- .../WelcomeScreen/WelcomeScreenDialog.ui | 2 +- Code/Sandbox/Editor/res/lyeditor.ico | 3 - Code/Sandbox/Editor/res/o3de_editor.ico | 3 + .../Objects/ComponentEntityObject.cpp | 39 +- .../AssetBrowserContextProvider.cpp | 2 +- .../AssetImporterPlugin.cpp | 6 + .../Plugins/EditorCommon/EditorCommon.rc | Bin 2536 -> 2552 bytes .../Sandbox/Plugins/FBXPlugin/FBXExporter.cpp | 10 +- .../PlatformSettings_Ios.h | 2 +- .../AWSNativeSDKInit/AWSNativeSDKInit.h | 4 +- .../assetbundlerbatch_exe_files.cmake | 1 + .../AssetBundler/source/AssetBundlerBatch.ico | 3 + .../AssetBundler/source/AssetBundlerBatch.rc | 1 + .../source/utils/applicationManager.cpp | 12 +- .../Tools/AssetBundler/source/utils/utils.cpp | 6 +- .../AssetBuilder/AssetBuilder.ico | 3 + .../AssetBuilder/AssetBuilder.rc | 1 + .../AssetBuilder/asset_builder_files.cmake | 1 + .../Linux/AssetProcessor_Traits_Linux.h | 4 +- .../Platform/Mac/AssetProcessor_Traits_Mac.h | 4 +- .../Platform/Windows/AssetProcessor.rc | 2 +- .../Platform/Windows/AssetProcessorBatch.ico | 3 + .../Platform/Windows/AssetProcessorBatch.rc | 1 + .../Windows/AssetProcessor_Traits_Windows.h | 4 +- .../assetprocessor_batch_files.cmake | 1 + .../native/AssetManager/FileStateCache.cpp | 5 +- .../AssetManager/assetProcessorManager.cpp | 98 +- .../AssetManager/assetProcessorManager.h | 8 +- .../native/resourcecompiler/RCBuilder.cpp | 10 +- .../tests/assetdatabase/AssetDatabaseTest.cpp | 8 +- .../AssetProcessorManagerTest.cpp | 125 +++ .../assetmanager/AssetProcessorManagerTest.h | 1 + .../native/ui/ProductAssetDetailsPanel.cpp | 2 +- .../native/ui/SourceAssetTreeModel.cpp | 2 +- .../native/ui/style/AssetProcessor.qrc | 2 +- .../native/ui/style/lyassetprocessor.ico | 3 - .../native/ui/style/lyassetprocessor.png | 3 - .../native/ui/style/o3de_assetprocessor.ico | 3 + .../native/ui/style/o3de_assetprocessor.png | 3 + .../AssetProcessingStateDataUnitTests.cpp | 26 +- .../utilities/GUIApplicationManager.cpp | 61 +- .../native/utilities/GUIApplicationManager.h | 1 - .../native/utilities/assetUtils.cpp | 20 +- Code/Tools/CrashHandler/Shared/CrashHandler.h | 4 +- .../CrashHandler/Tools/UI/submit_report.ui | 6 +- .../Tools/Uploader/ToolsCrashUploader.cpp | 4 +- .../Tools/Uploader/ToolsCrashUploader.h | 2 +- .../Tools/Uploader/platforms/win/main.cpp | 4 +- .../include/Uploader/BufferedDataStream.h | 2 +- .../Uploader/include/Uploader/CrashUploader.h | 2 +- .../include/Uploader/FileStreamDataSource.h | 2 +- .../Uploader/src/BufferedDataStream.cpp | 2 +- .../Uploader/src/CrashUploader.cpp | 2 +- .../Uploader/src/FileStreamDataSource.cpp | 2 +- .../Core/Server/CrySimpleSock.cpp | 2 +- Code/Tools/DeltaCataloger/CMakeLists.txt | 15 + .../deltacataloger_win_files.cmake | 14 + .../DeltaCataloger/source/DeltaCataloger.ico | 3 + .../DeltaCataloger/source/DeltaCataloger.rc | 1 + Code/Tools/HLSLCrossCompiler/include/hlslcc.h | 2 +- .../HLSLCrossCompilerMETAL/include/hlslcc.h | 2 +- .../Tools/News/NewsBuilder/Qt/NewsBuilder.cpp | 2 +- .../News/NewsShared/Qt/ArticleErrorView.ui | 2 +- Code/Tools/RC/ResourceCompiler/CMakeLists.txt | 1 - .../RC/ResourceCompiler/ResourceCompiler.cpp | 4 - .../RC/ResourceCompiler/ResourceCompiler.rc | 2 +- Code/Tools/RC/ResourceCompiler/main.cpp | 2 +- .../RC/ResourceCompilerPC/CMakeLists.txt | 1 - .../Common/MaterialExporter.cpp | 2 +- .../RC/ResourceCompilerXML/CMakeLists.txt | 1 - .../SceneAPI/FbxSDKWrapper/CMakeLists.txt | 2 + .../Importers/FbxMaterialImporter.cpp | 2 +- .../SceneAPI/SceneData/Groups/MeshGroup.cpp | 4 +- .../SceneData/Groups/SkeletonGroup.cpp | 2 +- .../SceneAPI/SceneData/Groups/SkinGroup.cpp | 4 +- .../SceneData/Rules/BlendShapeRule.cpp | 2 +- .../SceneAPI/SceneData/Rules/MaterialRule.cpp | 2 +- .../ShaderCacheGen/ShaderCacheGen.cpp | 13 +- .../Standalone/Source/Editor/hex_lua.ico | 4 +- .../Source/StandaloneToolsApplication.cpp | 2 +- .../Code/Source/Framework/AWSApiJob.cpp | 2 +- .../Code/Tests/AWSCoreSystemComponentTest.cpp | 2 +- .../Code/Source/IdentityProvider.cpp | 2 +- .../Code/Source/Converters/Cubemap.h | 2 +- .../Code/Source/ImageLoader/ImageLoaders.h | 2 +- .../Code/Source/Processing/DDSHeader.h | 2 +- Gems/Atom/Asset/Shader/Code/CMakeLists.txt | 6 - .../Code/Source/BootstrapSystemComponent.cpp | 19 +- .../Code/Source/BootstrapSystemComponent.h | 1 + .../Passes/EnvironmentCubeMapForwardMSAA.pass | 8 +- .../Passes/EnvironmentCubeMapPipeline.pass | 20 +- .../Feature/Common/Assets/Passes/Forward.pass | 8 +- .../Assets/Passes/ForwardCheckerboard.pass | 8 +- .../Common/Assets/Passes/ForwardMSAA.pass | 8 +- .../Common/Assets/Passes/MainPipeline.pass | 16 +- .../Common/Assets/Passes/OpaqueParent.pass | 12 +- .../Assets/Passes/PassTemplates.azasset | 4 +- ...adowmaps.pass => ProjectedShadowmaps.pass} | 4 +- .../Common/Assets/Passes/ShadowParent.pass | 24 +- .../Common/Assets/Passes/Transparent.pass | 8 +- .../Assets/Passes/TransparentParent.pass | 12 +- .../LightCulling/LightCullingShared.azsli | 4 +- .../MorphTargets/MorphTargetCompression.azsli | 18 + .../Atom/Features/PBR/ForwardPassSrg.azsli | 4 +- .../Atom/Features/PBR/Lights/DiskLight.azsli | 88 +- .../Atom/Features/PBR/Lights/Lights.azsli | 8 +- .../PBR/Lights/SimplePointLight.azsli | 55 ++ .../Features/PBR/Lights/SimpleSpotLight.azsli | 76 ++ .../Atom/Features/PBR/Lights/SpotLight.azsli | 152 --- .../Features/PBR/TransparentPassSrg.azsli | 4 +- .../Shadow/DirectionalLightShadow.azsli | 61 +- ...ightShadow.azsli => ProjectedShadow.azsli} | 148 +-- .../CoreLights/ViewSrg.azsli | 76 +- .../RayTracingSceneSrg.azsli | 32 +- .../Shaders/LightCulling/LightCulling.azsl | 184 ++-- .../Shaders/MorphTargets/MorphTargetCS.azsl | 17 +- .../Shaders/MorphTargets/MorphTargetSRG.azsli | 4 +- .../Shaders/SkinnedMesh/LinearSkinningCS.azsl | 38 + .../SkinnedMesh/LinearSkinningPassSRG.azsli | 18 + .../atom_feature_common_asset_files.cmake | 5 +- Gems/Atom/Feature/Common/Code/CMakeLists.txt | 1 - .../Feature/CoreLights/CoreLightsConstants.h | 4 +- ...irectionalLightFeatureProcessorInterface.h | 3 + .../DiskLightFeatureProcessorInterface.h | 52 +- .../Atom/Feature/CoreLights/ShadowConstants.h | 2 +- ...implePointLightFeatureProcessorInterface.h | 49 + ...SimpleSpotLightFeatureProcessorInterface.h | 53 + .../SpotLightFeatureProcessorInterface.h | 110 --- .../MorphTargets/MorphTargetInputBuffers.h | 2 + .../Feature/ParamMacros/ParamMacrosHowTo.inl | 2 +- ...ProjectedShadowFeatureProcessorInterface.h | 72 ++ .../SkinnedMesh/SkinnedMeshInputBuffers.h | 23 +- .../SkinnedMesh/SkinnedMeshShaderOptions.h | 1 + .../SkinnedMesh/SkinnedMeshVertexStreams.h | 6 + .../Atom/Feature/Utils/MultiSparseVector.h | 166 ++++ .../Include/Atom/Feature/Utils/SparseVector.h | 126 +++ .../Code/Source/CommonSystemComponent.cpp | 15 +- .../CoreLights/CoreLightsSystemComponent.cpp | 13 +- .../DirectionalLightFeatureProcessor.cpp | 10 + .../DirectionalLightFeatureProcessor.h | 6 +- .../CoreLights/DiskLightFeatureProcessor.cpp | 220 ++++- .../CoreLights/DiskLightFeatureProcessor.h | 30 +- .../Source/CoreLights/EsmShadowmapsPass.cpp | 4 +- .../Source/CoreLights/IndexedDataVector.h | 3 +- .../Source/CoreLights/IndexedDataVector.inl | 6 + .../Source/CoreLights/LightCullingPass.cpp | 41 +- .../Code/Source/CoreLights/LightCullingPass.h | 3 +- .../Source/CoreLights/LightCullingRemap.cpp | 1 - ...psPass.cpp => ProjectedShadowmapsPass.cpp} | 40 +- ...owmapsPass.h => ProjectedShadowmapsPass.h} | 22 +- .../Common/Code/Source/CoreLights/Shadow.h | 2 +- .../SimplePointLightFeatureProcessor.cpp | 173 ++++ .../SimplePointLightFeatureProcessor.h | 74 ++ .../SimpleSpotLightFeatureProcessor.cpp | 189 ++++ .../SimpleSpotLightFeatureProcessor.h | 78 ++ .../CoreLights/SpotLightFeatureProcessor.cpp | 929 ------------------ .../CoreLights/SpotLightFeatureProcessor.h | 158 --- .../Source/Decals/DecalFeatureProcessor.cpp | 2 +- .../DiffuseProbeGrid/DiffuseProbeGrid.cpp | 4 +- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 4 +- .../MorphTargets/MorphTargetDispatchItem.cpp | 44 +- .../MorphTargets/MorphTargetDispatchItem.h | 2 + .../RayTracing/RayTracingFeatureProcessor.cpp | 9 - .../ReflectionProbe/ReflectionProbe.cpp | 4 +- .../ProjectedShadowFeatureProcessor.cpp | 632 ++++++++++++ .../Shadows/ProjectedShadowFeatureProcessor.h | 141 +++ .../SkinnedMesh/SkinnedMeshDispatchItem.cpp | 24 +- .../SkinnedMesh/SkinnedMeshInputBuffers.cpp | 130 ++- .../SkinnedMeshShaderOptionsCache.cpp | 13 + .../SkinnedMeshShaderOptionsCache.h | 4 + .../SkinnedMeshVertexStreamProperties.cpp | 25 + .../Common/Code/Tests/SparseVectorTests.cpp | 292 ++++++ .../Code/atom_feature_common_files.cmake | 22 +- .../atom_feature_common_public_files.cmake | 4 +- .../atom_feature_common_tests_files.cmake | 1 + .../RHI/Vulkan/3rdParty/Findglad_vulkan.cmake | 2 +- .../Code/Include/Atom/RPI.Public/Culling.h | 27 +- .../Atom/RPI.Public/FeatureProcessor.h | 2 +- .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 8 +- .../Atom/RPI.Reflect/Model/MorphTargetDelta.h | 27 +- .../RPI.Reflect/Model/MorphTargetMetaAsset.h | 3 + .../Model/ModelAssetBuilderComponent.cpp | 59 +- .../Model/ModelAssetBuilderComponent.h | 7 + .../Model/MorphTargetExporter.cpp | 28 +- .../RPI/Code/Source/RPI.Public/Culling.cpp | 63 +- .../Source/RPI.Public/Pass/RasterPass.cpp | 7 +- .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 20 +- .../Shader/ShaderVariantAsyncLoader.cpp | 1 - .../RPI.Reflect/Model/MorphTargetDelta.cpp | 14 +- .../Model/MorphTargetMetaAsset.cpp | 1 + Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp | 1 + .../Atom/RPI/Code/Tests/System/SceneTests.cpp | 22 + .../Code/Source/Inspector/InspectorWidget.cpp | 2 +- .../Code/Source/MaterialEditor.ico | 3 - .../Platform/Windows/MaterialEditor.ico | 3 + .../{ => Platform/Windows}/MaterialEditor.rc | 0 .../Windows/platform_windows_files.cmake | 1 + .../Viewport/MaterialViewportRenderer.cpp | 5 + .../CreateMaterialDialog.h | 2 +- .../PresetBrowserDialog.h | 2 +- .../Window/ToolBar/MaterialEditorToolBar.cpp | 82 +- .../Window/ToolBar/MaterialEditorToolBar.h | 12 + .../ViewportSettingsInspector.cpp | 4 +- .../Tools/MaterialEditor/Code/Source/main.cpp | 2 +- .../Windows/ShaderManagementConsole.ico | 3 + .../Windows}/ShaderManagementConsole.rc | 0 .../Windows/platform_windows_files.cmake | 1 + .../Code/Source/ShaderManagementConsole.ico | 3 - .../Code/Source/main.cpp | 2 +- .../Include/Atom/Utils/ImGuiCullingDebug.inl | 4 +- .../Atom/Utils/ImGuiFrameVisualizer.inl | 1 - .../AtomImGuiTools/Code/CMakeLists.txt | 4 - .../CommonFeatures/CoreLights/AreaLightBus.h | 66 ++ .../CoreLights/AreaLightComponentConfig.h | 62 +- .../CoreLights/CoreLightsConstants.h | 4 - .../CoreLights/DirectionalLightBus.h | 7 + .../DirectionalLightComponentConfig.h | 3 + .../CommonFeatures/CoreLights/PointLightBus.h | 130 --- .../CoreLights/PointLightComponentConfig.h | 113 --- .../CommonFeatures/CoreLights/SpotLightBus.h | 172 ---- .../CoreLights/SpotLightComponentConfig.h | 62 -- .../CoreLights/AreaLightComponentConfig.cpp | 97 +- .../AreaLightComponentController.cpp | 710 +++++++++---- .../CoreLights/AreaLightComponentController.h | 28 +- .../DirectionalLightComponentConfig.cpp | 15 +- .../DirectionalLightComponentController.cpp | 16 +- .../DirectionalLightComponentController.h | 2 + .../Source/CoreLights/DiskLightDelegate.cpp | 149 ++- .../Source/CoreLights/DiskLightDelegate.h | 14 +- .../CoreLights/EditorAreaLightComponent.cpp | 286 +++++- .../CoreLights/EditorAreaLightComponent.h | 6 +- .../EditorDirectionalLightComponent.cpp | 16 +- .../CoreLights/EditorPointLightComponent.cpp | 206 ---- .../CoreLights/EditorPointLightComponent.h | 74 -- .../CoreLights/EditorSpotLightComponent.cpp | 261 ----- .../CoreLights/EditorSpotLightComponent.h | 49 - .../Source/CoreLights/LightDelegateBase.h | 36 +- .../Source/CoreLights/LightDelegateBase.inl | 23 +- .../CoreLights/LightDelegateInterface.h | 26 + .../Source/CoreLights/PointLightComponent.cpp | 44 - .../Source/CoreLights/PointLightComponent.h | 38 - .../PointLightComponentController.cpp | 286 ------ .../PointLightComponentController.h | 87 -- .../CoreLights/SimplePointLightDelegate.cpp | 56 ++ .../CoreLights/SimplePointLightDelegate.h | 44 + .../CoreLights/SimpleSpotLightDelegate.cpp | 58 ++ .../CoreLights/SimpleSpotLightDelegate.h | 44 + .../Source/CoreLights/SpotLightComponent.cpp | 44 - .../Source/CoreLights/SpotLightComponent.h | 37 - .../CoreLights/SpotLightComponentConfig.cpp | 83 -- .../SpotLightComponentController.cpp | 434 -------- .../CoreLights/SpotLightComponentController.h | 102 -- .../EditorMaterialComponentExporter.cpp | 8 +- .../CommonFeatures/Code/Source/Module.cpp | 8 - ...egration_commonfeatures_editor_files.cmake | 4 - ...omlyintegration_commonfeatures_files.cmake | 13 +- ...egration_commonfeatures_public_files.cmake | 4 - .../EMotionFXAtom/Code/CMakeLists.txt | 6 - .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 138 ++- .../Code/Source/AtomActorInstance.cpp | 7 +- .../ImguiAtom/Code/CMakeLists.txt | 4 - .../ImguiAtom/Code/Source/DebugConsole.cpp | 12 +- .../ImguiAtom/Code/Source/DebugConsole.h | 20 +- .../Code/Source/Engine/FileIOHandler_wwise.h | 4 +- Gems/Blast/Code/Include/Blast/BlastMaterial.h | 2 +- .../CrashReporting/GameCrashUploader.h | 2 +- .../Windows/GameCrashUploader_windows.cpp | 2 +- .../Code/Platform/Windows/main_windows.cpp | 4 +- .../Code/Source/GameCrashUploader.cpp | 4 +- Gems/CustomAssetExample/Code/CMakeLists.txt | 4 - Gems/EMotionFX/Code/CMakeLists.txt | 10 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 3 + .../EMotionFX/Source/EMotionFXManager.cpp | 4 +- .../EMStudioSDK/Source/LayoutManager.cpp | 3 +- .../EMStudioSDK/Source/MainWindow.cpp | 12 +- .../Source/RenderPlugin/RenderPlugin.cpp | 6 +- .../OpenGLRender/OpenGLRenderPlugin.cpp | 3 +- .../Source/AnimGraph/GameControllerWindow.cpp | 4 +- .../Attachments/AttachmentNodesWindow.cpp | 8 +- .../Source/Attachments/AttachmentsWindow.cpp | 12 +- .../Source/CommandBar/CommandBarPlugin.cpp | 10 +- .../PhonemeSelectionWindow.cpp | 12 +- .../MotionEvents/MotionEventPresetsWidget.cpp | 6 +- .../MotionSetManagementWindow.cpp | 6 +- .../MotionSetsWindow/MotionSetWindow.cpp | 10 +- .../MotionWindow/MotionWindowPlugin.cpp | 4 +- .../NodeGroups/NodeGroupManagementWidget.cpp | 8 +- .../Source/NodeGroups/NodeGroupWidget.cpp | 8 +- .../Source/SceneManager/ActorsWindow.cpp | 6 +- .../Source/SceneManager/MirrorSetupWindow.cpp | 25 +- .../Source/TimeView/PlaybackControlsGroup.cpp | 10 +- .../Source/TimeView/PlaybackOptionsGroup.cpp | 12 +- .../Source/TimeView/RecorderGroup.cpp | 8 +- .../Source/TimeView/TimeViewPlugin.cpp | 5 +- .../Source/TimeView/TrackDataHeaderWidget.cpp | 5 +- .../Source/TimeView/TrackHeaderWidget.cpp | 2 +- .../Editor/Platform/Mac/platform_mac.cmake | 4 +- .../Code/MysticQt/Source/MysticQtManager.cpp | 4 +- .../PropertyWidgets/ActorGoalNodeHandler.cpp | 4 +- .../PropertyWidgets/ActorJointHandler.cpp | 2 +- .../ActorMorphTargetHandler.cpp | 2 +- .../AnimGraphParameterHandler.cpp | 4 +- .../AnimGraphTransitionHandler.cpp | 2 +- .../BlendSpaceMotionContainerHandler.cpp | 2 +- .../MotionSetMotionIdHandler.cpp | 2 +- .../SimulatedObjectSelectionHandler.cpp | 2 +- .../TransitionStateFilterLocalHandler.cpp | 4 +- .../Source/Editor/SimulatedObjectModel.cpp | 2 - .../Source/Integration/Assets/ActorAsset.h | 4 +- .../Integration/System/SystemComponent.cpp | 8 +- .../Code/Tests/UI/CanUseLayoutMenu.cpp | 2 +- .../Code/Source/PythonProxyBus.h | 2 +- .../Code/Source/Widgets/GraphCanvasLabel.cpp | 2 - .../StaticLib/GraphCanvas/Styling/Parser.cpp | 2 - Gems/ImGui/Code/Include/ImGuiContextScope.h | 11 +- Gems/ImGui/Code/Source/ImGuiManager.cpp | 144 +-- .../Source/LYCommonMenu/ImGuiLYCommonMenu.cpp | 6 +- .../BuilderSettings/BuilderSettingManager.h | 2 +- .../Code/Source/Converters/Cubemap.h | 2 +- .../Source/InAppPurchasesSystemComponent.cpp | 2 +- .../Common/Apple/InAppPurchasesApple.mm | 10 +- .../Common/Apple/InAppPurchasesDelegate.mm | 26 +- .../XmlBuilderWorker/XmlBuilderWorker.cpp | 2 +- .../MaterialBuilderComponent.cpp | 2 +- .../Source/Shape/CapsuleShapeComponent.cpp | 2 - .../Code/Source/Shape/DiskShapeComponent.cpp | 2 - .../Shape/EditorCapsuleShapeComponent.h | 1 - .../Source/Shape/EditorDiskShapeComponent.cpp | 1 - .../EditorPolygonPrismShapeComponent.cpp | 2 - .../Source/Shape/EditorQuadShapeComponent.cpp | 1 - .../Source/Shape/EditorSphereShapeComponent.h | 1 - .../Code/Source/Shape/QuadShapeComponent.cpp | 2 - .../Source/Shape/SphereShapeComponent.cpp | 2 - .../Animation/UiAVCustomizeTrackColorsDlg.cpp | 2 +- .../Editor/Animation/UiAVEventsDialog.cpp | 2 +- .../Editor/Animation/UiAVSequenceProps.cpp | 2 +- .../Animation/UiAnimViewCurveEditor.cpp | 2 +- .../Editor/Animation/UiAnimViewDialog.cpp | 6 +- .../Editor/Animation/UiAnimViewFindDlg.cpp | 2 +- .../Animation/UiAnimViewKeyPropertiesDlg.cpp | 2 +- .../Animation/UiAnimViewNewSequenceDialog.cpp | 2 +- .../Code/Editor/Animation/UiAnimViewNodes.cpp | 2 +- Gems/LyShine/Code/Editor/EditorCommon.h | 4 +- .../Editor/LyShineEditorSystemComponent.cpp | 2 +- .../Tests/internal/test_UiTextComponent.cpp | 2 +- .../Code/Source/UiCanvasFileObject.cpp | 10 - .../Code/Source/MaestroSystemComponent.cpp | 2 +- Gems/Multiplayer/Code/CMakeLists.txt | 4 - .../ServerToClientReplicationWindow.cpp | 2 +- .../Code/CMakeLists.txt | 4 - .../Code/Platform/Windows/PAL_windows.cmake | 2 - .../Code/Source/System/SystemComponent.cpp | 4 +- Gems/PhysX/Code/CMakeLists.txt | 3 - .../PhysX/Code/Source/System/PhysXAllocator.h | 2 +- .../Code/Source/System/PhysXCpuDispatcher.h | 4 +- Gems/PhysX/Code/Source/System/PhysXJob.h | 2 +- .../Code/Source/System/PhysXSdkCallbacks.h | 2 +- Gems/PhysX/Code/Source/SystemComponent.h | 2 +- Gems/PhysXDebug/Code/Source/SystemComponent.h | 2 +- .../PrefabBuilder/PrefabBuilderTests.cpp | 3 + .../Prefab/PrefabBuilder/PrefabBuilderTests.h | 42 +- .../PythonBuilderRequestBus.h | 2 +- .../Code/Include/QtForPython/QtForPythonBus.h | 2 +- Gems/SaveData/Code/Tests/SaveDataTest.cpp | 2 +- Gems/SceneLoggingExample/Code/CMakeLists.txt | 4 - Gems/SceneLoggingExample/ReadMe.txt | 4 +- .../SceneProcessingConfigSystemComponent.cpp | 2 +- .../Code/Editor/Components/EditorGraph.cpp | 6 +- .../Code/Editor/SystemComponent.cpp | 2 +- .../VariablePanel/GraphVariablesTableView.h | 2 +- .../Include/ScriptCanvas/Utils/NodeUtils.cpp | 2 - Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 2 - Gems/TestAssetBuilder/Code/CMakeLists.txt | 4 - Gems/Twitch/Code/Source/TwitchReflection.cpp | 676 ++++++------- .../Windows/platform_windows_tools.cmake | 2 - Tests/ly_shared/PlatformSetting.py | 2 +- .../bin/windows/vs2019/Debug_x64/base.lib | 3 + .../bin/windows/vs2019/Debug_x64/base_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_client.lib | 3 + .../vs2019/Debug_x64/crashpad_client_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_compat.lib | 3 + .../vs2019/Debug_x64/crashpad_compat_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_context.lib | 3 + .../vs2019/Debug_x64/crashpad_context_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_handler.lib | 3 + .../vs2019/Debug_x64/crashpad_handler_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_minidump.lib | 3 + .../vs2019/Debug_x64/crashpad_minidump_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_snapshot.lib | 3 + .../vs2019/Debug_x64/crashpad_snapshot_cc.pdb | 3 + .../Debug_x64/crashpad_tool_support.lib | 3 + .../Debug_x64/crashpad_tool_support_cc.pdb | 3 + .../vs2019/Debug_x64/crashpad_util.lib | 3 + .../vs2019/Debug_x64/crashpad_util_cc.pdb | 3 + .../Debug_x64/third_party/getopt.cc.pdb | 3 + .../vs2019/Debug_x64/third_party/getopt.lib | 3 + .../vs2019/Debug_x64/third_party/zlib.c.pdb | 3 + .../vs2019/Debug_x64/third_party/zlib.lib | 3 + .../bin/windows/vs2019/Release_x64/base.lib | 3 + .../windows/vs2019/Release_x64/base_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_client.lib | 3 + .../vs2019/Release_x64/crashpad_client_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_compat.lib | 3 + .../vs2019/Release_x64/crashpad_compat_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_context.lib | 3 + .../Release_x64/crashpad_context_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_handler.lib | 3 + .../Release_x64/crashpad_handler_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_minidump.lib | 3 + .../Release_x64/crashpad_minidump_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_snapshot.lib | 3 + .../Release_x64/crashpad_snapshot_cc.pdb | 3 + .../Release_x64/crashpad_tool_support.lib | 3 + .../Release_x64/crashpad_tool_support_cc.pdb | 3 + .../vs2019/Release_x64/crashpad_util.lib | 3 + .../vs2019/Release_x64/crashpad_util_cc.pdb | 3 + .../Release_x64/third_party/getopt.cc.pdb | 3 + .../vs2019/Release_x64/third_party/getopt.lib | 3 + .../vs2019/Release_x64/third_party/zlib.c.pdb | 3 + .../vs2019/Release_x64/third_party/zlib.lib | 3 + .../handler/src/crash_report_upload_thread.cc | 8 +- .../Crashpad/include/client/crashpad_client.h | 5 +- Tools/LyTestTools/README.txt | 4 +- .../_internal/managers/workspace.py | 12 +- .../ly_test_tools/log/log_monitor.py | 2 +- .../{lumberyard => o3de}/__init__.py | 0 .../{lumberyard => o3de}/ap_log_parser.py | 0 .../{lumberyard => o3de}/asset_processor.py | 4 +- .../asset_processor_config_util.py | 4 +- .../asset_processor_utils.py | 0 .../ini_configuration_util.py | 0 .../{lumberyard => o3de}/pipeline_utils.py | 2 +- .../{lumberyard => o3de}/settings.py | 0 .../{lumberyard => o3de}/shader_compiler.py | 0 .../tests/unit/test_asset_processor.py | 38 +- .../tests/unit/test_launcher_android.py | 2 +- Tools/LyTestTools/tests/unit/test_settings.py | 32 +- .../tests/unit/test_shader_compiler.py | 34 +- .../build/Platform/Mac/build_config.json | 10 + cmake/3rdParty.cmake | 20 + .../Linux/BuiltInPackages_linux.cmake | 2 + .../Platform/Mac/BuiltInPackages_mac.cmake | 2 + .../Windows/BuiltInPackages_windows.cmake | 4 + .../Platform/Windows/Crashpad_windows.cmake | 5 +- cmake/3rdPartyPackages.cmake | 2 +- cmake/FindTargetTemplate.cmake | 45 + cmake/Findo3deTemplate.cmake | 35 + cmake/Install.cmake | 13 + cmake/LYWrappers.cmake | 82 +- cmake/LyAutoGen.cmake | 3 +- cmake/Platform/Android/Install_android.cmake | 12 + .../Android/platform_android_files.cmake | 2 + cmake/Platform/Common/Install_common.cmake | 284 ++++++ .../Common/MSVC/Configurations_msvc.cmake | 3 +- cmake/Platform/Linux/Install_linux.cmake | 12 + .../Platform/Linux/platform_linux_files.cmake | 2 + cmake/Platform/Mac/Install_mac.cmake | 21 + cmake/Platform/Mac/platform_mac_files.cmake | 1 + cmake/Platform/Windows/Install_windows.cmake | 12 + .../Windows/platform_windows_files.cmake | 2 + cmake/Platform/iOS/Install_ios.cmake | 21 + cmake/Platform/iOS/platform_ios_files.cmake | 1 + cmake/SettingsRegistry.cmake | 2 +- .../Tools/Platform/Android/android_support.py | 6 +- .../Android/generate_android_project.py | 2 +- cmake/UnitTest.cmake | 2 +- cmake/Version.cmake | 6 +- cmake/cmake_files.cmake | 1 + engine.json | 4 +- .../3rdParty/package_filelists/3rdParty.json | 2 +- .../package/Platform/Mac/package_env.json | 14 +- .../Mac/package_filelists/3rdParty.json | 82 ++ 904 files changed, 9289 insertions(+), 7157 deletions(-) create mode 100644 AutomatedTesting/AssetProcessorGamePlatformConfig.setreg create mode 100644 Code/Framework/AzFramework/AzFramework/Physics/RigidBody.h rename Code/Framework/AzQtComponents/AzQtComponents/Components/{LumberyardStylesheet.h => O3DEStylesheet.h} (85%) create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.ico create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.rc create mode 100644 Code/LauncherUnified/FindLauncherGenerator.cmake rename Code/LauncherUnified/Platform/Mac/{LumberyardApplication_Mac.mm => O3DEApplicationDelegate_Mac.mm} (80%) rename Code/LauncherUnified/Platform/Mac/{LumberyardApplication_Mac.h => O3DEApplication_Mac.h} (71%) rename Code/LauncherUnified/Platform/Mac/{LumberyardApplicationDelegate_Mac.mm => O3DEApplication_Mac.mm} (79%) create mode 100644 Code/LauncherUnified/launcher_generator.cmake delete mode 100644 Code/Sandbox/Editor/res/lyeditor.ico create mode 100644 Code/Sandbox/Editor/res/o3de_editor.ico create mode 100644 Code/Tools/AssetBundler/source/AssetBundlerBatch.ico create mode 100644 Code/Tools/AssetBundler/source/AssetBundlerBatch.rc create mode 100644 Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.ico create mode 100644 Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.rc create mode 100644 Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.ico create mode 100644 Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.rc delete mode 100644 Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.ico delete mode 100644 Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.png create mode 100644 Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.ico create mode 100644 Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.png create mode 100644 Code/Tools/DeltaCataloger/deltacataloger_win_files.cmake create mode 100644 Code/Tools/DeltaCataloger/source/DeltaCataloger.ico create mode 100644 Code/Tools/DeltaCataloger/source/DeltaCataloger.rc rename Gems/Atom/Feature/Common/Assets/Passes/{SpotLightShadowmaps.pass => ProjectedShadowmaps.pass} (91%) create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimplePointLight.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimpleSpotLight.azsli delete mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SpotLight.azsli rename Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/{SpotLightShadow.azsli => ProjectedShadow.azsli} (73%) create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimplePointLightFeatureProcessorInterface.h create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimpleSpotLightFeatureProcessorInterface.h delete mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h rename Gems/Atom/Feature/Common/Code/Source/CoreLights/{SpotLightShadowmapsPass.cpp => ProjectedShadowmapsPass.cpp} (87%) rename Gems/Atom/Feature/Common/Code/Source/CoreLights/{SpotLightShadowmapsPass.h => ProjectedShadowmapsPass.h} (82%) create mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h create mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h delete mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.cpp delete mode 100644 Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.h create mode 100644 Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h create mode 100644 Gems/Atom/Feature/Common/Code/Tests/SparseVectorTests.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.ico create mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.ico rename Gems/Atom/Tools/MaterialEditor/Code/Source/{ => Platform/Windows}/MaterialEditor.rc (100%) create mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.ico rename Gems/Atom/Tools/ShaderManagementConsole/Code/Source/{ => Platform/Windows}/ShaderManagementConsole.rc (100%) delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.ico delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightBus.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightComponentConfig.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightBus.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightComponentConfig.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.h delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentConfig.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.cpp delete mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.h create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/base.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/base_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.c.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/base.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/base_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util_cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.cc.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.lib create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.c.pdb create mode 100644 Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.lib rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/__init__.py (100%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/ap_log_parser.py (100%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/asset_processor.py (99%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/asset_processor_config_util.py (98%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/asset_processor_utils.py (100%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/ini_configuration_util.py (100%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/pipeline_utils.py (99%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/settings.py (100%) mode change 100755 => 100644 rename Tools/LyTestTools/ly_test_tools/{lumberyard => o3de}/shader_compiler.py (100%) mode change 100755 => 100644 create mode 100644 cmake/FindTargetTemplate.cmake create mode 100644 cmake/Findo3deTemplate.cmake create mode 100644 cmake/Install.cmake create mode 100644 cmake/Platform/Android/Install_android.cmake create mode 100644 cmake/Platform/Common/Install_common.cmake create mode 100644 cmake/Platform/Linux/Install_linux.cmake create mode 100644 cmake/Platform/Mac/Install_mac.cmake create mode 100644 cmake/Platform/Windows/Install_windows.cmake create mode 100644 cmake/Platform/iOS/Install_ios.cmake create mode 100644 scripts/build/package/Platform/Mac/package_filelists/3rdParty.json diff --git a/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg new file mode 100644 index 0000000000..c9876cb1f9 --- /dev/null +++ b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg @@ -0,0 +1,14 @@ +{ + "Amazon": { + "AssetProcessor": { + "Settings": { + "RC cgf": { + "ignore": true + }, + "RC fbx": { + "ignore": true + } + } + } + } +} diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py index 553427dd17..3297942775 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py @@ -10,7 +10,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Pytest fixture for standardizing key external project file locations. Houses a mock workspace for the external project. Only has enough information -to satisfy a ly_test_tools.lumberyard.asset_processor.AssetProcessor object. +to satisfy a ly_test_tools.o3de.asset_processor.AssetProcessor object. """ diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_fast_scan_setting_backup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_fast_scan_setting_backup_fixture.py index c6f89f7cfa..91b68c99f2 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_fast_scan_setting_backup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_fast_scan_setting_backup_fixture.py @@ -19,8 +19,8 @@ import logging # ly-shared import from automatedtesting_shared.platform_setting import PlatformSetting -from ly_test_tools.lumberyard.pipeline_utils import AP_FASTSCAN_KEY as fast_scan_key -from ly_test_tools.lumberyard.pipeline_utils import AP_FASTSCAN_SUBKEY as fast_scan_subkey +from ly_test_tools.o3de.pipeline_utils import AP_FASTSCAN_KEY as fast_scan_key +from ly_test_tools.o3de.pipeline_utils import AP_FASTSCAN_SUBKEY as fast_scan_subkey logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_idle_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_idle_fixture.py index aa90185d19..580cb025a7 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_idle_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_idle_fixture.py @@ -21,7 +21,7 @@ from . import ap_setup_fixture # Import LyTestTools import ly_test_tools.environment.waiter as waiter -from ly_test_tools.lumberyard.ap_log_parser import APLogParser +from ly_test_tools.o3de.ap_log_parser import APLogParser @pytest.mark.usefixtures("test_assets") diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_missing_dependency_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_missing_dependency_fixture.py index 091355ad4a..47bc2f4ec2 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_missing_dependency_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_missing_dependency_fixture.py @@ -21,7 +21,7 @@ from typing import Dict, List, Tuple, Any, Set from ly_test_tools.environment.file_system import create_backup, restore_backup, unlock_file from automatedtesting_shared import asset_database_utils as db_utils -from ly_test_tools.lumberyard.ap_log_parser import APLogParser +from ly_test_tools.o3de.ap_log_parser import APLogParser from . import ap_setup_fixture as ap_setup_fixture diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_setup_fixture.py index 0b33a4a23b..aa233c517f 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_setup_fixture.py @@ -16,7 +16,7 @@ import os import time import pytest from typing import Dict -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP @pytest.fixture def ap_setup_fixture(request, workspace) -> Dict: diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/asset_processor_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/asset_processor_fixture.py index 36c724a269..fdccbae96d 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/asset_processor_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/asset_processor_fixture.py @@ -18,7 +18,7 @@ import pytest import logging # Import LyTestTools -import ly_test_tools.lumberyard.asset_processor as asset_processor_commands +import ly_test_tools.o3de.asset_processor as asset_processor_commands logger = logging.getLogger(__name__) @@ -28,7 +28,7 @@ def asset_processor(request: pytest.fixture, workspace: pytest.fixture) -> asset """ Sets up usage of the asset proc :param request: - :return: ly_test_tools.lumberyard.asset_processor.AssetProcessor + :return: ly_test_tools.03de.asset_processor.AssetProcessor """ # Initialize the Asset Processor 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 84b343710c..580816e7b5 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 @@ -26,8 +26,8 @@ from . import timeout_option_fixture as timeout from . import ap_config_backup_fixture as config_backup import ly_test_tools.environment.file_system as fs -import ly_test_tools.lumberyard.pipeline_utils as utils -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +import ly_test_tools.o3de.pipeline_utils as utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/clear_moveoutput_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/clear_moveoutput_fixture.py index 7482911548..22288d0645 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/clear_moveoutput_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/clear_moveoutput_fixture.py @@ -15,7 +15,7 @@ Fixture for clearing out 'MoveOutput' folders from \dev and \dev\PROJECT import pytest # Import ly_shared -import ly_test_tools.lumberyard.pipeline_utils as pipeline_utils +import ly_test_tools.o3de.pipeline_utils as pipeline_utils @pytest.fixture diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_builder_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_builder_tests.py index 6cdb955b9c..e3d52e8260 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_builder_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_builder_tests.py @@ -25,8 +25,8 @@ from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_proce from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +import ly_test_tools.o3de.pipeline_utils as utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) # Configuring the logging is done in ly_test_tools at the following location: 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 98d364ee1c..d236e87aa2 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 @@ -36,8 +36,8 @@ from ..ap_fixtures.bundler_batch_setup_fixture \ from ..ap_fixtures.ap_config_backup_fixture import ap_config_backup_fixture as config_backup # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +import ly_test_tools.o3de.pipeline_utils as utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP win_and_mac_platforms = [ASSET_PROCESSOR_PLATFORM_MAP['windows'], ASSET_PROCESSOR_PLATFORM_MAP['mac']] diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests.py index ba5b65e33d..cfd088adc0 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests.py @@ -24,8 +24,8 @@ from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture # Import LyShared from automatedtesting_shared import file_utils as file_utils -from ly_test_tools.lumberyard.ap_log_parser import APLogParser, APOutputParser -import ly_test_tools.lumberyard.pipeline_utils as utils +from ly_test_tools.o3de.ap_log_parser import APLogParser, APOutputParser +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests2.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests2.py index b5e21ec0f8..4f33e0df4e 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests2.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_dependency_tests2.py @@ -24,8 +24,8 @@ from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture # Import LyShared from automatedtesting_shared import file_utils as file_utils -from ly_test_tools.lumberyard.ap_log_parser import APLogParser, APOutputParser -import ly_test_tools.lumberyard.pipeline_utils as utils +from ly_test_tools.o3de.ap_log_parser import APLogParser, APOutputParser +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py index b98853a699..50b3af1438 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py @@ -18,7 +18,7 @@ import os import stat # Import LyTestTools -from ly_test_tools.lumberyard import asset_processor as asset_processor_utils +from ly_test_tools.o3de import asset_processor as asset_processor_utils # Import fixtures from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor @@ -26,8 +26,8 @@ from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture # Import LyShared -from ly_test_tools.lumberyard.ap_log_parser import APLogParser, APOutputParser -import ly_test_tools.lumberyard.pipeline_utils as utils +from ly_test_tools.o3de.ap_log_parser import APLogParser, APOutputParser +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py index 79ad23de92..5c42af2139 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py @@ -19,8 +19,8 @@ import subprocess # Import LyTestTools -from ly_test_tools.lumberyard.asset_processor import AssetProcessor -from ly_test_tools.lumberyard import asset_processor as asset_processor_utils +from ly_test_tools.o3de.asset_processor import AssetProcessor +from ly_test_tools.o3de import asset_processor as asset_processor_utils import ly_test_tools.environment.file_system as fs # Import fixtures @@ -29,8 +29,8 @@ from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture # Import LyShared -from ly_test_tools.lumberyard.ap_log_parser import APLogParser, APOutputParser -import ly_test_tools.lumberyard.pipeline_utils as utils +from ly_test_tools.o3de.ap_log_parser import APLogParser, APOutputParser +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests.py index aecb1ac657..ed5651755c 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests.py @@ -25,8 +25,8 @@ import ly_test_tools.environment.waiter as waiter import ly_test_tools.environment.file_system as fs import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.launchers.launcher_helper as launcher_helper -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP -from ly_test_tools.lumberyard.asset_processor import AssetProcessorError +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de.asset_processor import AssetProcessorError # Import fixtures from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor @@ -38,7 +38,7 @@ from ..ap_fixtures.ap_fast_scan_setting_backup_fixture import ( # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py index 47dfaa6e8a..7c7b6b2452 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py @@ -25,7 +25,7 @@ import ly_test_tools.environment.waiter as waiter import ly_test_tools.environment.file_system as fs import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.launchers.launcher_helper as launcher_helper -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP, ASSET_PROCESSOR_SETTINGS_ROOT_KEY +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP, ASSET_PROCESSOR_SETTINGS_ROOT_KEY # Import fixtures from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor @@ -37,7 +37,7 @@ from ..ap_fixtures.ap_fast_scan_setting_backup_fixture import ( # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_relocator_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_relocator_tests.py index 350885d7b5..2d3872bf31 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_relocator_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_relocator_tests.py @@ -26,8 +26,8 @@ from typing import List import ly_test_tools.builtin.helpers as helpers import ly_test_tools.environment.file_system as fs import ly_test_tools.environment.process_utils as process_utils -from ly_test_tools.lumberyard import asset_processor as asset_processor_utils -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de import asset_processor as asset_processor_utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP # Import fixtures from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor @@ -37,7 +37,7 @@ from ..ap_fixtures.clear_moveoutput_fixture import clear_moveoutput_fixture as c from ..ap_fixtures.clear_testingAssets_dir import clear_testingAssets_dir as clear_testingAssets_dir # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils # Use the following logging pattern to hook all test logging together: logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py index bc77458ce1..6cc3484d96 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py @@ -20,8 +20,8 @@ from typing import List, Tuple from ..ap_fixtures.asset_processor_fixture import asset_processor from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP -from ly_test_tools.lumberyard import asset_processor as asset_processor_utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de import asset_processor as asset_processor_utils # fmt:off from ..ap_fixtures.ap_missing_dependency_fixture \ @@ -32,7 +32,7 @@ from ..ap_fixtures.ap_missing_dependency_fixture \ import ly_test_tools.builtin.helpers as helpers # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils from automatedtesting_shared import asset_database_utils as db_utils # Use the following logging pattern to hook all test logging together: diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py index 8dca973285..7e9f65de60 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py @@ -19,7 +19,7 @@ import subprocess import glob from ly_test_tools.builtin.helpers import * from ly_test_tools.environment.process_utils import * -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py index 594827ee76..b66984666b 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py @@ -18,8 +18,8 @@ from typing import List # Import LyTestTools import ly_test_tools.builtin.helpers as helpers -from ly_test_tools.lumberyard import asset_processor as asset_processor_utils -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP +from ly_test_tools.o3de import asset_processor as asset_processor_utils +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP # Import fixtures from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor @@ -29,7 +29,7 @@ from ..ap_fixtures.ap_config_default_platform_fixture import ap_config_default_p # Import LyShared -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils from automatedtesting_shared import asset_database_utils as asset_db_utils logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_database_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_database_utils.py index 190fdc711e..75df510db1 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_database_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_database_utils.py @@ -16,7 +16,7 @@ import sqlite3 import os from typing import List -import ly_test_tools.lumberyard.pipeline_utils as pipeline_utils +import ly_test_tools.o3de.pipeline_utils as pipeline_utils # Index for ProductID in Products table in DB PRODUCT_ID_INDEX = 0 diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py index 722b0aa0be..1fe2771370 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py @@ -12,7 +12,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # Built-in Imports from __future__ import annotations -# Lumberyard Imports +# Open 3D Engine Imports import azlmbr.bus as bus import azlmbr.asset as azasset import azlmbr.math as math diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py index e3ef1a3ab4..1887d5736e 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py @@ -20,7 +20,7 @@ import ly_test_tools.environment.file_system as file_system import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter -from ly_test_tools.lumberyard.asset_processor import AssetProcessor +from ly_test_tools.o3de.asset_processor import AssetProcessor from ly_test_tools.launchers.exceptions import WaitTimeoutError from ly_test_tools.log.log_monitor import LogMonitor, LogMonitorException diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py index cd78409b72..3e009563b8 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py @@ -16,7 +16,7 @@ from typing import List, Tuple, Union # Helper file Imports import utils -# Lumberyard Imports +# Open 3D Engine Imports import azlmbr import azlmbr.bus as bus import azlmbr.editor as editor diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py index 16acac0808..64a19aafdf 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py @@ -17,7 +17,7 @@ import time from typing import Sequence from .report import Report -# Lumberyard specific imports +# Open 3D Engine specific imports import azlmbr.legacy.general as general import azlmbr.legacy.settings as settings diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py index 77236797c7..05614296b1 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py @@ -296,8 +296,8 @@ def get_set_test(entity: object, component_index: int, path: str, value: object) def get_set_property_test(ly_object: object, attribute_name: str, value: object, expected_result: object = None) -> bool: """ - Used to set and validate BehaviorContext property changes in Lumberyard objects - :param ly_object: The lumberyard object to test + Used to set and validate BehaviorContext property changes in Open 3D Engine objects + :param ly_object: The Open 3D Engine object to test :param attribute_name: property (attribute) name in the BehaviorContext :param value: new value for the variable being changed in the component :param expected_result: (optional) check the result against a specific expected value other than the one set @@ -410,7 +410,7 @@ def set_editor_settings_by_path(path, value, is_bool = False): def get_component_type_id_map(component_name_list): """ Given a list of component names, returns a map of component name -> component type id - :param component_name_list: The lumberyard object to test + :param component_name_list: The Open 3D Engine object to test :return: Dictionary of component name -> component type id pairs """ # Remove any duplicates so we don't have to query for the same TypeId diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/platform_setting.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/platform_setting.py index a0eccde29a..c5596d280b 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/platform_setting.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/platform_setting.py @@ -16,7 +16,7 @@ import pytest import logging from typing import Optional, Any -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py index 3186eac245..6dc59d9be0 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py @@ -57,7 +57,7 @@ class AssetBrowserSearchFilteringTest(EditorTestHelper): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_TreeNavigation.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_TreeNavigation.py index 0a9ec689bd..dc0565d100 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_TreeNavigation.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_TreeNavigation.py @@ -49,7 +49,7 @@ class AssetBrowserTreeNavigationTest(EditorTestHelper): 6) Verify if the ScrollBar appears after expanding the tree Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py index f5c61d10f4..cdc204043e 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py @@ -58,7 +58,7 @@ class AddDeleteComponentsTest(EditorTestHelper): 7) Undo deletion of component Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py index 7393153f45..d6d284664a 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py @@ -58,7 +58,7 @@ class AddRemoveInputEventsTest(EditorTestHelper): 10) Close Asset Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py index cac5cdd42b..673e473390 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py @@ -55,7 +55,7 @@ class TestAltitudeFilterComponentAndOverrides(EditorTestHelper): 8) Instance counts post-filter are verified. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py index 7325a75d72..7e76a80cc4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py @@ -48,7 +48,7 @@ class TestAltitudeFilterShapeSample(EditorTestHelper): 6) Instance counts post-filter are verified. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py index 96338a9ab2..786348bcc6 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py @@ -57,7 +57,7 @@ class TestAssetListCombiner(EditorTestHelper): Combiner component to force a refresh, and validate instance count Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py index a1369706f6..85d4edfe6d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py @@ -52,7 +52,7 @@ class TestAssetWeightSelectorSortByWeight(EditorTestHelper): 8) Change sort values and validate instance count Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py index 9212cf4f9b..82b2fc8407 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py @@ -44,7 +44,7 @@ class TestDistanceBetweenFilterComponentOverrides(EditorTestHelper): expected instance counts with a few different Radius values Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py index ce2869bf8a..9f15215358 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py @@ -42,7 +42,7 @@ class TestDistanceBetweenFilterComponent(EditorTestHelper): 5-8) Add the Distance Between Filter, and validate expected instance counts with a few different Radius values Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py index b9940eab87..f25fbb2b6d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py @@ -49,7 +49,7 @@ class TestDynamicSliceInstanceSpawnerEmbeddedEditor(EditorTestHelper): 6) Save and export to engine Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py index e87a341cca..8af75f2d17 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py @@ -49,7 +49,7 @@ class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper): 6) Save and export to engine Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py index 583801f83c..507d8f505e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py @@ -49,7 +49,7 @@ class TestInstanceSpawnerPriority(EditorTestHelper): 6) Validate instance counts in the spawner area Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py index 5a290782cc..2e6992d7e2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py @@ -59,7 +59,7 @@ class TestVegLayerBlenderCreated(EditorTestHelper): 7) Export to engine Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py index c542d6a4a2..53c29344e1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py @@ -48,7 +48,7 @@ class TestLayerBlocker(EditorTestHelper): 7. Post-blocker instance counts are validated Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py index 0495b9f428..a5d04a3b6a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py @@ -45,7 +45,7 @@ class TestMeshSurfaceTagEmitter(EditorTestHelper): 5) Make sure Mesh Surface Tag Emitter is enabled after adding Mesh Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py index 26aaf2d1f2..e0011ea28f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py @@ -42,7 +42,7 @@ class TestMeshSurfaceTagEmitter(EditorTestHelper): 3) Add/ remove Surface Tags Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py index 5d8a070fff..d2d112907a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py @@ -50,7 +50,7 @@ class TestPositionModifierAutoSnapToSurface(EditorTestHelper): 8) Validate instance counts on top of and inside the sphere mesh with Auto Snap to Surface disabled Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py index 144d1484ed..bd2a2df16f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py @@ -52,7 +52,7 @@ class TestPositionModifierComponentAndOverrides(EditorTestHelper): are validated Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py index 1837d533a4..4d904e9623 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py @@ -52,7 +52,7 @@ class TestShapeIntersectionFilter(EditorTestHelper): 7) Remove the shape reference on the Intersection Filter and validate instance counts Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py index 1f2b0dbdb6..6f3b1d5629 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py @@ -55,7 +55,7 @@ class TestSlopeFilterComponentAndOverrides(EditorTestHelper): 9) Instance counts are validated Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py index 3e03b0b585..b164d34973 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py @@ -51,7 +51,7 @@ class TestSurfaceMaskFilterMultipleOverrides(EditorTestHelper): 7) Test 3 setup and validation: Inclusion tag matching surface c is set on a single descriptor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. 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 8e36e1aa1d..868d9d08e3 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py @@ -65,7 +65,7 @@ class TestGradientPreviewSettings(EditorTestHelper): 10) Create entity with Perlin Noise Gradient and verify gradient position after clearing pinned entity Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py index 5581bb32e4..d94c197fea 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py @@ -42,7 +42,7 @@ class TestGradientSampling(EditorTestHelper): field in Gradient Modifier Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py index b82dbe7ab8..a37ae97361 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py @@ -42,7 +42,7 @@ class TestGradientSurfaceTagEmitter(EditorTestHelper): 3) Add/ remove Surface Tags Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py index a55fd7a843..31f0ee2693 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py @@ -48,7 +48,7 @@ class TestGradientTransform_ComponentIncompatibleWithExpectedGradients(EditorTes 5) Make sure all newly added components are disabled Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py index 9c2fd3b9b9..0542e5e1b4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py @@ -46,7 +46,7 @@ class TestGradientTransform_ComponentIncompatibleWithSpawners(EditorTestHelper): 5) Make sure newly added component is disabled Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py index b53a328c52..22518e61be 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py @@ -48,7 +48,7 @@ class TestGradientTransformFrequencyZoom(EditorTestHelper): 5) Verify if the frequency value is set to higher value Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py index 337f412719..6b4a8bf17c 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py @@ -45,7 +45,7 @@ class TestImageGradient(EditorTestHelper): 3) Assign the newly processed gradient image as Image asset. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py b/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py index c32acf1daa..e5cee76415 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py @@ -62,7 +62,7 @@ def C12712452_ScriptCanvas_CollisionEvents(): 8) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py b/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py index eccde91046..808f1e4c31 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py @@ -93,7 +93,7 @@ def C12712454_ScriptCanvas_OverlapNodeVerification(): 13) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py b/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py index 1092c94cc5..a5c827edb9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py @@ -63,7 +63,7 @@ def C12712455_ScriptCanvas_ShapeCastVerification(): 8) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py b/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py index 22f63ab582..b84adcd246 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py @@ -82,7 +82,7 @@ def C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(): 8) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py index b27aaf09db..481c1fa43c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py @@ -69,7 +69,7 @@ def C12868580_ForceRegion_SplineModifiedTransform(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py b/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py index d8fb9a67e0..a9fb92b4fa 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py @@ -49,7 +49,7 @@ def C12905527_ForceRegion_MagnitudeDeviation(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py b/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py index a555176381..d3fe35b1cd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py @@ -41,7 +41,7 @@ def run(): 6) Verify there is warning in the logs Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py b/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py index adfbce0ebf..d4bbdca52f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py @@ -50,7 +50,7 @@ def C13351703_COM_NotIncludeTriggerShapes(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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 critical_results. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py b/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py index 729cc9c9cc..db497dabc6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py @@ -54,7 +54,7 @@ def C13895144_Ragdoll_ChangeLevel(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py index 4beca8845d..4837de3538 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py @@ -57,7 +57,7 @@ def C14195074_ScriptCanvas_PostUpdateEvent(): 11) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py b/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py index 97d83dae62..2bc620e0c1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py @@ -65,7 +65,7 @@ def C14654882_Ragdoll_ragdollAPTest(): 5.3) Search the recorded lines for an Unexpected Line Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py index 5c6c4c219d..43d4d0e905 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py @@ -37,7 +37,7 @@ def C14861500_DefaultSetting_ColliderShape(): 4) Check value of Shape property on PhysX Collider Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -51,7 +51,7 @@ def C14861500_DefaultSetting_ColliderShape(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.legacy.general as general PHYSICS_ASSET_INDEX = 7 # Hardcoded enum index value for Shape property diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py index faa7618e7b..a7fc5cf3b5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py @@ -42,7 +42,7 @@ def run(): 6) The physics asset in PhysX Collider component is auto-assigned. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py index b4d92e3691..94c1d8e404 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py @@ -41,7 +41,7 @@ def C14861502_PhysXCollider_AssetAutoAssigned(): 6) The physics asset in PhysX Collider component is auto-assigned. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -59,7 +59,7 @@ def C14861502_PhysXCollider_AssetAutoAssigned(): from editor_entity_utils import EditorEntity as Entity from asset_utils import Asset - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.legacy.general as general MESH_ASSET_PATH = os.path.join("Objects", "SphereBot", "r0-b_body.cgf") diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py b/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py index aa2fff43cf..0a6962a31c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py @@ -46,7 +46,7 @@ def run(): 7) Enter GameMode and check for warnings Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -65,7 +65,7 @@ def run(): from editor_entity_utils import EditorEntity as Entity from asset_utils import Asset - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.asset as azasset # Asset paths diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py index 4c9c7de263..ea62be9768 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py @@ -59,7 +59,7 @@ def C14902097_ScriptCanvas_PreUpdateEvent(): 11) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py b/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py index 669ff3d84d..fc3ae2bc18 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py @@ -70,7 +70,7 @@ def C14902098_ScriptCanvas_PostPhysicsUpdate(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py b/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py index b38dde5fc8..33a26d9433 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py @@ -55,7 +55,7 @@ def C14976307_Gravity_SetGravityWorks(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py b/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py index 9b065af7ce..ea01c71310 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py @@ -86,7 +86,7 @@ def C14976308_ScriptCanvas_SetKinematicTargetTransform(): 13) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py index 29975456db..f637981b1d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py @@ -95,7 +95,7 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after(): 5) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py index ea77a083ff..fcbc0ff723 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py @@ -88,7 +88,7 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before(): 4) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py b/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py index 757e598ed0..f393ddf527 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py @@ -136,7 +136,7 @@ def C15096735_Materials_DefaultLibraryConsistency(): 4) Exit game mode / Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py index 5ff8a8110b..c69b722e27 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py @@ -44,7 +44,7 @@ def C15096740_Material_LibraryUpdatedCorrectly(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -63,7 +63,7 @@ def C15096740_Material_LibraryUpdatedCorrectly(): from editor_entity_utils import EditorEntity from asset_utils import Asset - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.asset as azasset # Constants diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py b/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py index 102d452076..998d21067b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py @@ -57,7 +57,7 @@ def C15308217_NoCrash_LevelSwitch(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py b/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py index 6364329ce0..a6ddb73438 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py @@ -101,7 +101,7 @@ def C15308221_Material_ComponentsInSyncWithLibrary(): 7) Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py index 5b6e803ade..d2db2239c2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py @@ -108,7 +108,7 @@ def C15425935_Material_LibraryUpdatedAcrossLevels(): 4) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py b/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py index 8aaac05f15..8b0fba05b1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py @@ -103,7 +103,7 @@ def C15563573_Material_AddModifyDeleteOnCharacterController(): to change in mesh surfaces, during the game mode. - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py b/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py index 725dd0e136..2eb7759ead 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py @@ -52,7 +52,7 @@ def C15845879_ForceRegion_HighLinearDampingForce(): 8) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py index 8b5af5df99..a3115ceeab 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py @@ -42,7 +42,7 @@ def run(): 6) Verify there are no errors/warnings in the entity outliner Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py index ee3a819544..76b05a4ce9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py @@ -45,7 +45,7 @@ def C18243580_Joints_Fixed2BodiesConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py index e99f8d7c82..ffc48f6e3c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py @@ -44,7 +44,7 @@ def C18243581_Joints_FixedBreakable(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py index bbc10939fc..6c0f98b694 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py @@ -46,7 +46,7 @@ def C18243582_Joints_FixedLeadFollowerCollide(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py index 1baf75141f..fd1fb02557 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py @@ -48,7 +48,7 @@ def C18243583_Joints_Hinge2BodiesConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py index 45fc4ea475..c1ed3328a7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py @@ -48,7 +48,7 @@ def C18243584_Joints_HingeSoftLimitsConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py index ed96432f8a..515c51eb0b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py @@ -48,7 +48,7 @@ def C18243585_Joints_HingeNoLimitsConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py index 1ee1f97e2e..d673885ea1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py @@ -45,7 +45,7 @@ def C18243586_Joints_HingeLeadFollowerCollide(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py index 46846793a0..d58d618b99 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py @@ -46,7 +46,7 @@ def C18243587_Joints_HingeBreakable(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py index f460e273cf..1ead30c65e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py @@ -47,7 +47,7 @@ def C18243588_Joints_Ball2BodiesConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py index c9ca603f53..d29c472fcd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py @@ -49,7 +49,7 @@ def C18243589_Joints_BallSoftLimitsConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py index 816cce1f0b..d3a0c8e82c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py @@ -50,7 +50,7 @@ def C18243590_Joints_BallNoLimitsConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py index 1ac2fbebd9..ba8967acab 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py @@ -45,7 +45,7 @@ def C18243591_Joints_BallLeadFollowerCollide(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py index 6a2c1ab9cf..2b07d63a43 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py @@ -45,7 +45,7 @@ def C18243592_Joints_BallBreakable(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py index c1c8793830..1ebdaf73b3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py @@ -49,7 +49,7 @@ def C18243593_Joints_GlobalFrameConstrained(): 7) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py index a2d8755a08..46f1535bf4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py @@ -122,7 +122,7 @@ def C18977601_Material_FrictionCombinePriority(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py index 3d978e6fed..800ad38264 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py @@ -122,7 +122,7 @@ def C18981526_Material_RestitutionCombinePriority(): 10) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py b/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py index 0d32daa320..8dbee3cd4e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py @@ -40,7 +40,7 @@ def run(): 3) Enter game mode Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py b/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py index d9eb6d3d64..141c9fb4db 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py @@ -40,7 +40,7 @@ def run(): 3) Enter game mode Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py index 451f2f727b..8910a4ded4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py @@ -43,7 +43,7 @@ def C19578018_ShapeColliderWithNoShapeComponent(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -60,7 +60,7 @@ def C19578018_ShapeColliderWithNoShapeComponent(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.bus as bus import azlmbr.editor as editor diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py b/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py index 2d8b205019..5c940264ff 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py @@ -41,7 +41,7 @@ def C19578021_ShapeCollider_CanBeAdded(): 6) Verify there are no warnings in the entity outliner Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -56,7 +56,7 @@ def C19578021_ShapeCollider_CanBeAdded(): from utils import Tracer from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.legacy.general as general helper.init_idle() diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py b/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py index 355e7571a0..3296b32fc9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py @@ -37,7 +37,7 @@ def C19723164_ShapeColliders_WontCrashEditor(): 4) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -51,7 +51,7 @@ def C19723164_ShapeColliders_WontCrashEditor(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.legacy.general as general def idle_editor_for_check(): diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py index ef21ad8584..086f045eec 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py @@ -60,7 +60,7 @@ def C3510642_Terrain_NotCollideWithTerrain(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py b/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py index 5a517e98f6..765f7cbfe0 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py @@ -84,7 +84,7 @@ def C3510644_Collider_CollisionGroups(): 6) close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. - The level for this test uses two PhysX Terrains and must be run with cmdline argument "-autotest_mode" diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py b/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py index 0a1ab995a8..aae538527a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py @@ -168,7 +168,7 @@ def C4044455_Material_libraryChangesInstantly(): 9) Exit game mode Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py index aa1b3ad37d..80b7c6443f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py @@ -87,7 +87,7 @@ def C4044456_Material_FrictionCombine(): 10) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py index 7f33179bab..856a663fe6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py @@ -92,7 +92,7 @@ def C4044457_Material_RestitutionCombine(): 11) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py b/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py index e1f4c09977..ab4a8c1574 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py @@ -78,7 +78,7 @@ def C4044459_Material_DynamicFriction(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py b/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py index b0d0f7fdad..9918c5fac6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py @@ -76,7 +76,7 @@ def C4044460_Material_StaticFriction(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py b/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py index 210fa40c1e..a11cfd47f6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py @@ -83,7 +83,7 @@ def C4044461_Material_Restitution(): 11) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py b/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py index 0513f62e0c..3c3b777a69 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py @@ -62,7 +62,7 @@ def C4044694_Material_EmptyLibraryUsesDefault(): 7) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py index 163f9f22a4..cc2caaf3b6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py @@ -47,7 +47,7 @@ def run(): 6) Check if multiple material slots show up under Materials section in the PhysX Collider component Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py b/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py index 9ae4122eef..46a6b04edf 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py @@ -103,7 +103,7 @@ def C4044697_Material_PerfaceMaterialValidation(): 14) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py b/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py index d4c23a296b..49673da217 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py @@ -86,7 +86,7 @@ def C4888315_Material_AddModifyDeleteOnCollider(): 5) Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py index 3f04f73cf6..80a83e0222 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py @@ -72,7 +72,7 @@ def C4925577_Materials_MaterialAssignedToTerrain(): 11) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py index 609c989851..87f94c6dd4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py @@ -87,7 +87,7 @@ def C4925579_Material_AddModifyDeleteOnTerrain(): 5) Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py b/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py index f8f33f5cff..abb97da143 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py @@ -61,7 +61,7 @@ def C4925580_Material_RagdollBonesMaterial(): 8) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py b/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py index b4cf3c704a..0a309133a4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py @@ -88,7 +88,7 @@ def C4925582_Material_AddModifyDeleteOnRagdollBones(): 5) Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py b/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py index 3c19665dbb..90feb352b3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py @@ -49,7 +49,7 @@ def C4976194_RigidBody_PhysXComponentIsValid(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py index 1dd9cfd45f..287bc75214 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py @@ -53,7 +53,7 @@ def C4976195_RigidBodies_InitialLinearVelocity(): 9) Closes the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py index 07c586c24e..82b8df29f7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py @@ -65,7 +65,7 @@ def C4976197_RigidBodies_InitialAngularVelocity(): 12) Closes the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py index ed87276546..e8086e4965 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py @@ -96,7 +96,7 @@ def C4976201_RigidBody_MassIsAssigned(): 11) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py b/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py index c982a96b2a..f74119dd28 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py @@ -119,7 +119,7 @@ def C4976202_RigidBody_StopsWhenBelowKineticThreshold(): 12) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py b/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py index 3413d6f85b..fae8ea9a3a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py @@ -57,7 +57,7 @@ def C4976204_Verify_Start_Asleep_Condition(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py b/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py index cbe997aff2..a8227b6b1f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py @@ -59,7 +59,7 @@ def C4976206_RigidBodies_GravityEnabledActive(): 8) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py b/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py index e64ebfdea2..8003f495c8 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py @@ -54,7 +54,7 @@ def C4976207_PhysXRigidBodies_KinematicBehavior(): 8) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py b/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py index 241c9849f4..9f67751d67 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py @@ -80,7 +80,7 @@ def C4976209_RigidBody_ComputesCOM(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py b/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py index d15b3eb15c..7cda1bf6f0 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py @@ -65,7 +65,7 @@ def C4976210_COM_ManualSetting(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py b/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py index cc2d6abe1f..c9b9dfb89f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py @@ -46,7 +46,7 @@ def C4976227_Collider_NewGroup(): 5) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py index 07d6b14400..8c1527fc89 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py @@ -44,7 +44,7 @@ def C4976236_AddPhysxColliderComponent(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py b/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py index 1719b7108a..93d1981187 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py @@ -57,7 +57,7 @@ def C4976242_Collision_SameCollisionlayerSameCollisiongroup(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py b/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py index 931708a73c..a4a89fcdec 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py @@ -61,7 +61,7 @@ def C4976243_Collision_SameCollisionGroupDiffCollisionLayers(): 8) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py b/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py index de2455e779..2770b0142c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py @@ -57,7 +57,7 @@ def C4976244_Collider_SameGroupSameLayerCollision(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py index a32e57fe46..c70154f0be 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py @@ -62,7 +62,7 @@ def C4976245_PhysXCollider_CollisionLayerTest(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py index c9c12476b4..a05550ba90 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py @@ -62,7 +62,7 @@ def C4982593_PhysXCollider_CollisionLayerTest(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py b/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py index 06d6b264ea..86d862d547 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py @@ -70,7 +70,7 @@ def C4982595_Collider_TriggerDisablesCollision(): 11) Exit game mode and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py index b116ea4b06..cbe8d7d47e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py @@ -80,7 +80,7 @@ def C4982797_Collider_ColliderOffset(): 7) Exit game mode and editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py index 72d976301e..f64d762b3b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py @@ -83,7 +83,7 @@ def C4982798_Collider_ColliderRotationOffset(): 6) Exit game mode and editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py index 9c0723e3ba..d38bf780d4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py @@ -40,7 +40,7 @@ def C4982800_PhysXColliderShape_CanBeSelected(): 6) Verify they have been changed Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -54,7 +54,7 @@ def C4982800_PhysXColliderShape_CanBeSelected(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.math as math SPHERE_SHAPETYPE_ENUM = 0 diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py index 2e7c774a05..940f774088 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py @@ -40,7 +40,7 @@ def C4982801_PhysXColliderShape_CanBeSelected(): 6) Verify they have been changed Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -54,7 +54,7 @@ def C4982801_PhysXColliderShape_CanBeSelected(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.math as math BOX_SHAPETYPE_ENUM = 1 diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py index 92a1909c91..eba549abde 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py @@ -40,7 +40,7 @@ def C4982802_PhysXColliderShape_CanBeSelected(): 6) Verify they have been changed Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -54,7 +54,7 @@ def C4982802_PhysXColliderShape_CanBeSelected(): from utils import TestHelper as helper from editor_entity_utils import EditorEntity as Entity - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.math as math CAPSULE_SHAPETYPE_ENUM = 2 diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py b/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py index 72d01658c7..da201ddeda 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py @@ -49,7 +49,7 @@ def C4982803_Enable_PxMesh_Option(): 7) Verify that the entity falls on the ground and collides with the terrain. Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -69,7 +69,7 @@ def C4982803_Enable_PxMesh_Option(): from asset_utils import Asset import azlmbr.math as math - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr import azlmbr.legacy.general as general diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py b/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py index a8b2065455..f012fe73c0 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py @@ -62,7 +62,7 @@ def C5340400_RigidBody_ManualMomentOfInertia(): 9) Close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py b/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py index aad12c9000..10ebcacdb7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py @@ -53,7 +53,7 @@ def C5689522_Physxterrain_AddPhysxterrainNoEditorCrash(): 7) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py b/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py index f05c50c2b4..b00821343b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py @@ -55,7 +55,7 @@ def C5689524_MultipleTerrains_CheckWarningInConsole(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py b/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py index 936d4235ab..f540cae081 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py @@ -55,7 +55,7 @@ def C5689528_Terrain_MultipleTerrainComponents(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py b/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py index bba46c2cb6..2fbf21fb72 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py @@ -53,7 +53,7 @@ def C5689529_Verify_Terrain_RigidBody_Collider_Mesh(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py index 7ad0770548..c8e5d6873b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py @@ -60,7 +60,7 @@ def C5689531_Warning_TerrainSliceTerrainComponent(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py b/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py index d32e47b965..87bc4812b2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py @@ -60,7 +60,7 @@ def C5932040_ForceRegion_CubeExertsWorldForce(): 11) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py index 2274739fba..d78f0f386a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py @@ -61,7 +61,7 @@ def C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py b/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py index d8fa95f636..a3f6de6a5f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py @@ -66,7 +66,7 @@ def C5932042_PhysXForceRegion_LinearDamping(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py index e8000e9b33..4f8121e254 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py @@ -60,7 +60,7 @@ def C5932044_ForceRegion_PointForceOnRigidBody(): 12) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py b/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py index bf12145f52..4cb71ab54c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py @@ -66,7 +66,7 @@ def C5932045_ForceRegion_Spline(): 8) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py b/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py index df6e2d7f29..42020c78b7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py @@ -59,7 +59,7 @@ def C5959760_PhysXForceRegion_PointForceExertion(): 6) Closes the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py b/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py index d6a0776090..af9af57363 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py @@ -56,7 +56,7 @@ def C5959761_ForceRegion_PhysAssetExertsPointForce(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py b/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py index 8dddc8866d..e09b58ecdc 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py @@ -60,7 +60,7 @@ def C5959810_ForceRegion_ForceRegionCombinesForces(): 9) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py b/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py index 640424ff39..7c7c11f548 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py @@ -56,7 +56,7 @@ def C5968760_ForceRegion_CheckNetForceChange(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py b/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py index e163cae4de..d79954d26f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py @@ -75,7 +75,7 @@ def C6032082_Terrain_MultipleResolutionsValid(): 2) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py b/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py index 4f26ce9661..825b8287d1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py @@ -58,7 +58,7 @@ def C6090546_ForceRegion_SliceFileInstantiates(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py b/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py index 7dfeb7e846..a62a673b9f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py @@ -67,7 +67,7 @@ def C6090547_ForceRegion_ParentChildForceRegions(): 10) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py index d082f5e4eb..c85dc6a273 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py @@ -65,7 +65,7 @@ def C6090550_ForceRegion_WorldSpaceForceNegative(): 7) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py index 7d71caada3..45f9b21522 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py @@ -65,7 +65,7 @@ def C6090551_ForceRegion_LocalSpaceForceNegative(): 7) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py index e599f3d401..5751f55b0c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py @@ -64,7 +64,7 @@ def C6090552_ForceRegion_LinearDampingNegative(): 7) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py index ec88d5ea67..3c995bca62 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py @@ -58,7 +58,7 @@ def C6090553_ForceRegion_SimpleDragForceOnRigidBodies(): 11) Exits game mode and editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py index 9e87435801..0ea8ca2e4b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py @@ -65,7 +65,7 @@ def C6090554_ForceRegion_PointForceNegative(): 7) Exit game mode and close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py index a5a1953d6a..dfa992bc21 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py @@ -61,7 +61,7 @@ def C6090555_ForceRegion_SplineFollowOnRigidBodies(): 9) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py b/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py index 4db52684db..5e475a4c4c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py @@ -53,7 +53,7 @@ def C6131473_StaticSlice_OnDynamicSliceSpawn(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py b/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py index 9ac3b7facf..f88e07bf86 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py @@ -56,7 +56,7 @@ def C6224408_ScriptCanvas_EntitySpawn(): 8) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py b/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py index af2321b853..64baa81140 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py @@ -61,7 +61,7 @@ def C6274125_ScriptCanvas_TriggerEvents(): 6) Close the editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py b/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py index 9516f3366e..2b0168a2fe 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py @@ -85,7 +85,7 @@ def C6321601_Force_HighValuesDirectionAxes(): Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the Open 3D Engine Editor command terminal - Aed 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. diff --git a/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py index a23aa833d9..9eeb1ee1da 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py @@ -16,7 +16,7 @@ from xml.etree import ElementTree class Physmaterial_Editor: """ - This class is used to adjust physmaterial files for use with Lumberyard. + This class is used to adjust physmaterial files for use with Open 3D Engine. NOTEWORTHY: - Must use save_changes() for library modifications to take affect @@ -177,7 +177,7 @@ class Physmaterial_Editor: @staticmethod def _get_combine_id(combine_name): # type: (str) -> int - # Maps the Combine mode to its enumerated value used by the Lumberyard Editor + # Maps the Combine mode to its enumerated value used by the Open 3D Engine Editor combine_dictionary = {"Average": "0", "Minimum": "1", "Maximum": "2", "Multiply": "3"} if combine_name not in combine_dictionary: raise ValueError("Invalid Combine Value given. {} is not in combine map".format(combine_name)) diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py index c75a1121e7..666b4910a1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py @@ -46,7 +46,7 @@ def run(): 6) Close Editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py index 9df8fd4fb1..3b54c0de72 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py @@ -39,7 +39,7 @@ def Docking_Pane(): 5) Close Script Canvas window Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -55,7 +55,7 @@ def Docking_Pane(): from utils import TestHelper as helper import pyside_utils - # Lumberyard imports + # Open 3D Engine imports import azlmbr.legacy.general as general # Pyside imports diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py index 5091e05c20..4ea4d791dd 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py @@ -42,7 +42,7 @@ def Opening_Closing_Pane(): 7) Close Script Canvas window Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -58,7 +58,7 @@ def Opening_Closing_Pane(): from utils import TestHelper as helper import pyside_utils - # Lumberyard Imports + # Open 3D Engine Imports import azlmbr.legacy.general as general # Pyside imports diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py index 9378ad8aa8..216ef4fb7d 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py @@ -39,7 +39,7 @@ def Resizing_Pane(): 6) Close Script Canvas window Note: - - This test file must be called from the Lumberyard Editor command terminal + - 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. @@ -55,7 +55,7 @@ def Resizing_Pane(): from utils import TestHelper as helper import pyside_utils - # Lumberyard imports + # Open 3D Engine imports import azlmbr.legacy.general as general # Pyside imports diff --git a/AutomatedTesting/Gem/PythonTests/streaming/benchmark/asset_load_benchmark_test.py b/AutomatedTesting/Gem/PythonTests/streaming/benchmark/asset_load_benchmark_test.py index 96d8b00429..e92ec16b79 100755 --- a/AutomatedTesting/Gem/PythonTests/streaming/benchmark/asset_load_benchmark_test.py +++ b/AutomatedTesting/Gem/PythonTests/streaming/benchmark/asset_load_benchmark_test.py @@ -355,7 +355,7 @@ class TestBenchmarkAssetLoads(object): # Load 650 MB from a single root 10MB asset that has 64 dependent 10MB assets Benchmark('10mb_64x1', 1), # Load 650 MB from a single root 10MB asset where each asset has 1 dependent 10MB asset 64 levels deep - # (Currently removed because it crashes Lumberyard, re-enable once LY can handle it - SPEC-1314) + # (Currently removed because it crashes Open 3D Engine, re-enable once LY can handle it - SPEC-1314) #Benchmark('10mb_1x64', 1), # The second set of benchmarks measures the load time effects of different quantities of parallel asset loads. diff --git a/CMakeLists.txt b/CMakeLists.txt index dfc299e144..c09cfc9588 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# Cmake version 3.17 is the minimum version needed for all of lumberyard's supported platforms +# Cmake version 3.17 is the minimum version needed for all of Open 3D Engine's supported platforms cmake_minimum_required(VERSION 3.19) # CMP0111 introduced in 3.19 has a bug that produces the policy to warn every time there is an @@ -23,17 +23,22 @@ endif() include(cmake/Version.cmake) +set(INSTALLED_ENGINE TRUE) + if(NOT PROJECT_NAME) project(O3DE LANGUAGES C CXX VERSION ${LY_VERSION_STRING} ) + + set(INSTALLED_ENGINE FALSE) endif() include(cmake/Initialize.cmake) include(cmake/FileUtil.cmake) include(cmake/PAL.cmake) include(cmake/PALTools.cmake) +include(cmake/Install.cmake) include(cmake/Configurations.cmake) # Requires to be after PAL so we get platform variable definitions include(cmake/Dependencies.cmake) include(cmake/Deployment.cmake) @@ -54,9 +59,13 @@ include(cmake/CMakeFiles.cmake) # Add the projects first so the Launcher can find them include(cmake/Projects.cmake) -# Add the rest of the targets -add_subdirectory(Code) -add_subdirectory(Gems) +if(NOT INSTALLED_ENGINE) + # Add the rest of the targets + add_subdirectory(Code) + add_subdirectory(Gems) +else() + ly_find_o3de_packages() +endif() set(enabled_platforms ${PAL_PLATFORM_NAME} @@ -98,7 +107,7 @@ foreach(external_directory ${LY_EXTERNAL_SUBDIRS}) add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/${directory_name}-${full_directory_hash}) endforeach() -# The following steps have to be done after all targets were registered: +# The following steps have to be done after all targets are registered: # 1. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls # to provide applications with the filenames of gem modules to load # This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIE as MANUALLY_ADDED_DEPENDENCIES @@ -115,4 +124,8 @@ endif() # the dependencies include(cmake/RuntimeDependencies.cmake) # 5. Perform test impact framework post steps once all of the targets have been enumerated -ly_test_impact_post_step() \ No newline at end of file +ly_test_impact_post_step() +# 6. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine +if(NOT INSTALLED_ENGINE) + ly_setup_o3de_install() +endif() \ No newline at end of file diff --git a/Code/CryEngine/Cry3DEngine/3dEngine.cpp b/Code/CryEngine/Cry3DEngine/3dEngine.cpp index 34472fa6b4..1050916423 100644 --- a/Code/CryEngine/Cry3DEngine/3dEngine.cpp +++ b/Code/CryEngine/Cry3DEngine/3dEngine.cpp @@ -1675,9 +1675,11 @@ bool C3DEngine::IsTessellationAllowedForShadowMap(const SRenderingPassInfo& pass default: return false; } -#endif //#ifdef MESH_TESSELLATION_ENGINE +#else return false; + +#endif //#ifdef MESH_TESSELLATION_ENGINE } void C3DEngine::SetPhysMaterialEnumerator(IPhysMaterialEnumerator* pPhysMaterialEnumerator) diff --git a/Code/CryEngine/Cry3DEngine/CZBufferCuller.cpp b/Code/CryEngine/Cry3DEngine/CZBufferCuller.cpp index 7aa7509ce3..381c6b8058 100644 --- a/Code/CryEngine/Cry3DEngine/CZBufferCuller.cpp +++ b/Code/CryEngine/Cry3DEngine/CZBufferCuller.cpp @@ -127,10 +127,6 @@ bool CZBufferCuller::IsBoxVisible(const AABB& objBox, [[maybe_unused]] uint32* c return Rasterize<2>(Verts, 8); } return Rasterize<0>(Verts, 8); - - ++m_ObjectsTestedAndRejected; - - return false; } static int sh = 8; @@ -197,4 +193,4 @@ void CZBufferCuller::GetMemoryUsage(ICrySizer* pSizer) const { SIZER_COMPONENT_NAME(pSizer, "CoverageBuffer"); pSizer->AddObject(m_ZBuffer, sizeof(TZBZexel) * m_SizeX * m_SizeY); -} \ No newline at end of file +} diff --git a/Code/CryEngine/Cry3DEngine/CZBufferCuller.h b/Code/CryEngine/Cry3DEngine/CZBufferCuller.h index 07ea23e893..f5e01abc68 100644 --- a/Code/CryEngine/Cry3DEngine/CZBufferCuller.h +++ b/Code/CryEngine/Cry3DEngine/CZBufferCuller.h @@ -97,7 +97,10 @@ protected: { return true; } - MinX = 0; + else + { + MinX = 0; + } } if (MaxX > m_SizeX) { @@ -105,7 +108,10 @@ protected: { return true; } - MaxX = m_SizeX; + else + { + MaxX = m_SizeX; + } } if (MinY < 0) { @@ -113,7 +119,10 @@ protected: { return true; } - MinY = 0; + else + { + MinY = 0; + } } if (MaxY > m_SizeY) { @@ -121,7 +130,10 @@ protected: { return true; } - MaxY = m_SizeY; + else + { + MaxY = m_SizeY; + } } if constexpr (ROTATE == 2) { diff --git a/Code/CryEngine/Cry3DEngine/MaterialHelpers.cpp b/Code/CryEngine/Cry3DEngine/MaterialHelpers.cpp index ceea4756e0..a9a2c90cb2 100644 --- a/Code/CryEngine/Cry3DEngine/MaterialHelpers.cpp +++ b/Code/CryEngine/Cry3DEngine/MaterialHelpers.cpp @@ -844,7 +844,6 @@ void MaterialHelpers::MigrateXmlLegacyData(SInputShaderResources& pShaderResourc CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "Material %s has had legacy GlowAmount automatically converted to Emissive Intensity. The material parameters related to Emittance should be manually adjusted for this material.", materialName.c_str()); } - // In Lumberyard version 1.9 BlendLayer2Specular became a color instead of a single float, so it needs to be updated XmlNodeRef publicParamsNode = node->findChild("PublicParams"); if (publicParamsNode && publicParamsNode->haveAttr("BlendLayer2Specular")) { diff --git a/Code/CryEngine/Cry3DEngine/TimeOfDay.cpp b/Code/CryEngine/Cry3DEngine/TimeOfDay.cpp index 3cb5109836..067616899a 100644 --- a/Code/CryEngine/Cry3DEngine/TimeOfDay.cpp +++ b/Code/CryEngine/Cry3DEngine/TimeOfDay.cpp @@ -214,7 +214,7 @@ CTimeOfDay::CTimeOfDay() // fill local var list so, sandbox can access var list without level being loaded // Cryengine supports the notion of environment presets which are set in code that is currently not - // in lumberyard. Therefore, create a default preset here that is used as the only one. + // in Open 3D Engine. Therefore, create a default preset here that is used as the only one. m_defaultPreset = new CEnvironmentPreset; for (int i = 0; i < PARAM_TOTAL; ++i) { diff --git a/Code/CryEngine/CryCommon/CryAssert_impl.h b/Code/CryEngine/CryCommon/CryAssert_impl.h index 8b67a2d71e..ed55162f1a 100644 --- a/Code/CryEngine/CryCommon/CryAssert_impl.h +++ b/Code/CryEngine/CryCommon/CryAssert_impl.h @@ -323,7 +323,7 @@ void CryAssertTrace(const char* _pszFormat, ...) //----------------------------------------------------------------------------------------------------- -static const char* gs_strRegSubKey = "Software\\Amazon\\Lumberyard\\AssertWindow"; +static const char* gs_strRegSubKey = "Software\\O3DE\\AssertWindow"; static const char* gs_strRegXValue = "AssertInfoX"; static const char* gs_strRegYValue = "AssertInfoY"; diff --git a/Code/CryEngine/CryCommon/EngineSettingsBackendWin32.cpp b/Code/CryEngine/CryCommon/EngineSettingsBackendWin32.cpp index 8ec03cdfa9..c2e9a67d57 100644 --- a/Code/CryEngine/CryCommon/EngineSettingsBackendWin32.cpp +++ b/Code/CryEngine/CryCommon/EngineSettingsBackendWin32.cpp @@ -26,7 +26,7 @@ #define REG_SOFTWARE L"Software\\" #define REG_COMPANY_NAME L"Amazon\\" -#define REG_PRODUCT_NAME L"Lumberyard\\" +#define REG_PRODUCT_NAME L"Open 3D Engine\\" #define REG_SETTING L"Settings\\" #define REG_BASE_SETTING_KEY REG_SOFTWARE REG_COMPANY_NAME REG_PRODUCT_NAME REG_SETTING @@ -181,7 +181,7 @@ bool CEngineSettingsBackendWin32::SetModuleSpecificBoolEntry(const char* key, co bool CEngineSettingsBackendWin32::GetInstalledBuildRootPathUtf16(const int index, CWCharBuffer name, CWCharBuffer path) { - RegKey key(REG_BASE_SETTING_KEY L"LumberyardExport\\ProjectBuilds", false); + RegKey key(REG_BASE_SETTING_KEY L"O3DEExport\\ProjectBuilds", false); if (key.pKey) { DWORD type; diff --git a/Code/CryEngine/CryCommon/HMDBus.h b/Code/CryEngine/CryCommon/HMDBus.h index 07292f5d1e..f76405120d 100644 --- a/Code/CryEngine/CryCommon/HMDBus.h +++ b/Code/CryEngine/CryCommon/HMDBus.h @@ -61,7 +61,7 @@ namespace AZ /// /// Attempt to initialize this device. If initialization is initially successful (device exists and is able to startup) then this device should connect to the - /// HMDDeviceRequestBus in order to be used as an HMD from the main Lumberyard system. + /// HMDDeviceRequestBus in order to be used as an HMD from the main Open 3D Engine system. /// /// @return If true, initialization fully succeeded. /// diff --git a/Code/CryEngine/CryCommon/ISystem.h b/Code/CryEngine/CryCommon/ISystem.h index 2519aae1c3..9b1e817602 100644 --- a/Code/CryEngine/CryCommon/ISystem.h +++ b/Code/CryEngine/CryCommon/ISystem.h @@ -1470,7 +1470,7 @@ struct ISystem virtual int GetApplicationInstance() = 0; // Summary: - // Get log index of the currently running lumberyard application. (0 = first instance, 1 = second instance, etc) + // Get log index of the currently running Open 3D Engine application. (0 = first instance, 1 = second instance, etc) virtual int GetApplicationLogInstance(const char* logFilePath) = 0; // Summary: diff --git a/Code/CryEngine/CryFont/FFont.cpp b/Code/CryEngine/CryFont/FFont.cpp index 0441ef325f..c028a0827e 100644 --- a/Code/CryEngine/CryFont/FFont.cpp +++ b/Code/CryEngine/CryFont/FFont.cpp @@ -111,7 +111,10 @@ int32 CFFont::Release() m_pCryFont = nullptr; } - gEnv->pRenderer->DeleteFont(this); + if (gEnv->pRenderer) + { + gEnv->pRenderer->DeleteFont(this); + } return 0; } return nRef; diff --git a/Code/CryEngine/CrySystem/CrashHandler.rc b/Code/CryEngine/CrySystem/CrashHandler.rc index a3f9e37e18..01afa72550 100644 --- a/Code/CryEngine/CrySystem/CrashHandler.rc +++ b/Code/CryEngine/CrySystem/CrashHandler.rc @@ -85,7 +85,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Save",IDB_CONFIRM_SAVE,4,96,68,20 PUSHBUTTON "Cancel",IDB_DONT_SAVE,206,96,68,20 - LTEXT "Lumberyard has encountered an error and needs to close.\n\nA backup has been saved to the '_savebackup' subfolder.\n\nIf you are unable to save your file, you can recover by copying the contents of the _savebackup folder over the broken files.",IDC_STATIC,60,8,210,61 + LTEXT "Open 3D Engine has encountered an error and needs to close.\n\nA backup has been saved to the '_savebackup' subfolder.\n\nIf you are unable to save your file, you can recover by copying the contents of the _savebackup folder over the broken files.",IDC_STATIC,60,8,210,61 LTEXT "Attempt save?",IDC_STATIC,60,72,180,21 CONTROL 128,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_REALSIZEIMAGE,8,8,48,40 END diff --git a/Code/CryEngine/CrySystem/CryDLMalloc.c b/Code/CryEngine/CrySystem/CryDLMalloc.c index e7838cffcb..bcb835b0d5 100644 --- a/Code/CryEngine/CrySystem/CryDLMalloc.c +++ b/Code/CryEngine/CrySystem/CryDLMalloc.c @@ -4871,7 +4871,9 @@ static void* tmalloc_small(mstate m, size_t nb) } CORRUPTION_ERROR_ACTION(m); +#if PROCEED_ON_ERROR return 0; +#endif } /* --------------------------- realloc support --------------------------- */ @@ -4930,7 +4932,9 @@ static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { USAGE_ERROR_ACTION(m, oldmem); POSTACTION(m); +#if PROCEED_ON_ERROR return 0; +#endif } #if DEBUG if (newp != 0) @@ -5884,7 +5888,9 @@ void* mspace_malloc(mspace msp, size_t bytes) if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } if (!PREACTION(ms)) { @@ -6150,7 +6156,9 @@ void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } if (n_elements != 0) { @@ -6193,7 +6201,9 @@ void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } return internal_realloc(ms, oldmem, bytes); } @@ -6205,7 +6215,9 @@ void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } return internal_memalign(ms, alignment, bytes); } @@ -6218,7 +6230,9 @@ void** mspace_independent_calloc(mspace msp, size_t n_elements, if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } return ialloc(ms, n_elements, &sz, 3, chunks); } @@ -6230,7 +6244,9 @@ void** mspace_independent_comalloc(mspace msp, size_t n_elements, if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); +#if PROCEED_ON_ERROR return 0; +#endif } return ialloc(ms, n_elements, sizes, 0, chunks); } diff --git a/Code/CryEngine/CrySystem/IDebugCallStack.cpp b/Code/CryEngine/CrySystem/IDebugCallStack.cpp index 05f810f3c1..d73d70ab8b 100644 --- a/Code/CryEngine/CrySystem/IDebugCallStack.cpp +++ b/Code/CryEngine/CrySystem/IDebugCallStack.cpp @@ -226,7 +226,7 @@ void IDebugCallStack::FatalError(const char* description) bShowDebugScreen = bShowDebugScreen && gEnv->mMainThreadId == CryGetCurrentThreadId(); if (bShowDebugScreen) { - EBUS_EVENT(AZ::NativeUI::NativeUIRequestBus, DisplayOkDialog, "Lumberyard Fatal Error", description, false); + EBUS_EVENT(AZ::NativeUI::NativeUIRequestBus, DisplayOkDialog, "Open 3D Engine Fatal Error", description, false); } #endif diff --git a/Code/CryEngine/CrySystem/MemoryManager.cpp b/Code/CryEngine/CrySystem/MemoryManager.cpp index 40e1a9b11e..4704d2f5fe 100644 --- a/Code/CryEngine/CrySystem/MemoryManager.cpp +++ b/Code/CryEngine/CrySystem/MemoryManager.cpp @@ -98,14 +98,18 @@ bool CCryMemoryManager::GetProcessMemInfo(SProcessMemInfo& minfo) } return false; +#else #define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION MEMORYMANAGER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE(MemoryManager_cpp) +#if defined(AZ_RESTRICTED_PLATFORM) + #define AZ_RESTRICTED_SECTION MEMORYMANAGER_CPP_SECTION_1 + #include AZ_RESTRICTED_FILE(MemoryManager_cpp) #endif + + bool retVal = true; + #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(LINUX) MEMORYSTATUS MemoryStatus; @@ -143,11 +147,15 @@ bool CCryMemoryManager::GetProcessMemInfo(SProcessMemInfo& minfo) return false; } minfo.WorkingSetSize = kTaskInfo.resident_size; + #else - return false; + + retVal = false; + #endif - return true; + return retVal; +#endif } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/CryEngine/CrySystem/System.cpp b/Code/CryEngine/CrySystem/System.cpp index af14060826..a48f63afdf 100644 --- a/Code/CryEngine/CrySystem/System.cpp +++ b/Code/CryEngine/CrySystem/System.cpp @@ -1451,20 +1451,12 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode) //bool bPause = false; bool bNoUpdate = false; #ifndef EXCLUDE_UPDATE_ON_CONSOLE - //check what is the current process - IProcess* pProcess = GetIProcess(); - if (!pProcess) - { - return (true); //should never happen - } if (m_sysNoUpdate && m_sysNoUpdate->GetIVal()) { bNoUpdate = true; updateFlags = ESYSUPDATE_IGNORE_PHYSICS; } - //if ((pProcess->GetFlags() & PROC_MENU) || (m_sysNoUpdate && m_sysNoUpdate->GetIVal())) - // bPause = true; m_bNoUpdate = bNoUpdate; #endif //EXCLUDE_UPDATE_ON_CONSOLE @@ -1537,7 +1529,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode) } ////////////////////////////////////////////////////////////////////////// - if (m_env.pRenderer->GetIStereoRenderer()->IsRenderingToHMD()) + if (m_env.pRenderer && m_env.pRenderer->GetIStereoRenderer()->IsRenderingToHMD()) { EBUS_EVENT(AZ::VR::HMDDeviceRequestBus, UpdateInternalState); } @@ -2860,8 +2852,6 @@ bool CSystem::HandleMessage([[maybe_unused]] HWND hWnd, UINT uMsg, WPARAM wParam default: return false; } - - return true; } #endif diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp index 21eb0c538c..5e43d6a1df 100644 --- a/Code/CryEngine/CrySystem/SystemInit.cpp +++ b/Code/CryEngine/CrySystem/SystemInit.cpp @@ -248,7 +248,7 @@ CUNIXConsole* pUnixConsole; #define LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME "Libs/Localization/localization.xml" #define LOAD_LEGACY_RENDERER_FOR_EDITOR true // If you set this to false you must for now also set 'ed_useAtomNativeViewport' to true (see /Code/Sandbox/Editor/ViewManager.cpp) -#define LOAD_LEGACY_RENDERER_FOR_LAUNCHER true +#define LOAD_LEGACY_RENDERER_FOR_LAUNCHER false ////////////////////////////////////////////////////////////////////////// // Where possible, these are defaults used to initialize cvars @@ -1256,7 +1256,7 @@ bool CSystem::OpenRenderLibrary(int type, const SSystemInitParams& initParams) if (allowPrompts) { AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Asking user if they wish to continue..."); - const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedGPU(gpuName, gpuVendorId, gpuDeviceId).c_str(), L"Lumberyard", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); + const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedGPU(gpuName, gpuVendorId, gpuDeviceId).c_str(), L"Open 3D Engine", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); if (mbRes == IDCANCEL) { AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to cancel startup due to unsupported GPU."); @@ -2093,7 +2093,7 @@ static bool CheckCPURequirements([[maybe_unused]] CCpuFeatures* pCpu, [[maybe_un if (allowPrompts) { AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Asking user if they wish to continue..."); - const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedCPU().c_str(), L"Lumberyard", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); + const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedCPU().c_str(), L"Open 3D Engine", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); if (mbRes == IDCANCEL) { AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to cancel startup."); @@ -2305,7 +2305,7 @@ AZ_POP_DISABLE_WARNING if (!bIsWindowsXPorLater) { - AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Lumberyard requires an OS version of Windows XP or later."); + AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Open 3D Engine requires an OS version of Windows XP or later."); return false; } } @@ -2420,7 +2420,7 @@ AZ_POP_DISABLE_WARNING azstrcpy( headerString, AZ_ARRAY_SIZE(headerString), - "Lumberyard - " + "Open 3D Engine - " #if defined(LINUX) "Linux " #elif defined(MAC) diff --git a/Code/CryEngine/CrySystem/SystemRender.cpp b/Code/CryEngine/CrySystem/SystemRender.cpp index 6e1a763759..01828175db 100644 --- a/Code/CryEngine/CrySystem/SystemRender.cpp +++ b/Code/CryEngine/CrySystem/SystemRender.cpp @@ -626,7 +626,7 @@ void CSystem::RenderStats() float nTextPosX = 101 - 20, nTextPosY = -2, nTextStepY = 3; m_env.p3DEngine->DisplayInfo(nTextPosX, nTextPosY, nTextStepY, iDisplayInfo != 1); - // Dump Lumberyard CPU and GPU memory statistics to screen + // Dump Open 3D Engine CPU and GPU memory statistics to screen m_env.p3DEngine->DisplayMemoryStatistics(); #if defined(ENABLE_LW_PROFILERS) diff --git a/Code/CryEngine/CrySystem/SystemWin32.cpp b/Code/CryEngine/CrySystem/SystemWin32.cpp index 5a81617bdd..a46f080106 100644 --- a/Code/CryEngine/CrySystem/SystemWin32.cpp +++ b/Code/CryEngine/CrySystem/SystemWin32.cpp @@ -1091,7 +1091,7 @@ void CSystem::FatalError(const char* format, ...) { ::ShowWindow((HWND)gEnv->pRenderer->GetHWND(), SW_MINIMIZE); } - ::MessageBox(NULL, szBuffer, "Lumberyard Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL); + ::MessageBox(NULL, szBuffer, "Open 3D Engine Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL); } // Dump callstack. diff --git a/Code/CryEngine/CrySystem/XML/ReadXMLSink.cpp b/Code/CryEngine/CrySystem/XML/ReadXMLSink.cpp index 8b2f6a1821..30d170435a 100644 --- a/Code/CryEngine/CrySystem/XML/ReadXMLSink.cpp +++ b/Code/CryEngine/CrySystem/XML/ReadXMLSink.cpp @@ -193,34 +193,12 @@ bool IsOptionalReadXML(const SParseParams& parseParams, XmlNodeRef& definition) return optional; } -bool CheckEnum([[maybe_unused]] const SParseParams& parseParams, const char* name, XmlNodeRef& definition, XmlNodeRef& data) +bool CheckEnum([[maybe_unused]] const SParseParams& parseParams, [[maybe_unused]] const char* name, XmlNodeRef& definition, [[maybe_unused]] XmlNodeRef& data) { if (XmlNodeRef enumNode = definition->findChild("Enum")) { // If strict mode is off, then no need to check the enum value return true; - - // if restrictive attribute set to false, check always succeeds - if (enumNode->haveAttr("restrictive")) - { - bool res = true; - enumNode->getAttr("restrictive", res); - if (!res) - { - return true; - } - } - - // else check enum values - const char* val = data->getAttr(name); - for (int i = 0; i < enumNode->getChildCount(); ++i) - { - if (0 == strcmp(enumNode->getChild(i)->getContent(), val)) - { - return true; - } - } - return false; } return true; } diff --git a/Code/CryEngine/RenderDll/Common/RenderThread.cpp b/Code/CryEngine/RenderDll/Common/RenderThread.cpp index dd52999c9b..f90c8e58b2 100644 --- a/Code/CryEngine/RenderDll/Common/RenderThread.cpp +++ b/Code/CryEngine/RenderDll/Common/RenderThread.cpp @@ -711,6 +711,7 @@ bool SRenderThread::RC_CreateDeviceTexture(CTexture* pTex, const byte* pData[6]) return pTex->RT_CreateDeviceTexture(pData); } +#if !defined(MULTITHREADED_RESOURCE_CREATION) if (pTex->IsAsyncDevTexCreation()) { return !IsFailed(); @@ -727,6 +728,7 @@ bool SRenderThread::RC_CreateDeviceTexture(CTexture* pTex, const byte* pData[6]) FlushAndWait(); return !IsFailed(); +#endif } void SRenderThread::RC_CopyDataToTexture( diff --git a/Code/CryEngine/RenderDll/Common/RendererDefs.h b/Code/CryEngine/RenderDll/Common/RendererDefs.h index 246726e743..9dad69f471 100644 --- a/Code/CryEngine/RenderDll/Common/RendererDefs.h +++ b/Code/CryEngine/RenderDll/Common/RendererDefs.h @@ -229,7 +229,7 @@ namespace detail #if defined(OPENGL) && (defined(DEBUG) || defined(_DEBUG)) #define LY_ENABLE_OPENGL_ERROR_CHECKING #endif -namespace Lumberyard +namespace O3de { namespace OpenGL { diff --git a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp index a05c846c42..9963685743 100644 --- a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp +++ b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp @@ -776,9 +776,6 @@ static bool sIterateDL(DWORD& dwDL) else { return false; - nLights = 2; - nType[0] = SLMF_DIRECT; - nType[1] = SLMF_POINT; } break; case 2: diff --git a/Code/CryEngine/RenderDll/Common/Shaders/ShaderTemplate.cpp b/Code/CryEngine/RenderDll/Common/Shaders/ShaderTemplate.cpp index 77cc1f737a..79a74c35a9 100644 --- a/Code/CryEngine/RenderDll/Common/Shaders/ShaderTemplate.cpp +++ b/Code/CryEngine/RenderDll/Common/Shaders/ShaderTemplate.cpp @@ -771,7 +771,6 @@ const char* CShaderMan::mfTemplateTexIdToName(int Id) default: return "Unknown"; } - return "Unknown"; } CTexAnim* CShaderMan::mfReadTexSequence(const char* na, int Flags, [[maybe_unused]] bool bFindOnly) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderD3D11.rc b/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderD3D11.rc index 4a5d291af7..6f4202b3ea 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderD3D11.rc +++ b/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderD3D11.rc @@ -47,7 +47,7 @@ BEGIN VALUE "FileVersion", "1, 0, 0, 1" VALUE "FileDescription", "CryRenderD3D11" VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "ProductName", "Lumberyard" + VALUE "ProductName", "Open 3D Engine" VALUE "ProductVersion", "1, 0, 0, 1" END END diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderGL.rc b/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderGL.rc index 48822ceada..9cbf98627e 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderGL.rc +++ b/Code/CryEngine/RenderDll/XRenderD3D9/CryRenderGL.rc @@ -47,7 +47,7 @@ BEGIN VALUE "FileVersion", "1, 0, 0, 1" VALUE "FileDescription", "CryRenderGL" VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "ProductName", "Lumberyard" + VALUE "ProductName", "Open 3D Engine" VALUE "ProductVersion", "1, 0, 0, 1" END END diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/D3DFXPipeline.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/D3DFXPipeline.cpp index fa92c7c123..319a3ffe76 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/D3DFXPipeline.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/D3DFXPipeline.cpp @@ -2909,7 +2909,6 @@ byte CD3D9Renderer::FX_StartQuery(SRendItem* pRI) return 0; } #endif - return 0; } void CD3D9Renderer::FX_EndQuery(SRendItem* pRI, byte bStartQ) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLContext.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLContext.cpp index 535b3cac26..d23935fe18 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLContext.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLContext.cpp @@ -3641,7 +3641,7 @@ case _D3DValue: \ glDrawElements(m_ePrimitiveTopologyMode, uIndexCount, m_eIndexType, pvOffset); #endif - Lumberyard::OpenGL::CheckError(); + O3de::OpenGL::CheckError(); END_TRACE(); } @@ -3662,7 +3662,7 @@ case _D3DValue: \ CRY_ASSERT(m_ePrimitiveTopologyMode != GL_NONE); glDrawArrays(m_ePrimitiveTopologyMode, uStartVertexLocation, uVertexCount); - Lumberyard::OpenGL::CheckError(); + O3de::OpenGL::CheckError(); END_TRACE(); } diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLDevice.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLDevice.cpp index 76e971731d..3508d23176 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLDevice.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLDevice.cpp @@ -2422,7 +2422,7 @@ namespace NCryOpenGL return false; } - Lumberyard::OpenGL::ClearErrors(); + O3de::OpenGL::ClearErrors(); GLint major = 0, minor = 0; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); @@ -2431,7 +2431,7 @@ namespace NCryOpenGL pAdapter->m_sVersion.m_uMajorVersion = static_cast(major); pAdapter->m_sVersion.m_uMinorVersion = static_cast(minor); - return Lumberyard::OpenGL::CheckError() == GL_NO_ERROR; + return O3de::OpenGL::CheckError() == GL_NO_ERROR; } bool ParseExtensions(SAdapterPtr& pAdapter) @@ -2443,7 +2443,7 @@ namespace NCryOpenGL int num = 0, index; bool result = true; - Lumberyard::OpenGL::ClearErrors(); + O3de::OpenGL::ClearErrors(); glGetIntegerv(GL_NUM_EXTENSIONS, &num); for (index = 0; index < num; ++index) { @@ -2458,7 +2458,7 @@ namespace NCryOpenGL pAdapter->AddExtension(extension); } - return result && Lumberyard::OpenGL::CheckError() == GL_NO_ERROR; + return result && O3de::OpenGL::CheckError() == GL_NO_ERROR; } bool DetectAdapters(std::vector& kAdapters) @@ -2971,7 +2971,7 @@ namespace NCryOpenGL #endif //DXGL_CHECK_ERRORS } // namespace NCryOpenGL -namespace Lumberyard +namespace O3de { namespace OpenGL { @@ -2994,4 +2994,4 @@ namespace Lumberyard } #endif } // namespace OpenGL -} // namespace Lumberyard +} // namespace O3de diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DriverD3D.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DriverD3D.cpp index 8f2f86081f..e3675be4e1 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DriverD3D.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DriverD3D.cpp @@ -4914,7 +4914,6 @@ bool CD3D9Renderer::ScreenShotInternal([[maybe_unused]] const char* filename, [[ // ignore invalid file access for screenshots CDebugAllowFileAccess ignoreInvalidFileAccess; - bool bRet = true; #if !defined(_RELEASE) || defined(WIN32) || defined(WIN64) || defined(ENABLE_LW_PROFILERS) if (m_pRT && !m_pRT->IsRenderThread()) { @@ -5041,8 +5040,11 @@ bool CD3D9Renderer::ScreenShotInternal([[maybe_unused]] const char* filename, [[ return CaptureFrameBufferToFile(path); +#else + + return true; + #endif//_RELEASE - return bRet; } bool CD3D9Renderer::ScreenShot(const char* filename, int iPreWidth) @@ -5656,8 +5658,6 @@ bool CD3D9Renderer::CaptureFrameBufferFast([[maybe_unused]] unsigned char* pDstR } SAFE_RELEASE(pSourceTexture); - - return bStatus; #endif return bStatus; @@ -5710,8 +5710,6 @@ bool CD3D9Renderer::CopyFrameBufferFast([[maybe_unused]] unsigned char* pDstRGBA GetDeviceContext().Unmap(pCopyTexture, 0); bStatus = true; } - - return bStatus; #endif return bStatus; diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/GPUTimer.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/GPUTimer.cpp index 7a61de76b3..01c24631e0 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/GPUTimer.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/GPUTimer.cpp @@ -105,8 +105,9 @@ bool CD3DProfilingGPUTimer::Init() { #ifdef ENABLE_PROFILING_GPU_TIMERS return CD3DGPUTimer::Init(); -#endif +#else return false; +#endif } CD3DGPUTimer::CD3DGPUTimer() @@ -264,4 +265,4 @@ bool CD3DGPUTimer::Init() #endif return m_bInitialized; -} \ No newline at end of file +} diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/MultiLayerAlphaBlendPass.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/MultiLayerAlphaBlendPass.cpp index 60ce22eb2a..26bffca9c2 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/MultiLayerAlphaBlendPass.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/MultiLayerAlphaBlendPass.cpp @@ -90,7 +90,7 @@ bool MultiLayerAlphaBlendPass::IsSupported() } #else m_supported = SupportLevel::NOT_SUPPORTED; - AZ_Warning("Rendering", false, "Multi-Layer Alpha Blending requires Lumberyard to have been built with the Windows 10 SDK or higher."); + AZ_Warning("Rendering", false, "Multi-Layer Alpha Blending requires Open 3D Engine to have been built with the Windows 10 SDK or higher."); #endif } diff --git a/Code/CryEngine/RenderDll/XRenderNULL/CryRenderNULL.rc b/Code/CryEngine/RenderDll/XRenderNULL/CryRenderNULL.rc index 5730d0a537..33e65697ad 100644 --- a/Code/CryEngine/RenderDll/XRenderNULL/CryRenderNULL.rc +++ b/Code/CryEngine/RenderDll/XRenderNULL/CryRenderNULL.rc @@ -84,7 +84,7 @@ BEGIN VALUE "CompanyName", "Amazon.com, Inc." VALUE "FileVersion", "1, 0, 0, 1" VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "ProductName", "Lumberyard" + VALUE "ProductName", "Open 3D Engine" VALUE "ProductVersion", "1, 0, 0, 1" END END diff --git a/Code/Framework/AzCore/AzCore/Android/APKFileHandler.cpp b/Code/Framework/AzCore/AzCore/Android/APKFileHandler.cpp index b535d9e201..6f0903bf31 100644 --- a/Code/Framework/AzCore/AzCore/Android/APKFileHandler.cpp +++ b/Code/Framework/AzCore/AzCore/Android/APKFileHandler.cpp @@ -111,7 +111,7 @@ namespace AZ bool loadFileToMemory = Get().ShouldLoadFileToMemory(filename); int assetMode = loadFileToMemory ? AASSET_MODE_BUFFER : AASSET_MODE_UNKNOWN; - asset = AAssetManager_open(Utils::GetAssetManager(), Utils::StripApkPrefix(filename), assetMode); + asset = AAssetManager_open(Utils::GetAssetManager(), Utils::StripApkPrefix(filename).c_str(), assetMode); if (asset != nullptr) { @@ -192,7 +192,7 @@ namespace AZ { buf->m_offset = buf->m_totalSize - offset; } - + if (buf->m_offset > buf->m_totalSize) { buf->m_offset = buf->m_totalSize; @@ -320,12 +320,19 @@ namespace AZ bool APKFileHandler::DirectoryOrFileExists(const char* path) { - ANDROID_IO_PROFILE_SECTION_ARGS("APK DirOrFileexists"); + ANDROID_IO_PROFILE_SECTION_ARGS("APK DirOrFileExists"); - AZ::IO::PathView insideApkPathView(Utils::StripApkPrefix(path)); + AZ::IO::FixedMaxPath insideApkPath(Utils::StripApkPrefix(path)); - AZ::IO::FixedMaxPathString filename{ insideApkPathView.Filename().Native() }; - AZ::IO::FixedMaxPathString pathToFile{ insideApkPathView.ParentPath().Native() }; + // Check for the case where the input path is equal to the APK Assets Prefix of /APK + // In that case the directory is the "root" of APK assets in which case the directory exist + if (insideApkPath.empty() && Utils::IsApkPath(path)) + { + return true; + } + + AZ::IO::FixedMaxPathString filename{ insideApkPath.Filename().Native() }; + AZ::IO::FixedMaxPathString pathToFile{ insideApkPath.ParentPath().Native() }; bool foundFile = false; ParseDirectory(pathToFile.c_str(), [&](const char* name) diff --git a/Code/Framework/AzCore/AzCore/Android/Utils.cpp b/Code/Framework/AzCore/AzCore/Android/Utils.cpp index aaf3a21328..efbbf50d1d 100644 --- a/Code/Framework/AzCore/AzCore/Android/Utils.cpp +++ b/Code/Framework/AzCore/AzCore/Android/Utils.cpp @@ -17,7 +17,7 @@ #include #include - +#include namespace AZ { @@ -28,9 +28,9 @@ namespace AZ namespace { //////////////////////////////////////////////////////////////// - const char* GetApkAssetsPrefix() + constexpr const char* GetApkAssetsPrefix() { - return "/APK/"; + return "/APK"; } } @@ -104,19 +104,14 @@ namespace AZ //////////////////////////////////////////////////////////////// bool IsApkPath(const char* filePath) { - return (strncmp(filePath, GetApkAssetsPrefix(), 4) == 0); // +3 for "APK", +1 for '/' starting slash + return AZ::IO::PathView(filePath).IsRelativeTo(AZ::IO::PathView(GetApkAssetsPrefix())); } //////////////////////////////////////////////////////////////// - const char* StripApkPrefix(const char* filePath) + AZ::IO::FixedMaxPath StripApkPrefix(const char* filePath) { - const int prefixLength = 5; // +3 for "APK", +2 for '/' on either end - if (!IsApkPath(filePath)) - { - return filePath; - } - - return filePath + prefixLength; + constexpr AZ::IO::PathView apkPrefixView = GetApkAssetsPrefix(); + return AZ::IO::PathView(filePath).LexicallyProximate(apkPrefixView); } //////////////////////////////////////////////////////////////// @@ -130,7 +125,7 @@ namespace AZ // first check to see if they are in public storage (application specific) const char* publicAppStorage = GetAppPublicStoragePath(); - OSString path = OSString::format("%s/bootstrap.cfg", publicAppStorage); + OSString path = OSString::format("%s/engine.json", publicAppStorage); AZ_TracePrintf("Android::Utils", "Searching for %s\n", path.c_str()); FILE* f = fopen(path.c_str(), "r"); @@ -145,7 +140,7 @@ namespace AZ AAssetManager* mgr = GetAssetManager(); if (mgr) { - AAsset* asset = AAssetManager_open(mgr, "bootstrap.cfg", AASSET_MODE_UNKNOWN); + AAsset* asset = AAssetManager_open(mgr, "engine.json", AASSET_MODE_UNKNOWN); if (asset) { AAsset_close(asset); diff --git a/Code/Framework/AzCore/AzCore/Android/Utils.h b/Code/Framework/AzCore/AzCore/Android/Utils.h index 2398aa490d..222fac80ad 100644 --- a/Code/Framework/AzCore/AzCore/Android/Utils.h +++ b/Code/Framework/AzCore/AzCore/Android/Utils.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include @@ -55,7 +56,7 @@ namespace AZ const char* GetObbStoragePath(); //! Get the dot separated package name for the current application. - //! e.g. com.lumberyard.samples for SamplesProject + //! e.g. com.o3de.samples for SamplesProject const char* GetPackageName(); //! Get the app version code (android:versionCode in the manifest). @@ -70,7 +71,7 @@ namespace AZ //! Will first check to verify the argument is an apk asset path and if so //! will strip the prefix from the path. //! \return The pointer position of the relative asset path - const char* StripApkPrefix(const char* filePath); + AZ::IO::FixedMaxPath StripApkPrefix(const char* filePath); //! Searches application storage and the APK for bootstrap.cfg. Will return nullptr //! if bootstrap.cfg is not found. diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp index aa9af89457..767dadedf8 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include #include @@ -107,7 +107,8 @@ namespace AZ result = ContinueLoading(&id, azrtti_typeid(), it->value, context); if (!id.m_guid.IsNull()) { - *instance = Asset(id, instance->GetType()); + *instance = AssetManager::Instance().FindOrCreateAsset(id, instance->GetType(), AssetLoadBehavior::NoLoad); + result.Combine(context.Report(result, "Successfully created Asset with id.")); } diff --git a/Code/Framework/AzCore/AzCore/Component/Component.h b/Code/Framework/AzCore/AzCore/Component/Component.h index c2878c1c7c..4804c35013 100644 --- a/Code/Framework/AzCore/AzCore/Component/Component.h +++ b/Code/Framework/AzCore/AzCore/Component/Component.h @@ -12,7 +12,7 @@ /** @file * Header file for the Component base class. - * In Lumberyard's component entity system, each component defines a discrete + * In Open 3D Engine's component entity system, each component defines a discrete * feature that can be attached to an entity. */ @@ -76,7 +76,7 @@ namespace AZ * practice to access other components through EBuses instead of accessing them directly. * For more information, see the * Programmer's Guide to Entities and Components - * in the Lumberyard Developer Guide. + * in the Open 3D Engine Developer Guide. * @return A pointer to the entity. If the component is not attached to any entity, * the return value is a null pointer. */ @@ -426,7 +426,7 @@ namespace AZ /** * Describes the properties of the component descriptor event bus. - * This bus uses AzTypeInfo::Uuid as the ID for the specific descriptor. Lumberyard allows only one + * This bus uses AzTypeInfo::Uuid as the ID for the specific descriptor. Open 3D Engine allows only one * descriptor for each component type. When you call functions on the bus for a specific component * type, you can safely pass only one result variable because aggregating or overwriting results * is impossible. diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index 276e9fe78d..b8d3e12712 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -174,6 +173,7 @@ namespace AZ return true; }; + //! SettingsRegistry notifier handler which updates relevant registry settings based //! on an update to '/Amazon/AzCore/Bootstrap/project_path' key. struct UpdateProjectSettingsEventHandler @@ -185,66 +185,57 @@ namespace AZ void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type) { - UpdateProjectSpecializationInRegistry(path); + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; + AZ::IO::FixedMaxPath newProjectPath; + if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path) + && m_registry.Get(newProjectPath.Native(), projectPathKey) && newProjectPath != m_oldProjectPath) + { + UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath)); + } + + const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name"; + FixedValueString newProjectName; + if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path) + && m_registry.Get(newProjectName, projectNameKey) && newProjectName != m_oldProjectName) + { + UpdateProjectSpecializationFromProjectName(newProjectName); + } } //! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path //! and remove the current project name specialization if one exists. - void UpdateProjectSpecializationInRegistry(AZStd::string_view path) + void UpdateProjectSpecializationFromProjectName(AZStd::string_view newProjectName) { - auto projectPathKey = - AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) - + "/project_path"; - if (path == projectPathKey) - { - AZ::SettingsRegistryInterface::FixedValueString newProjectPath; - if (m_registry.Get(newProjectPath, path) && !newProjectPath.empty()) - { - // Make the path absolute by appending to app root, in case project path is relative. - // If the project path is already absolute it will remain the same. - // If we turn it from a relative path to an absolute path, write-back the absolute path to the registry. - AZ::IO::FixedMaxPath projectPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath; - if (projectPath.Compare(newProjectPath.c_str())) - { - m_registry.Set(path, projectPath.Native()); - } + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + // Add the project_name as a specialization for loading the build system dependency .setreg files + auto newProjectNameSpecialization = FixedValueString::format("%s/%.*s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, + aznumeric_cast(newProjectName.size()), newProjectName.data()); + auto oldProjectNameSpecialization = FixedValueString::format("%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, + m_oldProjectName.c_str()); + m_registry.Remove(oldProjectNameSpecialization); + m_oldProjectName = newProjectName; + m_registry.Set(newProjectNameSpecialization, true); + } - // Merge the project.json file into settings registry under ProjectSettingsRootKey path. - AZ::IO::FixedMaxPath projectMetadataFile{ projectPath }; - projectMetadataFile /= "project.json"; - m_registry.MergeSettingsFile(projectMetadataFile.Native(), - AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey); + void UpdateProjectSettingsFromProjectPath(AZ::IO::PathView newProjectPath) + { + // Update old Project path before attempting to merge in new Settings Registry values in order to prevent recursive calls + m_oldProjectPath = newProjectPath; - // Get the 'project_name' value from what was in the 'project.json' file... - auto projectNameKey = - AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) - + "/project_name"; + // Merge the project.json file into settings registry under ProjectSettingsRootKey path. + AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath }; + projectMetadataFile /= "project.json"; + m_registry.MergeSettingsFile(projectMetadataFile.Native(), + AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey); - AZ::SettingsRegistryInterface::FixedValueString projectSpecialization; - if (m_registry.Get(projectSpecialization, projectNameKey)) - { - auto specializationKey = AZ::SettingsRegistryInterface::FixedValueString::format( - "%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, projectSpecialization.c_str()); - if (m_currentSpecialization != specializationKey) - { - m_registry.Set(specializationKey, true); - if (!m_currentSpecialization.empty()) - { - // Remove the previous Project Name from the specialization path if it was set. - m_registry.Remove(m_currentSpecialization); - } - m_currentSpecialization = specializationKey; - - // Update all the runtime file paths based on the new "project_path" value. - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry); - } - } - } - } + // Update all the runtime file paths based on the new "project_path" value. + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry); } private: - AZ::SettingsRegistryInterface::FixedValueString m_currentSpecialization; + AZ::IO::FixedMaxPath m_oldProjectPath; + AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName; AZ::SettingsRegistryInterface& m_registry; }; @@ -424,7 +415,7 @@ namespace AZ // Add the Command Line arguments into the SettingsRegistry SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine); - // Merge Command Line arguments + // Merge Command Line arguments constexpr bool executeRegDumpCommands = false; SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands); @@ -1395,10 +1386,7 @@ namespace AZ //========================================================================= void ComponentApplication::CalculateExecutablePath() { - Utils::GetExecutableDirectory(m_exeDirectory.data(), m_exeDirectory.capacity()); - // Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string stored within it - m_exeDirectory.resize_no_construct(AZStd::char_traits::length(m_exeDirectory.data())); - m_exeDirectory.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR); + m_exeDirectory = Utils::GetExecutableDirectory(); } void ComponentApplication::CalculateAppRoot() @@ -1406,19 +1394,12 @@ namespace AZ if (AZStd::optional appRootPath = Utils::GetDefaultAppRootPath(); appRootPath) { m_appRoot = AZStd::move(*appRootPath); - if (!m_appRoot.empty() && !m_appRoot.ends_with(AZ_CORRECT_FILESYSTEM_SEPARATOR)) - { - m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR); - } } } void ComponentApplication::CalculateEngineRoot() { - if (m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native(); !m_engineRoot.empty()) - { - m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR); - } + m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native(); } void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h index 05507ba164..ef5c813573 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -392,9 +393,9 @@ namespace AZ void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy. IAllocatorAllocate* m_osAllocator{ nullptr }; EntitySetType m_entities; - AZ::IO::FixedMaxPathString m_exeDirectory; - AZ::IO::FixedMaxPathString m_engineRoot; - AZ::IO::FixedMaxPathString m_appRoot; + AZ::IO::FixedMaxPath m_exeDirectory; + AZ::IO::FixedMaxPath m_engineRoot; + AZ::IO::FixedMaxPath m_appRoot; AZ::SettingsRegistryInterface::NotifyEventHandler m_projectChangedHandler; diff --git a/Code/Framework/AzCore/AzCore/Component/Entity.h b/Code/Framework/AzCore/AzCore/Component/Entity.h index b8c8782ebf..b7dcb70b9c 100644 --- a/Code/Framework/AzCore/AzCore/Component/Entity.h +++ b/Code/Framework/AzCore/AzCore/Component/Entity.h @@ -12,7 +12,7 @@ /** @file * Header file for the Entity class. - * In Lumberyard's component entity system, an entity is an addressable container for + * In Open 3D Engine's component entity system, an entity is an addressable container for * a group of components. The entity represents the functionality and properties of an * object within your game. */ diff --git a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h index 1d72c69e07..ea4522f126 100644 --- a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h +++ b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h @@ -15,7 +15,7 @@ * Header file for internal EBus classes. * For more information about EBuses, see AZ::EBus and AZ::EBusTraits in this guide and * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html) - * in the *Lumberyard Developer Guide*. + * in the *Open 3D Engine Developer Guide*. */ #pragma once diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h index 5cd0c2b9ec..9a83d83529 100644 --- a/Code/Framework/AzCore/AzCore/EBus/EBus.h +++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h @@ -13,11 +13,11 @@ /** * @file * Header file for event bus (EBus), a general-purpose communication system - * that Lumberyard uses to dispatch notifications and receive requests. + * that Open 3D Engine uses to dispatch notifications and receive requests. * EBuses are configurable and support many different use cases. * For more information about %EBuses, see AZ::EBus in this guide and * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html) - * in the *Lumberyard Developer Guide*. + * in the *Open 3D Engine Developer Guide*. */ #pragma once @@ -70,7 +70,7 @@ namespace AZ * * For more information about %EBuses, see EBus in this guide and * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html) - * in the *Lumberyard Developer Guide*. + * in the *Open 3D Engine Developer Guide*. */ struct EBusTraits { @@ -256,7 +256,7 @@ namespace AZ /** * Event buses (EBuses) are a general-purpose communication system - * that Lumberyard uses to dispatch notifications and receive requests. + * that Open 3D Engine uses to dispatch notifications and receive requests. * * @tparam Interface A class whose virtual functions define the events * dispatched or received by the %EBus. @@ -268,7 +268,7 @@ namespace AZ * For more information about EBuses, see * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html) * and [Components and EBuses: Best Practices ](http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-components-ebuses-best-practices.html) - * in the *Lumberyard Developer Guide*. + * in the *Open 3D Engine Developer Guide*. * * ## How Components Use EBuses * Components commonly use EBuses in two ways: to dispatch events or to handle requests. diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h index 28e6854e60..61294cd637 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h @@ -96,8 +96,8 @@ namespace AZ::IO constexpr int Compare(const value_type* pathString) const noexcept; // decomposition - //! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of - //! "/lumberyard/foo/bar/name.txt" + //! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of + //! "/O3DE/foo/bar/name.txt" //! The following functions return the following //! Returns the root name part of the path. if it has one. @@ -114,10 +114,10 @@ namespace AZ::IO constexpr PathView RootPath() const; //! Returns the relative path portion of the path. //! This contains the path parts after the root path - //! windows = "lumberyard\foo\bar\name.txt", posix = "lumberyard/foo/bar/name.txt" + //! windows = "O3DE\foo\bar\name.txt", posix = "O3DE/foo/bar/name.txt" constexpr PathView RelativePath() const; //! Returns the parent directory of filename contained within the path - //! windows = "C:\lumberyard\foo\bar", posix = "/lumberyard/foo/bar" + //! windows = "C:\O3DE\foo\bar", posix = "/O3DE/foo/bar" //! NOTE: If the path ends with a trailing separator "test/foo/" it is treated as being a path of //! "test/foo" as if the filename of the path is "foo" and the parent directory is "test" constexpr PathView ParentPath() const; @@ -150,7 +150,7 @@ namespace AZ::IO //! The root portion of the path is made up of root_name() / root_directory() [[nodiscard]] constexpr bool HasRootPath() const; //! checks whether the relative part of path is empty - //! (C:\\ lumberyard\dev\) + //! (C:\\ O3DE\dev\) //! ^ ^ //! root part relative part [[nodiscard]] constexpr bool HasRelativePath() const; @@ -485,10 +485,10 @@ namespace AZ::IO constexpr PathView RootPath() const; //! Returns the relative path portion of the path. //! This contains the path parts after the root path - //! windows = "lumberyard\foo\bar\name.txt", posix = "lumberyard/foo/bar/name.txt" + //! windows = "O3DE\foo\bar\name.txt", posix = "O3DE/foo/bar/name.txt" constexpr PathView RelativePath() const; //! Returns the parent directory of filename contained within the path - //! windows = "C:\lumberyard\foo\bar", posix = "/lumberyard/foo/bar" + //! windows = "C:\O3DE\foo\bar", posix = "/O3DE/foo/bar" //! NOTE: If the path ends with a trailing separator "test/foo/" it is treated as being a path of //! "test/foo" as if the filename of the path is "foo" and the parent directory is "test" constexpr PathView ParentPath() const; @@ -521,8 +521,8 @@ namespace AZ::IO //! The root portion of the path is made up of root_name() / root_directory() [[nodiscard]] constexpr bool HasRootPath() const; //! checks whether the relative part of path is empty - //! (C:\\ lumberyard\dev\) - //! ^ ^ + //! (C:\\ O3DE\dev\) + //! ^ ^ //! root part relative part [[nodiscard]] constexpr bool HasRelativePath() const; //! checks whether the path has a parent path that empty @@ -544,8 +544,8 @@ namespace AZ::IO [[nodiscard]] constexpr bool IsRelativeTo(const PathView& base) const; // decomposition - //! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of - //! "/lumberyard/foo/bar/name.txt" + //! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of + //! "/O3DE/foo/bar/name.txt" //! The following functions return the following // query diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp index dc1fac68e0..33b319bbb1 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp @@ -147,15 +147,18 @@ namespace AZ ReadFile(request, args); return; } - else if constexpr (AZStd::is_same_v) + else { - FlushCache(args.m_path); + if constexpr (AZStd::is_same_v) + { + FlushCache(args.m_path); + } + else if constexpr (AZStd::is_same_v) + { + FlushEntireCache(); + } + StreamStackEntry::QueueRequest(request); } - else if constexpr (AZStd::is_same_v) - { - FlushEntireCache(); - } - StreamStackEntry::QueueRequest(request); }, request->GetCommand()); } diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp index 20997eac59..8990ac3eb9 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp @@ -146,15 +146,18 @@ namespace AZ DestroyDedicatedCache(request, args); return; } - else if constexpr (AZStd::is_same_v) + else { - FlushCache(args.m_path); + if constexpr (AZStd::is_same_v) + { + FlushCache(args.m_path); + } + else if constexpr (AZStd::is_same_v) + { + FlushEntireCache(); + } + StreamStackEntry::QueueRequest(request); } - else if constexpr (AZStd::is_same_v) - { - FlushEntireCache(); - } - StreamStackEntry::QueueRequest(request); }, request->GetCommand()); } diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/StorageDrive.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/StorageDrive.cpp index 62deaf7388..451d23a78d 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/StorageDrive.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/StorageDrive.cpp @@ -97,19 +97,22 @@ namespace AZ CancelRequest(request, args.m_target); return; } - else if constexpr (AZStd::is_same_v) + else { - FlushCache(args.m_path); + if constexpr (AZStd::is_same_v) + { + FlushCache(args.m_path); + } + else if constexpr (AZStd::is_same_v) + { + FlushEntireCache(); + } + else if constexpr (AZStd::is_same_v) + { + Report(args); + } + StreamStackEntry::QueueRequest(request); } - else if constexpr (AZStd::is_same_v) - { - FlushEntireCache(); - } - else if constexpr (AZStd::is_same_v) - { - Report(args); - } - StreamStackEntry::QueueRequest(request); }, request->GetCommand()); } diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp index 3e3c366485..db09a86908 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp @@ -374,7 +374,7 @@ namespace AZ targetForward.Normalize(); - // Lumberyard is Z-up and is right-handed. + // Open 3D Engine is Z-up and is right-handed. Vector3 up = Vector3::CreateAxisZ(); // We have a degenerate case if target forward is parallel to the up axis, @@ -391,7 +391,7 @@ namespace AZ up.Normalize(); // Passing in forwardAxis allows you to force a particular local-space axis to look - // at the target point. In Lumberyard, the default is forward is along Y+. + // at the target point. In Open 3D Engine, the default is forward is along Y+. switch (forwardAxis) { case Axis::XPositive: diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.cpp b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.cpp index df85fd7f18..49b2eeab47 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.cpp @@ -426,7 +426,7 @@ namespace AZ Matrix4x4 Matrix4x4::CreateProjection(float fovY, float aspectRatio, float nearDist, float farDist) { // This section contains some notes about camera matrices and field of view, because there are some subtle differences - // between the convention Lumberyard uses and what you might be used to from other software packages. + // between the convention Open 3D Engine uses and what you might be used to from other software packages. // Our camera space has the camera looking down the *positive* z-axis, the x-axis points towards the left of the screen, // and the y-axis points towards the top of the screen. // diff --git a/Code/Framework/AzCore/AzCore/Math/Obb.cpp b/Code/Framework/AzCore/AzCore/Math/Obb.cpp index 4bbecbb647..eb511669d0 100644 --- a/Code/Framework/AzCore/AzCore/Math/Obb.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Obb.cpp @@ -154,7 +154,7 @@ namespace AZ return Obb::CreateFromPositionRotationAndHalfLengths( transform.TransformPoint(obb.GetPosition()), transform.GetRotation() * obb.GetRotation(), - obb.GetHalfLengths() + transform.GetScale() * obb.GetHalfLengths() ); } } diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.cpp b/Code/Framework/AzCore/AzCore/Math/Transform.cpp index 3845b7b570..77d8658d0f 100644 --- a/Code/Framework/AzCore/AzCore/Math/Transform.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Transform.cpp @@ -354,7 +354,7 @@ namespace AZ targetForward.Normalize(); - // Lumberyard is Z-up and is right-handed. + // Open 3D Engine is Z-up and is right-handed. Vector3 up = Vector3::CreateAxisZ(); // We have a degenerate case if target forward is parallel to the up axis, @@ -371,7 +371,7 @@ namespace AZ up.Normalize(); // Passing in forwardAxis allows you to force a particular local-space axis to look - // at the target point. In Lumberyard, the default is forward is along Y+. + // at the target point. In Open 3D Engine, the default is forward is along Y+. switch (forwardAxis) { case Axis::XPositive: diff --git a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp index 76e745bc00..4c33c332da 100644 --- a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp @@ -707,7 +707,7 @@ PoolSchema::GarbageCollect() // occur exclusively in the destruction of the allocator. // // TODO: A better solution needs to be found for integrating back into mainline - // Lumberyard. + // Open 3D Engine. //m_impl->GarbageCollect(); } diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp index b01062fe2c..ac1e61a5aa 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp @@ -1600,7 +1600,7 @@ static int Global_Typeid(lua_State* l) return 1; } -#ifdef LUA_LUMBERYARD_EXTENSIONS +#ifdef LUA_O3DE_EXTENSIONS //========================================================================= // LUA Dummy Node Extension @@ -1631,7 +1631,7 @@ LUA_API const Node* lua_getDummyNode() return &(*s_luaDummyNodeVariable); } -#endif // LUA_LUMBERYARD_EXTENSIONS +#endif // LUA_O3DE_EXTENSIONS ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl index d4658d4e8c..eac6e5760e 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl @@ -103,7 +103,7 @@ namespace AZ const static AZ::Crc32 ChangeNotify = AZ_CRC("ChangeNotify", 0xf793bc19); const static AZ::Crc32 ClearNotify = AZ_CRC("ClearNotify", 0x88914c8c); - //! Specifies a function to accept or reject a value changed in the Lumberyard Editor. + //! Specifies a function to accept or reject a value changed in the Open 3D Engine Editor. //! For example, a component could reject AZ::EntityId values that reference its own entity. //! //! Element type to use this with: Any type that you reflect using AZ::EditContext::ClassInfo::DataElement(). diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp index 4d506e1960..6c67fd284a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp @@ -22,9 +22,9 @@ namespace AZ // JsonBaseContext // - JsonBaseContext::JsonBaseContext(JsonSerializationMetadata metadata, JsonSerializationResult::JsonIssueCallback reporting, + JsonBaseContext::JsonBaseContext(JsonSerializationMetadata& metadata, JsonSerializationResult::JsonIssueCallback reporting, StackedString::Format pathFormat, SerializeContext* serializeContext, JsonRegistrationContext* registrationContext) - : m_metadata(AZStd::move(metadata)) + : m_metadata(metadata) , m_serializeContext(serializeContext) , m_registrationContext(registrationContext) , m_path(pathFormat) @@ -126,20 +126,13 @@ namespace AZ // JsonDeserializerContext // - JsonDeserializerContext::JsonDeserializerContext(const JsonDeserializerSettings& settings) + JsonDeserializerContext::JsonDeserializerContext(JsonDeserializerSettings& settings) : JsonBaseContext(settings.m_metadata, settings.m_reporting, StackedString::Format::JsonPointer, settings.m_serializeContext, settings.m_registrationContext) , m_clearContainers(settings.m_clearContainers) { } - JsonDeserializerContext::JsonDeserializerContext(JsonDeserializerSettings&& settings) - : JsonBaseContext(AZStd::move(settings.m_metadata), AZStd::move(settings.m_reporting), - StackedString::Format::JsonPointer, settings.m_serializeContext, settings.m_registrationContext) - , m_clearContainers(settings.m_clearContainers) - { - } - bool JsonDeserializerContext::ShouldClearContainers() const { return m_clearContainers; @@ -151,7 +144,7 @@ namespace AZ // JsonSerializerContext // - JsonSerializerContext::JsonSerializerContext(const JsonSerializerSettings& settings, rapidjson::Document::AllocatorType& jsonAllocator) + JsonSerializerContext::JsonSerializerContext(JsonSerializerSettings& settings, rapidjson::Document::AllocatorType& jsonAllocator) : JsonBaseContext(settings.m_metadata, settings.m_reporting, StackedString::Format::ContextPath, settings.m_serializeContext, settings.m_registrationContext) , m_jsonAllocator(jsonAllocator) @@ -159,14 +152,6 @@ namespace AZ { } - JsonSerializerContext::JsonSerializerContext(JsonSerializerSettings&& settings, rapidjson::Document::AllocatorType& jsonAllocator) - : JsonBaseContext(AZStd::move(settings.m_metadata), AZStd::move(settings.m_reporting), StackedString::Format::ContextPath, - settings.m_serializeContext, settings.m_registrationContext) - , m_jsonAllocator(jsonAllocator) - , m_keepDefaults(settings.m_keepDefaults) - { - } - rapidjson::Document::AllocatorType& JsonSerializerContext::GetJsonAllocator() { return m_jsonAllocator; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h index da6483d592..f6ced44583 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h @@ -26,7 +26,7 @@ namespace AZ class JsonBaseContext { public: - JsonBaseContext(JsonSerializationMetadata metadata, JsonSerializationResult::JsonIssueCallback reporting, + JsonBaseContext(JsonSerializationMetadata& metadata, JsonSerializationResult::JsonIssueCallback reporting, StackedString::Format pathFormat, SerializeContext* serializeContext, JsonRegistrationContext* registrationContext); virtual ~JsonBaseContext() = default; @@ -71,10 +71,6 @@ namespace AZ const JsonRegistrationContext* GetRegistrationContext() const; protected: - //! Metadata that's passed in by the settings as additional configuration options or metadata that's collected - //! during processing for later use. - JsonSerializationMetadata m_metadata; - //! Callback used to report progress and issues. Users of the serialization can update the return code to change //! the behavior of the serializer. AZStd::stack m_reporters; @@ -82,6 +78,10 @@ namespace AZ //! Path to the element that's currently being operated on. StackedString m_path; + //! Metadata that's passed in by the settings as additional configuration options or metadata that's collected + //! during processing for later use. + JsonSerializationMetadata& m_metadata; + //! The Serialize Context that can be used to retrieve meta data during processing. SerializeContext* m_serializeContext = nullptr; //! The registration context for the json serialization. This can be used to retrieve the handlers for specific types. @@ -92,8 +92,7 @@ namespace AZ : public JsonBaseContext { public: - explicit JsonDeserializerContext(const JsonDeserializerSettings& settings); - explicit JsonDeserializerContext(JsonDeserializerSettings&& settings); + explicit JsonDeserializerContext(JsonDeserializerSettings& settings); ~JsonDeserializerContext() override = default; JsonDeserializerContext(const JsonDeserializerContext&) = delete; @@ -114,8 +113,7 @@ namespace AZ : public JsonBaseContext { public: - explicit JsonSerializerContext(const JsonSerializerSettings& settings, rapidjson::Document::AllocatorType& jsonAllocator); - explicit JsonSerializerContext(JsonSerializerSettings&& settings, rapidjson::Document::AllocatorType& jsonAllocator); + JsonSerializerContext(JsonSerializerSettings& settings, rapidjson::Document::AllocatorType& jsonAllocator); ~JsonSerializerContext() override = default; JsonSerializerContext(const JsonSerializerContext&) = delete; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp index aea239e3b9..e359888da7 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp @@ -20,7 +20,7 @@ namespace AZ { JsonSerializationResult::ResultCode JsonMerger::ApplyPatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, - const JsonApplyPatchSettings& settings) + JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -122,7 +122,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::CreatePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, const JsonCreatePatchSettings& settings) + const rapidjson::Value& target, JsonCreatePatchSettings& settings) { StackedString element(StackedString::Format::JsonPointer); return CreatePatchInternal(patch.SetArray(), allocator, source, target, element, settings); @@ -130,7 +130,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyMergePatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, - const JsonApplyPatchSettings& settings) + JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -196,14 +196,14 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::CreateMergePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, const JsonCreatePatchSettings& settings) + const rapidjson::Value& target, JsonCreatePatchSettings& settings) { StackedString element(StackedString::Format::JsonPointer); return CreateMergePatchInternal(patch, allocator, source, target, element, settings); } JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_GetFromValue(rapidjson::Value** fromValue, rapidjson::Pointer& fromPointer, - rapidjson::Value& target, const rapidjson::Value& entry, StackedString& element, const JsonApplyPatchSettings& settings) + rapidjson::Value& target, const rapidjson::Value& entry, StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -242,7 +242,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Add(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& entry, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -261,7 +261,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_AddValue(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Pointer& path, rapidjson::Value&& newValue, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -347,7 +347,7 @@ namespace AZ } JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Remove(rapidjson::Value& target, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -399,7 +399,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Replace(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& entry, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -426,7 +426,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Move(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& entry, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -445,7 +445,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Copy(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& entry, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings) + StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -463,7 +463,7 @@ namespace AZ } JsonSerializationResult::ResultCode JsonMerger::ApplyPatch_Test(rapidjson::Value& target, const rapidjson::Value& entry, - const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings) + const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -495,7 +495,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::CreatePatchInternal(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, StackedString& element, const JsonCreatePatchSettings& settings) + const rapidjson::Value& target, StackedString& element, JsonCreatePatchSettings& settings) { using namespace JsonSerializationResult; @@ -633,7 +633,7 @@ namespace AZ JsonSerializationResult::ResultCode JsonMerger::CreateMergePatchInternal(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, StackedString& element, const JsonCreatePatchSettings& settings) + const rapidjson::Value& target, StackedString& element, JsonCreatePatchSettings& settings) { using namespace JsonSerializationResult; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.h index f016897165..a33bac117b 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.h @@ -30,43 +30,43 @@ namespace AZ //! Implementation of the JSON Patch algorithm: https://tools.ietf.org/html/rfc6902 static JsonSerializationResult::ResultCode ApplyPatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, - const JsonApplyPatchSettings& settings); + JsonApplyPatchSettings& settings); //! Function to create JSON Patches: https://tools.ietf.org/html/rfc6902 static JsonSerializationResult::ResultCode CreatePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, const JsonCreatePatchSettings& settings); + const rapidjson::Value& target, JsonCreatePatchSettings& settings); //! Implementation of the JSON Merge Patch algorithm: https://tools.ietf.org/html/rfc7386 static JsonSerializationResult::ResultCode ApplyMergePatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, - const JsonApplyPatchSettings& settings); + JsonApplyPatchSettings& settings); //! Function to create JSON Merge Patches: https://tools.ietf.org/html/rfc7386 static JsonSerializationResult::ResultCode CreateMergePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, const JsonCreatePatchSettings& settings); + const rapidjson::Value& target, JsonCreatePatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_GetFromValue(rapidjson::Value** fromValue, rapidjson::Pointer& fromPointer, - rapidjson::Value& target, const rapidjson::Value& entry, StackedString& element, const JsonApplyPatchSettings& settings); + rapidjson::Value& target, const rapidjson::Value& entry, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Add(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_AddValue(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Pointer& path, rapidjson::Value&& newValue, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Pointer& path, rapidjson::Value&& newValue, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Remove(rapidjson::Value& target, const rapidjson::Pointer& path, - StackedString& element, const JsonApplyPatchSettings& settings); + StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Replace(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Move(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Copy(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode ApplyPatch_Test(rapidjson::Value& target, - const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, const JsonApplyPatchSettings& settings); + const rapidjson::Value& entry, const rapidjson::Pointer& path, StackedString& element, JsonApplyPatchSettings& settings); static JsonSerializationResult::ResultCode CreatePatchInternal(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, StackedString& element, const JsonCreatePatchSettings& settings); + const rapidjson::Value& target, StackedString& element, JsonCreatePatchSettings& settings); static rapidjson::Value CreatePatchInternal_Add(rapidjson::Document::AllocatorType& allocator, StackedString& path, const rapidjson::Value& value); static rapidjson::Value CreatePatchInternal_Remove(rapidjson::Document::AllocatorType& allocator, StackedString& path); @@ -75,6 +75,6 @@ namespace AZ static JsonSerializationResult::ResultCode CreateMergePatchInternal(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, - const rapidjson::Value& target, StackedString& element, const JsonCreatePatchSettings& settings); + const rapidjson::Value& target, StackedString& element, JsonCreatePatchSettings& settings); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp index f9359b890f..0629f1c32e 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp @@ -97,9 +97,18 @@ namespace AZ } } // namespace JsonSerializationInternal + JsonSerializationResult::ResultCode JsonSerialization::ApplyPatch( + rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, JsonMergeApproach approach, + const JsonApplyPatchSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonApplyPatchSettings settingsCopy{ settings }; + return ApplyPatch(target, allocator, patch, approach, settingsCopy); + } + JsonSerializationResult::ResultCode JsonSerialization::ApplyPatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, JsonMergeApproach approach, - JsonApplyPatchSettings settings) + JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -126,8 +135,17 @@ namespace AZ } } + JsonSerializationResult::ResultCode JsonSerialization::ApplyPatch( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, + const rapidjson::Value& patch, JsonMergeApproach approach, const JsonApplyPatchSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonApplyPatchSettings settingsCopy{settings}; + return ApplyPatch(output, allocator, source, patch, approach, settingsCopy); + } + JsonSerializationResult::ResultCode JsonSerialization::ApplyPatch(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& source, const rapidjson::Value& patch, JsonMergeApproach approach, JsonApplyPatchSettings settings) + const rapidjson::Value& source, const rapidjson::Value& patch, JsonMergeApproach approach, JsonApplyPatchSettings& settings) { using namespace JsonSerializationResult; @@ -166,9 +184,18 @@ namespace AZ return result; } + JsonSerializationResult::ResultCode JsonSerialization::CreatePatch( + rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, + const rapidjson::Value& target, JsonMergeApproach approach, const JsonCreatePatchSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonCreatePatchSettings settingsCopy{settings}; + return CreatePatch(patch, allocator, source, target, approach, settingsCopy); + } - JsonSerializationResult::ResultCode JsonSerialization::CreatePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& source, const rapidjson::Value& target, JsonMergeApproach approach, JsonCreatePatchSettings settings) + JsonSerializationResult::ResultCode JsonSerialization::CreatePatch( + rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, + const rapidjson::Value& target, JsonMergeApproach approach, JsonCreatePatchSettings& settings) { using namespace JsonSerializationResult; @@ -194,7 +221,16 @@ namespace AZ } } - JsonSerializationResult::ResultCode JsonSerialization::Load(void* object, const Uuid& objectType, const rapidjson::Value& root, JsonDeserializerSettings settings) + JsonSerializationResult::ResultCode JsonSerialization::Load( + void* object, const Uuid& objectType, const rapidjson::Value& root, const JsonDeserializerSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonDeserializerSettings settingsCopy{settings}; + return Load(object, objectType, root, settingsCopy); + } + + JsonSerializationResult::ResultCode JsonSerialization::Load( + void* object, const Uuid& objectType, const rapidjson::Value& root, JsonDeserializerSettings& settings) { using namespace JsonSerializationResult; @@ -212,14 +248,23 @@ namespace AZ if (result.GetOutcome() == Outcomes::Success) { StackedString path(StackedString::Format::JsonPointer); - JsonDeserializerContext context(AZStd::move(settings)); + JsonDeserializerContext context(settings); result = JsonDeserializer::Load(object, objectType, root, context); } return result; } + JsonSerializationResult::ResultCode JsonSerialization::LoadTypeId( + Uuid& typeId, const rapidjson::Value& input, const Uuid* baseClassTypeId, AZStd::string_view jsonPath, + const JsonDeserializerSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonDeserializerSettings settingsCopy{settings}; + return LoadTypeId(typeId, input, baseClassTypeId, jsonPath, settingsCopy); + } + JsonSerializationResult::ResultCode JsonSerialization::LoadTypeId(Uuid& typeId, const rapidjson::Value& input, - const Uuid* baseClassTypeId, AZStd::string_view jsonPath, JsonDeserializerSettings settings) + const Uuid* baseClassTypeId, AZStd::string_view jsonPath, JsonDeserializerSettings& settings) { using namespace JsonSerializationResult; @@ -236,7 +281,7 @@ namespace AZ ResultCode result = JsonSerializationInternal::GetContexts(settings, settings.m_serializeContext, settings.m_registrationContext); if (result.GetOutcome() == Outcomes::Success) { - JsonDeserializerContext context(AZStd::move(settings)); + JsonDeserializerContext context(settings); context.PushPath(jsonPath); result = JsonDeserializer::LoadTypeId(typeId, input, context, baseClassTypeId); @@ -244,8 +289,18 @@ namespace AZ return result; } - JsonSerializationResult::ResultCode JsonSerialization::Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const void* object, const void* defaultObject, const Uuid& objectType, JsonSerializerSettings settings) + JsonSerializationResult::ResultCode JsonSerialization::Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const void* object, const void* defaultObject, + const Uuid& objectType, const JsonSerializerSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonSerializerSettings settingsCopy{settings}; + return Store(output, allocator, object, defaultObject, objectType, settingsCopy); + } + + JsonSerializationResult::ResultCode JsonSerialization::Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const void* object, const void* defaultObject, + const Uuid& objectType, JsonSerializerSettings& settings) { using namespace JsonSerializationResult; @@ -269,15 +324,24 @@ namespace AZ settings.m_keepDefaults = false; } - JsonSerializerContext context(AZStd::move(settings), allocator); + JsonSerializerContext context(settings, allocator); StackedString path(StackedString::Format::ContextPath); result = JsonSerializer::Store(output, object, defaultObject, objectType, context); } return result; } + JsonSerializationResult::ResultCode JsonSerialization::StoreTypeId( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const Uuid& typeId, AZStd::string_view elementPath, + const JsonSerializerSettings& settings) + { + // Explicitly make a copy to call the correct overloaded version and avoid infinite recursion on this function. + JsonSerializerSettings settingsCopy{settings}; + return StoreTypeId(output, allocator, typeId, elementPath, settingsCopy); + } + JsonSerializationResult::ResultCode JsonSerialization::StoreTypeId(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const Uuid& typeId, AZStd::string_view elementPath, JsonSerializerSettings settings) + const Uuid& typeId, AZStd::string_view elementPath, JsonSerializerSettings& settings) { using namespace JsonSerializationResult; @@ -294,7 +358,7 @@ namespace AZ ResultCode result = JsonSerializationInternal::GetContexts(settings, settings.m_serializeContext, settings.m_registrationContext); if (result.GetOutcome() == Outcomes::Success) { - JsonSerializerContext context(AZStd::move(settings), allocator); + JsonSerializerContext context(settings, allocator); context.PushPath(elementPath); result = JsonSerializer::StoreTypeName(output, typeId, context); } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h index 58c2c390a1..5746005832 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h @@ -48,14 +48,25 @@ namespace AZ //! Merges two json values together by applying "patch" to "target" using the selected merge algorithm. //! This version of ApplyPatch is destructive to "target". If the patch can't be correctly applied it will - //! leave target in a partially patched state. Use the over version of ApplyPatch if target should be copied. + //! leave target in a partially patched state. Use the other version of ApplyPatch if target should be copied. //! @param target The value where the patch will be applied to. //! @param allocator The allocator associated with the document that holds the target. //! @param patch The value holding the patch information. //! @param approach The merge algorithm that will be used to apply the patch on top of the target. //! @param settings Optional additional settings to control the way the patch is applied. static JsonSerializationResult::ResultCode ApplyPatch(rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, - const rapidjson::Value& patch, JsonMergeApproach approach, JsonApplyPatchSettings settings = JsonApplyPatchSettings{}); + const rapidjson::Value& patch, JsonMergeApproach approach, const JsonApplyPatchSettings& settings = JsonApplyPatchSettings{}); + //! Merges two json values together by applying "patch" to "target" using the selected merge algorithm. + //! This version of ApplyPatch is destructive to "target". If the patch can't be correctly applied it will + //! leave target in a partially patched state. Use the other version of ApplyPatch if target should be copied. + //! @param target The value where the patch will be applied to. + //! @param allocator The allocator associated with the document that holds the target. + //! @param patch The value holding the patch information. + //! @param approach The merge algorithm that will be used to apply the patch on top of the target. + //! @param settings Additional settings to control the way the patch is applied. + static JsonSerializationResult::ResultCode ApplyPatch( + rapidjson::Value& target, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& patch, + JsonMergeApproach approach, JsonApplyPatchSettings& settings); //! Merges two json values together by applying "patch" to a copy of "output" and written to output using the //! selected merge algorithm. This version of ApplyPatch is non-destructive to "source". If the patch couldn't be @@ -68,7 +79,19 @@ namespace AZ //! @param settings Optional additional settings to control the way the patch is applied. static JsonSerializationResult::ResultCode ApplyPatch(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, const rapidjson::Value& patch, JsonMergeApproach approach, - JsonApplyPatchSettings settings = JsonApplyPatchSettings{}); + const JsonApplyPatchSettings& settings = JsonApplyPatchSettings{}); + //! Merges two json values together by applying "patch" to a copy of "output" and written to output using the + //! selected merge algorithm. This version of ApplyPatch is non-destructive to "source". If the patch couldn't be + //! fully applied "output" will be left set to an empty (default) object. + //! @param source A copy of source with the patch applied to it or an empty object if the patch couldn't be applied. + //! @param allocator The allocator associated with the document that holds the source. + //! @param target The value where the patch will be applied to. + //! @param patch The value holding the patch information. + //! @param approach The merge algorithm that will be used to apply the patch on top of the target. + //! @param settings Additional settings to control the way the patch is applied. + static JsonSerializationResult::ResultCode ApplyPatch( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, + const rapidjson::Value& patch, JsonMergeApproach approach, JsonApplyPatchSettings& settings); //! Creates a patch using the selected merge algorithm such that when applied to source it results in target. //! @param patch The value containing the differences between source and target. @@ -79,22 +102,46 @@ namespace AZ //! @param settings Optional additional settings to control the way the patch is created. static JsonSerializationResult::ResultCode CreatePatch(rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, const rapidjson::Value& target, JsonMergeApproach approach, - JsonCreatePatchSettings settings = JsonCreatePatchSettings{}); + const JsonCreatePatchSettings& settings = JsonCreatePatchSettings{}); + //! Creates a patch using the selected merge algorithm such that when applied to source it results in target. + //! @param patch The value containing the differences between source and target. + //! @param allocator The allocator associated with the document that will hold the patch. + //! @param source The value used as a starting point. + //! @param target The value that will result if the patch is applied to the source. + //! @param approach The algorithm that will be used when the patch is applied to the source. + //! @param settings Additional settings to control the way the patch is created. + static JsonSerializationResult::ResultCode CreatePatch( + rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& source, + const rapidjson::Value& target, JsonMergeApproach approach, JsonCreatePatchSettings& settings); //! Loads the data from the provided json value into the supplied object. The object is expected to be created before calling load. //! @param object Object where the data will be loaded into. //! @param root The Value or Document where the deserializer will start reading data from. - //! @param settings The settings used during deserialization. Use the value passed in from Load. + //! @param settings Optional additional settings to control the way document is deserialized. template - static JsonSerializationResult::ResultCode Load(T& object, const rapidjson::Value& root, - JsonDeserializerSettings settings = JsonDeserializerSettings{}); + static JsonSerializationResult::ResultCode Load( + T& object, const rapidjson::Value& root, const JsonDeserializerSettings& settings = JsonDeserializerSettings{}); + //! Loads the data from the provided json value into the supplied object. The object is expected to be created before calling load. + //! @param object Object where the data will be loaded into. + //! @param root The Value or Document where the deserializer will start reading data from. + //! @param settings Additional settings to control the way document is deserialized. + template + static JsonSerializationResult::ResultCode Load(T& object, const rapidjson::Value& root, JsonDeserializerSettings& settings); //! Loads the data from the provided json value into the supplied object. The object is expected to be created before calling load. //! @param object Pointer to the object where the data will be loaded into. //! @param objectType Type id of the object passed in. //! @param root The Value or Document from where the deserializer will start reading data. - //! @param settings The settings used during deserialization. Use the value passed in from Load. - static JsonSerializationResult::ResultCode Load(void* object, const Uuid& objectType, const rapidjson::Value& root, - JsonDeserializerSettings settings = JsonDeserializerSettings{}); + //! @param settings Optional additional settings to control the way document is deserialized. + static JsonSerializationResult::ResultCode Load( + void* object, const Uuid& objectType, const rapidjson::Value& root, + const JsonDeserializerSettings& settings = JsonDeserializerSettings{}); + //! Loads the data from the provided json value into the supplied object. The object is expected to be created before calling load. + //! @param object Pointer to the object where the data will be loaded into. + //! @param objectType Type id of the object passed in. + //! @param root The Value or Document from where the deserializer will start reading data. + //! @param settings Additional settings to control the way document is deserialized. + static JsonSerializationResult::ResultCode Load( + void* object, const Uuid& objectType, const rapidjson::Value& root, JsonDeserializerSettings& settings); //! Loads the type id from the provided input. //! Note: it's not recommended to use this function (frequently) as it requires users of the json file to have knowledge of the internal @@ -105,20 +152,44 @@ namespace AZ //! references multiple types then the baseClassTypeId will be used to disambiguate between the different types by looking //! if exactly one of the types inherits from the base class that baseClassTypeId points to. //! @param jsonPath An optional path to the json node. This will be used for reporting. - //! @param settings An optional settings object to change where this function collects information from. This can be same settings + //! @param settings Optional settings object to change where this function collects information from. This can be same settings //! as used for the other Load functions. static JsonSerializationResult::ResultCode LoadTypeId(Uuid& typeId, const rapidjson::Value& input, const Uuid* baseClassTypeId = nullptr, AZStd::string_view jsonPath = AZStd::string_view{}, - JsonDeserializerSettings settings = JsonDeserializerSettings{}); + const JsonDeserializerSettings& settings = JsonDeserializerSettings{}); + //! Loads the type id from the provided input. + //! Note: it's not recommended to use this function (frequently) as it requires users of the json file to have knowledge of the + //! internal type structure and is therefore harder to use. + //! @param typeId The uuid where the loaded data will be written to. If loading fails this will be a null uuid. + //! @param input The json node to load from. The node is expected to contain a string. + //! @param baseClassTypeId. An optional type id for the base class, if known. If a type name is stored in the string which + //! references multiple types then the baseClassTypeId will be used to disambiguate between the different types by looking + //! if exactly one of the types inherits from the base class that baseClassTypeId points to. + //! @param jsonPath An optional path to the json node. This will be used for reporting. + //! @param settings Settings object to change where this function collects information from. This can be same settings + //! as used for the other Load functions. + static JsonSerializationResult::ResultCode LoadTypeId( + Uuid& typeId, const rapidjson::Value& input, const Uuid* baseClassTypeId, + AZStd::string_view jsonPath, JsonDeserializerSettings& settings); //! Stores the data in the provided object as json values starting at the provided value. //! @param output The Value or Document where the converted data will start writing to. //! @param allocator The memory allocator used by RapidJSON to create the json document. //! @param object The object that will be read from for values to convert. - //! @param settings The settings used during serialization. Use the value passed in from Store. + //! @param settings Optional additional settings to control the way document is serialized. template - static JsonSerializationResult::ResultCode Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const T& object, JsonSerializerSettings settings = JsonSerializerSettings{}); + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, + const JsonSerializerSettings& settings = JsonSerializerSettings{}); + //! Stores the data in the provided object as json values starting at the provided value. + //! @param output The Value or Document where the converted data will start writing to. + //! @param allocator The memory allocator used by RapidJSON to create the json document. + //! @param object The object that will be read from for values to convert. + //! @param settings Additional settings to control the way document is serialized. + template + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, + JsonSerializerSettings& settings); //! Stores the data in the provided object as json values starting at the provided value. //! @param output The Value or Document where the converted data will start writing to. @@ -127,10 +198,23 @@ namespace AZ //! @param defaultObject Default object used to compare the object to in order to determine if values are //! defaulted or not. If this is argument is provided m_keepDefaults in the settings will automatically //! be set to true. - //! @param settings The settings used during serialization. Use the value passed in from Store. + //! @param settings Optional additional settings to control the way document is serialized. template - static JsonSerializationResult::ResultCode Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const T& object, const T& defaultObject, JsonSerializerSettings settings = JsonSerializerSettings{}); + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, const T& defaultObject, + const JsonSerializerSettings& settings = JsonSerializerSettings{}); + //! Stores the data in the provided object as json values starting at the provided value. + //! @param output The Value or Document where the converted data will start writing to. + //! @param allocator The memory allocator used by RapidJSON to create the json document. + //! @param object The object that will be read from for values to convert. + //! @param defaultObject Default object used to compare the object to in order to determine if values are + //! defaulted or not. If this is argument is provided m_keepDefaults in the settings will automatically + //! be set to true. + //! @param settings Additional settings to control the way document is serialized. + template + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, const T& defaultObject, + JsonSerializerSettings& settings); //! Stores the data in the provided object as json values starting at the provided value. //! @param output The Value or Document where the converted data will start writing to. @@ -140,10 +224,22 @@ namespace AZ //! defaulted or not. This argument can be null, in which case a temporary default may be created if required by //! the settings. If this is argument is provided m_keepDefaults in the settings will automatically be set to true. //! @param objectType The type id of the object and default object. - //! @param settings The settings used during serialization. Use the value passed in from Store. - static JsonSerializationResult::ResultCode Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const void* object, const void* defaultObject, const Uuid& objectType, - JsonSerializerSettings settings = JsonSerializerSettings{}); + //! @param settings Optional additional settings to control the way document is serialized. + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const void* object, const void* defaultObject, + const Uuid& objectType, const JsonSerializerSettings& settings = JsonSerializerSettings{}); + //! Stores the data in the provided object as json values starting at the provided value. + //! @param output The Value or Document where the converted data will start writing to. + //! @param allocator The memory allocator used by RapidJSON to create the json document. + //! @param object Pointer to the object that will be read from for values to convert. + //! @param defaultObject Pointer to a default object used to compare the object to in order to determine if values are + //! defaulted or not. This argument can be null, in which case a temporary default may be created if required by + //! the settings. If this is argument is provided m_keepDefaults in the settings will automatically be set to true. + //! @param objectType The type id of the object and default object. + //! @param settings Additional settings to control the way document is serialized. + static JsonSerializationResult::ResultCode Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const void* object, const void* defaultObject, + const Uuid& objectType, JsonSerializerSettings& settings); //! Stores a name for the type id in the provided output. The name can be safely used to reference a type such as a class during loading. //! Note: it's not recommended to use this function (frequently) as it requires users of the json file to have knowledge of the internal @@ -152,10 +248,25 @@ namespace AZ //! @param allocator The allocator associated with the document that will or already holds the output. //! @param typeId The type id to store. //! @param elementPath An optional path to the element. This will be used for reporting. - //! @param settings An optional settings object to change where this function collects information from. This can be same settings + //! @param settings Optional settings to change where this function collects information from. This can be the same settings //! as used for the other Store functions. - static JsonSerializationResult::ResultCode StoreTypeId(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const Uuid& typeId, AZStd::string_view elementPath = AZStd::string_view{}, JsonSerializerSettings settings = JsonSerializerSettings{}); + static JsonSerializationResult::ResultCode StoreTypeId( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const Uuid& typeId, + AZStd::string_view elementPath = AZStd::string_view{}, const JsonSerializerSettings& settings = JsonSerializerSettings{}); + //! Stores a name for the type id in the provided output. The name can be safely used to reference a type such as a class during + //! loading. Note: it's not recommended to use this function (frequently) as it requires users of the json file to have knowledge of + //! the internal + //! type structure and is therefore harder to use. + //! @param output The json value the result will be written to. If successful this will contain a string object otherwise a default + //! object. + //! @param allocator The allocator associated with the document that will or already holds the output. + //! @param typeId The type id to store. + //! @param elementPath The path to the element. This will be used for reporting. + //! @param settings Settings to change where this function collects information from. This can be the same settings + //! as used for the other Store functions. + static JsonSerializationResult::ResultCode StoreTypeId( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const Uuid& typeId, + AZStd::string_view elementPath, JsonSerializerSettings& settings); //! Compares two json values of any type and determines if the left is less, equal or greater than the right. //! @param lhs The left hand side value for the compare. @@ -180,22 +291,43 @@ namespace AZ }; template - JsonSerializationResult::ResultCode JsonSerialization::Load(T& object, const rapidjson::Value& root, JsonDeserializerSettings settings) + JsonSerializationResult::ResultCode JsonSerialization::Load(T& object, const rapidjson::Value& root, const JsonDeserializerSettings& settings) { return Load(&object, azrtti_typeid(object), root, settings); } template - JsonSerializationResult::ResultCode JsonSerialization::Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const T& object, JsonSerializerSettings settings) + JsonSerializationResult::ResultCode JsonSerialization::Load(T& object, const rapidjson::Value& root, JsonDeserializerSettings& settings) + { + return Load(&object, azrtti_typeid(object), root, settings); + } + + template + JsonSerializationResult::ResultCode JsonSerialization::Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, const JsonSerializerSettings& settings) + { + return Store(output, allocator, &object, nullptr, azrtti_typeid(object), settings); + } + + template + JsonSerializationResult::ResultCode JsonSerialization::Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, JsonSerializerSettings& settings) { return Store(output, allocator, &object, nullptr, azrtti_typeid(object), settings); } template JsonSerializationResult::ResultCode JsonSerialization::Store(rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, - const T& object, const T& defaultObject, JsonSerializerSettings settings) + const T& object, const T& defaultObject, const JsonSerializerSettings& settings) { return Store(output, allocator, &object,& defaultObject, azrtti_typeid(object), settings); } + + template + JsonSerializationResult::ResultCode JsonSerialization::Store( + rapidjson::Value& output, rapidjson::Document::AllocatorType& allocator, const T& object, const T& defaultObject, + JsonSerializerSettings& settings) + { + return Store(output, allocator, &object, &defaultObject, azrtti_typeid(object), settings); + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.h index d48f5f8d39..97d57f0631 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.h @@ -22,14 +22,20 @@ namespace AZ class JsonSerializationMetadata final { public: + //! Creates a new settings object in the metadata collection. + //! Only one object of the same type can be added or created. + //! Returns false if an object of this type was already added. + template + bool Create(Args&&... args); + //! Adds a new settings object to the metadata collection. - //! Only one object of the same type can be added. + //! Only one object of the same type can be added or created. //! Returns false if an object of this type was already added. template bool Add(MetadataT&& data); //! Adds a new settings object to the metadata collection. - //! Only one object of the same type can be added. + //! Only one object of the same type can be added or created. //! Returns false if an object of this type was already added. template bool Add(const MetadataT& data); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.inl b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.inl index e1a540ff14..d7f6eb857d 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.inl +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializationMetadata.inl @@ -16,19 +16,31 @@ namespace AZ { - template - bool JsonSerializationMetadata::Add(MetadataT&& data) + template + bool JsonSerializationMetadata::Create(Args&&... args) { - auto typeId = azrtti_typeid(); - auto iter = m_data.find(typeId); - if (iter != m_data.end()) + const Uuid& typeId = azrtti_typeid(); + if (m_data.find(typeId) != m_data.end()) { - AZ_Warning("JsonSerializationMetadata", false, "Metadata object of type %s already added", - typeId.template ToString().c_str()); + AZ_Assert(false, "Metadata object of type %s already added", typeId.template ToString().c_str()); return false; } - m_data[typeId] = AZStd::any{ AZStd::forward(data) }; + m_data.emplace(typeId, MetadataT{AZStd::forward(args)...}); + return true; + } + + template + bool JsonSerializationMetadata::Add(MetadataT&& data) + { + const Uuid& typeId = azrtti_typeid(); + if (m_data.find(typeId) != m_data.end()) + { + AZ_Assert(false, "Metadata object of type %s already added", typeId.template ToString().c_str()); + return false; + } + + m_data.emplace(typeId, AZStd::forward(data)); return true; } @@ -41,7 +53,7 @@ namespace AZ template MetadataT* JsonSerializationMetadata::Find() { - const auto& typeId = azrtti_typeid(); + const Uuid& typeId = azrtti_typeid(); auto iter = m_data.find(typeId); return iter != m_data.end() ? AZStd::any_cast(&iter->second) : nullptr; } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 46f4c59455..392e95bf6e 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -576,14 +576,32 @@ namespace AZ::SettingsRegistryMergeUtils aznumeric_cast(projectPathKey.size()), projectPathKey.data()); } -#if !AZ_TRAIT_USE_ASSET_CACHE_FOLDER - // Setup the cache and user paths for Platforms where the Asset Cache Folder isn't used +#if !AZ_TRAIT_OS_IS_HOST_OS_PLATFORM + // Setup the cache and user paths when to platform specific locations when running on non-host platforms path = engineRoot; - registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native()); - registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native()); - registry.Set(FilePathKey_DevWriteStorage, path.LexicallyNormal().Native()); - registry.Set(FilePathKey_ProjectUserPath, (path / "user").LexicallyNormal().Native()); -#endif // AZ_TRAIT_USE_ASSET_CACHE_FOLDER + if (AZStd::optional nonHostCacheRoot = Utils::GetDefaultAppRootPath(); + nonHostCacheRoot) + { + registry.Set(FilePathKey_CacheProjectRootFolder, *nonHostCacheRoot); + registry.Set(FilePathKey_CacheRootFolder, *nonHostCacheRoot); + } + else + { + registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native()); + registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native()); + } + if (AZStd::optional devWriteStorage = Utils::GetDevWriteStoragePath(); + devWriteStorage) + { + registry.Set(FilePathKey_DevWriteStorage, *devWriteStorage); + registry.Set(FilePathKey_ProjectUserPath, *devWriteStorage); + } + else + { + registry.Set(FilePathKey_DevWriteStorage, path.LexicallyNormal().Native()); + registry.Set(FilePathKey_ProjectUserPath, (path / "user").LexicallyNormal().Native()); + } +#endif // AZ_TRAIT_OS_IS_HOST_OS_PLATFORM } void MergeSettingsToRegistry_TargetBuildDependencyRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform, @@ -986,4 +1004,12 @@ namespace AZ::SettingsRegistryMergeUtils return visitor.Finalize(); } + + bool IsPathAncestorDescendantOrEqual(AZStd::string_view candidatePath, AZStd::string_view inputPath) + { + AZ::IO::PathView candidateView{ candidatePath, AZ::IO::PosixPathSeparator }; + AZ::IO::PathView inputView{ inputPath, AZ::IO::PosixPathSeparator }; + return inputView.empty() || candidateView.IsRelativeTo(inputView) || inputView.IsRelativeTo(candidateView); + } + } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index dd7488d7f1..dad6c36d0f 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -256,4 +256,22 @@ namespace AZ::SettingsRegistryMergeUtils aznumeric_cast(keyName.size()), keyName.data()); return registry.Get(result, key); } + + //! Check if the supplied input path is an ancestor, a descendant or exactly equal to the candidate path + //! The can be used to check if a JSON pointer to a settings registry entry has potentially + //! "modified" the object at candidate path or its children in notifications + //! @param candidatePath Path which is being checked for the ancestor/descendant relationship + //! @param inputPath Path which is checked to determine if it is an ancestor or descendant of the candidate path + //! @return true if the input path is an ancestor, descendant or equal to the candidate path + //! Example: input path is ancestor path of candidate path + //! IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore") = true + //! Example: input path is equal to candidate path + //! IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore/Bootstrap") = true + //! Example: input path is descendant of candidate path + //! IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore/Bootstrap/project_path") = true + //! //! Example: input path is unrelated to candidate path + //! IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/Project/Settings/project_name") = false + //! //! Example: The path "" is the root JSON pointer therefore that is the ancestor of all paths + //! IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "") = true + bool IsPathAncestorDescendantOrEqual(AZStd::string_view candidatePath, AZStd::string_view inputPath); } diff --git a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp index e1a954bb51..592989ebda 100644 --- a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp @@ -2900,7 +2900,7 @@ namespace AZ { AZ::Data::AssetCatalogRequestBus::BroadcastResult(referencedSliceAssetPath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, slice.GetSliceAsset()->GetId()); } - AZ_Error("Slices", false, "Slice with asset ID %s and path %s has an invalid slice reference to slice with path %s. The Lumberyard editor may be unstable, it is recommended you re-launch the editor.", + AZ_Error("Slices", false, "Slice with asset ID %s and path %s has an invalid slice reference to slice with path %s. The Open 3D Engine editor may be unstable, it is recommended you re-launch the editor.", !m_myAsset ? "invalid asset" : m_myAsset->GetId().ToString().c_str(), mySliceAssetPath.empty() ? "invalid path" : mySliceAssetPath.c_str(), referencedSliceAssetPath.empty() ? "invalid path" : referencedSliceAssetPath.c_str()); diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h index 7dc4b79090..29d9b9328a 100644 --- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h +++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h @@ -769,8 +769,8 @@ namespace AZ *! This has similar behavior to Python pathlib '/' operator and os.path.join *! Specifically, that it uses the last absolute path as the anchor for the resulting path *! https://docs.python.org/3/library/pathlib.html#pathlib.PurePath - *! This means that joining StringFunc::Path::Join("C:\\lumberyard" "F:\\lumberyard") results in "F:\\lumberyard" - *! not "C:\\lumberyard\\F:\\lumberyard" + *! This means that joining StringFunc::Path::Join("C:\\O3DE" "F:\\O3DE") results in "F:\\O3DE" + *! not "C:\\O3DE\\F:\\O3DE" *! EX: StringFunc::Path::Join("C:\\p4\\game","info\\some.file", a) == true; a== "C:\\p4\\game\\info\\some.file" *! EX: StringFunc::Path::Join("C:\\p4\\game\\info", "game\\info\\some.file", a) == true; a== "C:\\p4\\game\\info\\game\\info\\some.file" *! EX: StringFunc::Path::Join("C:\\p4\\game\\info", "\\game\\info\\some.file", a) == true; a== "C:\\game\\info\\some.file" diff --git a/Code/Framework/AzCore/AzCore/UnitTest/UnitTest.h b/Code/Framework/AzCore/AzCore/UnitTest/UnitTest.h index c00ba2dd55..49e116ee81 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/UnitTest.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/UnitTest.h @@ -278,7 +278,7 @@ namespace UnitTest #define AZ_TEST_STATIC_ASSERT(_Exp) static_assert(_Exp, "Test Static Assert") #ifdef AZ_ENABLE_TRACING /* - * The AZ_TEST_START_ASSERTTEST and AZ_TEST_STOP_ASSERTTEST macros have been deprecated and will be removed in a future Lumberyard release. + * The AZ_TEST_START_ASSERTTEST and AZ_TEST_STOP_ASSERTTEST macros have been deprecated and will be removed in a future Open 3D Engine release. * The AZ_TEST_START_TRACE_SUPPRESSION and AZ_TEST_STOP_TRACE_SUPPRESSION is the recommend macros * The reason for the deprecation is that the AZ_TEST_(START|STOP)_ASSERTTEST implies that they should be used to for writing assert unit test * where the asserts themselves are expected to cause the test process to terminate. diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h index eb2bf18b8e..ce7d0fd9e4 100644 --- a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h +++ b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h @@ -105,7 +105,6 @@ #define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE static_cast(sysconf(_SC_NPROCESSORS_ONLN)); #define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 0 #define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 1 -#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 0 #define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 0 #define AZ_TRAIT_USE_POSIX_STRERROR_R 1 #define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 0 diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/IO/SystemFile_Android.cpp b/Code/Framework/AzCore/Platform/Android/AzCore/IO/SystemFile_Android.cpp index 80cdf8fa7e..2b1ebf54aa 100644 --- a/Code/Framework/AzCore/Platform/Android/AzCore/IO/SystemFile_Android.cpp +++ b/Code/Framework/AzCore/Platform/Android/AzCore/IO/SystemFile_Android.cpp @@ -193,7 +193,7 @@ namespace Platform::Internal void FindFilesInApk(const char* filter, const SystemFile::FindFileCB& cb) { // Separate the directory from the filename portion of the filter - AZ::IO::PathView filterPath(AZ::Android::Utils::StripApkPrefix(filter)); + AZ::IO::FixedMaxPath filterPath(AZ::Android::Utils::StripApkPrefix(filter)); AZ::IO::FixedMaxPathString filterDir{ filterPath.ParentPath().Native() }; AZStd::string_view fileFilter{ filterPath.Filename().Native() }; diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h index 976efed60d..2f213dcfd1 100644 --- a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h +++ b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h @@ -105,7 +105,6 @@ #define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE static_cast(sysconf(_SC_NPROCESSORS_ONLN)); #define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 0 #define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 0 -#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 1 #define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 1 #define AZ_TRAIT_USE_POSIX_STRERROR_R 1 #define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 0 diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h index e7475451bd..d03ab12ebf 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h @@ -105,7 +105,6 @@ #define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE static_cast(sysconf(_SC_NPROCESSORS_ONLN)); #define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 0 #define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 0 -#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 1 #define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 1 #define AZ_TRAIT_USE_POSIX_STRERROR_R 1 #define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 0 diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h index 144d6ee890..52872e3d43 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h @@ -105,7 +105,6 @@ #define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE INVALID_RETURN_VALUE #define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 1 #define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 0 -#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 1 #define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 0 #define AZ_TRAIT_USE_POSIX_STRERROR_R 0 #define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 1 diff --git a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h index 1cbe1f5e98..210841932c 100644 --- a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h +++ b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h @@ -106,7 +106,6 @@ #define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE static_cast(sysconf(_SC_NPROCESSORS_ONLN)); #define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 0 #define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 0 -#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 0 #define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 1 #define AZ_TRAIT_USE_POSIX_STRERROR_R 1 #define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 0 diff --git a/Code/Framework/AzCore/Tests/AZStd/Optional.cpp b/Code/Framework/AzCore/Tests/AZStd/Optional.cpp index 260c1151db..817fc9a61e 100644 --- a/Code/Framework/AzCore/Tests/AZStd/Optional.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/Optional.cpp @@ -90,7 +90,7 @@ namespace UnitTest TEST_F(OptionalFixture, ConstructorInPlaceWithInitializerList) { - const optional opt(in_place, {"Lumberyard"}, 4); + const optional opt(in_place, {"O3DE"}, 4); EXPECT_TRUE(bool(opt)) << "optional constructed with args should be true"; } diff --git a/Code/Framework/AzCore/Tests/Components.cpp b/Code/Framework/AzCore/Tests/Components.cpp index 3f4a9464a9..7801f69375 100644 --- a/Code/Framework/AzCore/Tests/Components.cpp +++ b/Code/Framework/AzCore/Tests/Components.cpp @@ -1081,13 +1081,11 @@ namespace UnitTest AZStd::string filePath; if (providerId == UserSettings::CT_GLOBAL) { - filePath.append(static_cast(m_exeDirectory)); - filePath.append("GlobalUserSettings.xml"); + filePath = (m_exeDirectory / "GlobalUserSettings.xml").String(); } else if (providerId == UserSettings::CT_LOCAL) { - filePath.append(static_cast(m_exeDirectory)); - filePath.append("LocalUserSettings.xml"); + filePath = (m_exeDirectory / "LocalUserSettings.xml").String(); } return filePath; } diff --git a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp index e7aa61a9ef..c85a78cf9b 100644 --- a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp +++ b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp @@ -547,7 +547,7 @@ namespace UnitTest PathLexicallyNormalParams{ '/', "foo/./bar/..", "foo" }, PathLexicallyNormalParams{ '/', "foo/.///bar/../", "foo" }, PathLexicallyNormalParams{ '/', R"(/foo\./bar\..\)", "/foo" }, - PathLexicallyNormalParams{ '\\', R"(C:/lumberyard/dev/Cache\game/../pc)", R"(C:\lumberyard\dev\Cache\pc)" } + PathLexicallyNormalParams{ '\\', R"(C:/O3DE/dev/Cache\game/../pc)", R"(C:\O3DE\dev\Cache\pc)" } ) ); @@ -756,13 +756,13 @@ namespace UnitTest PathPrefixParams{ "C:\\foo\\", "C:\\foo", true }, PathPrefixParams{ "C:", "C:\\foo", true }, PathPrefixParams{ "D:\\", "C:\\foo", false }, - PathPrefixParams{ "/lumberyard/dev/", "/lumberyard/dev", true }, - PathPrefixParams{ "/lumberyard/dev", "/lumberyard/dev/", true }, - PathPrefixParams{ "/lumberyard/dev/", "/lumberyard/dev/Cache", true }, - PathPrefixParams{ "/lumberyard/dev", "/lumberyard/dev/Cache", true }, - PathPrefixParams{ "/lumberyard/dev", "/lumberyard/dev/Cache/", true }, - PathPrefixParams{ "lumberyard/dev/", "lumberyard/dev/Cache/", true }, - PathPrefixParams{ "lumberyard\\dev/Assets", "lumberyard/dev/Cache/", false } + PathPrefixParams{ "/O3DE/dev/", "/O3DE/dev", true }, + PathPrefixParams{ "/O3DE/dev", "/O3DE/dev/", true }, + PathPrefixParams{ "/O3DE/dev/", "/O3DE/dev/Cache", true }, + PathPrefixParams{ "/O3DE/dev", "/O3DE/dev/Cache", true }, + PathPrefixParams{ "/O3DE/dev", "/O3DE/dev/Cache/", true }, + PathPrefixParams{ "O3DE/dev/", "O3DE/dev/Cache/", true }, + PathPrefixParams{ "O3DE\\dev/Assets", "O3DE/dev/Cache/", false } )); struct PathDecompositionParams @@ -854,7 +854,7 @@ namespace Benchmark } protected: AZStd::fixed_vector m_appendPaths{ "foo", "bar", "baz", "bazzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - "boo/bar/base", "C:\\path\\to\\lumberyard", "C", "\\\\", "/", R"(test\\path/with\mixed\separators)" }; + "boo/bar/base", "C:\\path\\to\\O3DE", "C", "\\\\", "/", R"(test\\path/with\mixed\separators)" }; }; BENCHMARK_F(PathBenchmarkFixture, BM_PathAppendFixedPath)(benchmark::State& state) diff --git a/Code/Framework/AzCore/Tests/Math/ObbTests.cpp b/Code/Framework/AzCore/Tests/Math/ObbTests.cpp index f837bd677b..a90d66f288 100644 --- a/Code/Framework/AzCore/Tests/Math/ObbTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/ObbTests.cpp @@ -56,6 +56,16 @@ namespace UnitTest EXPECT_THAT(obb.GetAxisZ(), IsClose(Vector3(1.0f, 0.0f, 0.0f))); } + TEST(MATH_Obb, TestScaleTransform) + { + Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths); + Vector3 scaleFactors = Vector3(1.0f, 2.0f, 3.0f); + Transform transform = Transform::CreateScale(scaleFactors); + obb = transform * obb; + EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(1.0f, 4.0f, 9.0f))); + EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(0.5f, 1.0f, 1.5f))); + } + TEST(MATH_Obb, TestSetPosition) { Obb obb; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializationMetadataTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializationMetadataTests.cpp index 1546681bd8..8b2f39b214 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializationMetadataTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializationMetadataTests.cpp @@ -93,8 +93,10 @@ namespace JsonSerializationTests TEST_F(JsonSerializationMetadataTests, Add_MoveDuplicateValue_ReturnsFalse) { + AZ_TEST_START_TRACE_SUPPRESSION; m_metadata->Add(TestSettingsA{ 42 }); EXPECT_FALSE(m_metadata->Add(TestSettingsA{ 88 })); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); } TEST_F(JsonSerializationMetadataTests, Add_CopyNewValue_ReturnsTrue) @@ -119,11 +121,13 @@ namespace JsonSerializationTests TEST_F(JsonSerializationMetadataTests, Find_MultipleValues_ReturnsFirstValue) { - m_metadata->Add(TestSettingsA{ 42 }); + AZ_TEST_START_TRACE_SUPPRESSION; + m_metadata->Add(TestSettingsA{42}); m_metadata->Add(TestSettingsA{ 88 }); TestSettingsA* value = m_metadata->Find(); ASSERT_NE(nullptr, value); EXPECT_EQ(42, value->m_number); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); } TEST_F(JsonSerializationMetadataTests, FindConst_PreviouslyAddedValue_ReturnsConstPointer) diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp b/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp index 37ea9f1bc1..36b9757ce3 100644 --- a/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp +++ b/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp @@ -542,4 +542,14 @@ tags=tools,renderer,metal)" EXPECT_STREQ("Foo", commandLine.GetMiscValue(1).c_str()); EXPECT_STREQ("Bat", commandLine.GetMiscValue(2).c_str()); } + + using SettingsRegistryAncestorDescendantOrEqualPathFixture = SettingsRegistryMergeUtilsCommandLineFixture; + + TEST_F(SettingsRegistryAncestorDescendantOrEqualPathFixture, ValidateThatAncestorOrDescendantOrPathWithTheSameValue_Succeeds) + { + EXPECT_TRUE(AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore")); + EXPECT_TRUE(AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore/Bootstrap")); + EXPECT_TRUE(AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/AzCore/Bootstrap/project_path")); + EXPECT_FALSE(AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual("/Amazon/AzCore/Bootstrap", "/Amazon/Project/Settings/project_name")); + } } diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index ff9e0ce6c5..4b75a3d1cf 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -82,9 +82,6 @@ static const char* s_azFrameworkWarningWindow = "AzFramework"; -static const char* s_engineConfigFileName = "engine.json"; -static const char* s_engineConfigEngineVersionKey = "LumberyardVersion"; - namespace AzFramework { namespace ApplicationInternal @@ -264,24 +261,8 @@ namespace AzFramework void Application::PreModuleLoad() { - // Calculate the engine root by reading the engine.json file - AZStd::string engineJsonPath = AZStd::string_view{ m_engineRoot }; - engineJsonPath += s_engineConfigFileName; - AzFramework::StringFunc::Path::Normalize(engineJsonPath); - AZ::IO::LocalFileIO localFileIO; - auto readJsonResult = AzFramework::FileFunc::ReadJsonFile(engineJsonPath, &localFileIO); - - if (readJsonResult.IsSuccess()) - { - SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str()); - AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str()); - } - else - { - // If there is any problem reading the engine.json file, then default to engine root to the app root - AZ_Warning(s_azFrameworkWarningWindow, false, "Unable to read engine.json file '%s' (%s). Defaulting the engine root to '%s'", engineJsonPath.c_str(), readJsonResult.GetError().c_str(), m_appRoot.c_str()); - SetRootPath(RootPathType::EngineRoot, m_appRoot.c_str()); - } + SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str()); + AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str()); } @@ -504,13 +485,13 @@ namespace AzFramework void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const { - AZStd::string fullPath = AZStd::string(m_engineRoot) + AZStd::string(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING) + engineRelativePath; - engineRelativePath = fullPath; + AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath; + engineRelativePath = fullPath.String(); } void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const { - AzFramework::StringFunc::AssetPath::CalculateBranchToken(AZStd::string(m_engineRoot), token); + AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token); } //////////////////////////////////////////////////////////////////////////// @@ -648,37 +629,21 @@ namespace AzFramework void Application::SetRootPath(RootPathType type, const char* source) { - size_t sourceLen = strlen(source); - - constexpr AZStd::string_view pathSeparators{ AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR }; - // Determine if we need to append a trailing path separator - bool appendTrailingPathSep = sourceLen > 0 && pathSeparators.find_first_of(source[sourceLen - 1]) == AZStd::string_view::npos; + const size_t sourceLen = strlen(source); // Copy the source path to the intended root path and correct the path separators as well switch (type) { case RootPathType::AppRoot: { - AZ_Assert(sourceLen < m_appRoot.max_size(), "String overflow for App Root: %s", source); - m_appRoot = source; - - AZStd::replace(std::begin(m_appRoot), std::end(m_appRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (appendTrailingPathSep) - { - m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR); - } + AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source); + m_appRoot = AZ::IO::PathView(source).LexicallyNormal(); } break; case RootPathType::EngineRoot: { - AZ_Assert(sourceLen < m_engineRoot.max_size(), "String overflow for Engine Root: %s", source); - m_engineRoot = source; - - AZStd::replace(std::begin(m_engineRoot), std::end(m_engineRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (appendTrailingPathSep) - { - m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR); - } + AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source); + m_engineRoot = AZ::IO::PathView(source).LexicallyNormal(); } break; default: diff --git a/Code/Framework/AzFramework/AzFramework/Archive/MissingFileReport.cpp b/Code/Framework/AzFramework/AzFramework/Archive/MissingFileReport.cpp index f57a4cafa6..91f945c31e 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/MissingFileReport.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/MissingFileReport.cpp @@ -28,7 +28,7 @@ namespace AZ::IO::Internal static bool IsIgnored(const char* szPath); // Do not report missing LOD files if no CGF files depend on them - // Do not report missing .cgfm files since they're not actually created and used in Lumberyard + // Do not report missing .cgfm files since they're not actually created and used in Open 3D Engine // This checking prevents our missing dependency scanner from having a lot of false positives on these files static bool IgnoreCGFDependencies(const char* szPath); diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetBundleManifest.h b/Code/Framework/AzFramework/AzFramework/Asset/AssetBundleManifest.h index d80974382b..0c2ef28ac1 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetBundleManifest.h +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetBundleManifest.h @@ -21,7 +21,7 @@ namespace AZ namespace AzFramework { - // Class to describe metadata about an AssetBundle in Lumberyard + // Class to describe metadata about an AssetBundle in Open 3D Engine class AssetBundleManifest { public: diff --git a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp index bf60241419..860f1e3b4a 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp @@ -597,9 +597,9 @@ namespace AZ { // here we are making sure that the buffer being passed in has enough space to include the alias in it. // we are trying to find the LONGEST match, meaning of the following two examples, the second should 'win' - // File: g:/lumberyard/dev/files/morefiles/blah.xml - // Alias1 links to 'g:/lumberyard/dev/' - // Alias2 links to 'g:/lumberyard/dev/files/morefiles' + // File: g:/O3DE/dev/files/morefiles/blah.xml + // Alias1 links to 'g:/O3DE/dev/' + // Alias2 links to 'g:/O3DE/dev/files/morefiles' // so returning Alias2 is preferred as it is more specific, even though alias1 includes it. // note that its not possible for this to be matched if the string is shorter than the length of the alias itself so we skip // strings that are shorter than the alias's mapped path without checking. diff --git a/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp b/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp index 4117c72572..b16d142365 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp @@ -126,19 +126,22 @@ namespace AzFramework return; } } - else if constexpr (AZStd::is_same_v) + else { - FlushCache(args.m_path); + if constexpr (AZStd::is_same_v) + { + FlushCache(args.m_path); + } + else if constexpr (AZStd::is_same_v) + { + FlushEntireCache(); + } + else if constexpr (AZStd::is_same_v) + { + Report(args); + } + StreamStackEntry::QueueRequest(request); } - else if constexpr (AZStd::is_same_v) - { - FlushEntireCache(); - } - else if constexpr (AZStd::is_same_v) - { - Report(args); - } - StreamStackEntry::QueueRequest(request); }, request->GetCommand()); } diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Material.h b/Code/Framework/AzFramework/AzFramework/Physics/Material.h index 72be2805f9..e9eaae929f 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Material.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Material.h @@ -168,7 +168,7 @@ namespace Physics MaterialId m_id; }; - /// An asset that holds a list of materials to be edited and assigned in Lumberyard Editor + /// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor /// ====================================================================================== /// /// Use Asset Editor to create a MaterialLibraryAsset and add materials to it.\n diff --git a/Code/Framework/AzFramework/AzFramework/Physics/RigidBody.h b/Code/Framework/AzFramework/AzFramework/Physics/RigidBody.h new file mode 100644 index 0000000000..04d9799c8b --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Physics/RigidBody.h @@ -0,0 +1,238 @@ +/* +* 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 + +#include +#include + +namespace +{ + class ReflectContext; +} + +namespace Physics +{ + class ShapeConfiguration; + class World; + class Shape; + + /// Default values used for initializing RigidBodySettings. + /// These can be modified by Physics Implementation gems. // O3DE_DEPRECATED(LY-114472) - DefaultRigidBodyConfiguration values are not shared across modules. + // Use RigidBodyConfiguration default values. + struct DefaultRigidBodyConfiguration + { + static float m_mass; + static bool m_computeInertiaTensor; + static float m_linearDamping; + static float m_angularDamping; + static float m_sleepMinEnergy; + static float m_maxAngularVelocity; + }; + + enum class MassComputeFlags : AZ::u8 + { + NONE = 0, + + //! Flags indicating whether a certain mass property should be auto-computed or not. + COMPUTE_MASS = 1, + COMPUTE_INERTIA = 1 << 1, + COMPUTE_COM = 1 << 2, + + //! If set, non-simulated shapes will also be included in the mass properties calculation. + INCLUDE_ALL_SHAPES = 1 << 3, + + DEFAULT = COMPUTE_COM | COMPUTE_INERTIA | COMPUTE_MASS + }; + + class RigidBodyConfiguration + : public WorldBodyConfiguration + { + public: + AZ_CLASS_ALLOCATOR(RigidBodyConfiguration, AZ::SystemAllocator, 0); + AZ_RTTI(RigidBodyConfiguration, "{ACFA8900-8530-4744-AF00-AA533C868A8E}", WorldBodyConfiguration); + static void Reflect(AZ::ReflectContext* context); + + enum PropertyVisibility : AZ::u16 + { + InitialVelocities = 1 << 0, ///< Whether the initial linear and angular velocities are visible. + InertiaProperties = 1 << 1, ///< Whether the whole category of inertia properties (mass, compute inertia, + ///< inertia tensor etc) is visible. + Damping = 1 << 2, ///< Whether linear and angular damping are visible. + SleepOptions = 1 << 3, ///< Whether the sleep threshold and start asleep options are visible. + Interpolation = 1 << 4, ///< Whether the interpolation option is visible. + Gravity = 1 << 5, ///< Whether the effected by gravity option is visible. + Kinematic = 1 << 6, ///< Whether the option to make the body kinematic is visible. + ContinuousCollisionDetection = 1 << 7, ///< Whether the option to enable continuous collision detection is visible. + MaxVelocities = 1 << 8 ///< Whether upper limits on velocities are visible. + }; + + RigidBodyConfiguration() = default; + RigidBodyConfiguration(const RigidBodyConfiguration& settings) = default; + + // Visibility functions. + AZ::Crc32 GetPropertyVisibility(PropertyVisibility property) const; + void SetPropertyVisibility(PropertyVisibility property, bool isVisible); + + AZ::Crc32 GetInitialVelocitiesVisibility() const; + /// Returns whether the whole category of inertia settings (mass, inertia, center of mass offset etc) is visible. + AZ::Crc32 GetInertiaSettingsVisibility() const; + /// Returns whether the individual inertia tensor field is visible or is hidden because the compute inertia option is selected. + AZ::Crc32 GetInertiaVisibility() const; + /// Returns whether the mass field is visible or is hidden because compute mass option is selected. + AZ::Crc32 GetMassVisibility() const; + /// Returns whether the individual centre of mass offset field is visible or is hidden because compute CoM option is selected. + AZ::Crc32 GetCoMVisibility() const; + AZ::Crc32 GetDampingVisibility() const; + AZ::Crc32 GetSleepOptionsVisibility() const; + AZ::Crc32 GetInterpolationVisibility() const; + AZ::Crc32 GetGravityVisibility() const; + AZ::Crc32 GetKinematicVisibility() const; + AZ::Crc32 GetCCDVisibility() const; + AZ::Crc32 GetMaxVelocitiesVisibility() const; + MassComputeFlags GetMassComputeFlags() const; + void SetMassComputeFlags(MassComputeFlags flags); + + bool IsCCDEnabled() const; + + // Basic initial settings. + AZ::Vector3 m_initialLinearVelocity = AZ::Vector3::CreateZero(); + AZ::Vector3 m_initialAngularVelocity = AZ::Vector3::CreateZero(); + AZ::Vector3 m_centerOfMassOffset = AZ::Vector3::CreateZero(); + + // Simulation parameters. + float m_mass = DefaultRigidBodyConfiguration::m_mass; + AZ::Matrix3x3 m_inertiaTensor = AZ::Matrix3x3::CreateIdentity(); + float m_linearDamping = DefaultRigidBodyConfiguration::m_linearDamping; + float m_angularDamping = DefaultRigidBodyConfiguration::m_angularDamping; + float m_sleepMinEnergy = DefaultRigidBodyConfiguration::m_sleepMinEnergy; + float m_maxAngularVelocity = DefaultRigidBodyConfiguration::m_maxAngularVelocity; + + // Visibility settings. + AZ::u16 m_propertyVisibilityFlags = (std::numeric_limits::max)(); + + bool m_startAsleep = false; + bool m_interpolateMotion = false; + bool m_gravityEnabled = true; + bool m_simulated = true; + bool m_kinematic = false; + bool m_ccdEnabled = false; ///< Whether continuous collision detection is enabled. + float m_ccdMinAdvanceCoefficient = 0.15f; ///< Coefficient affecting how granularly time is subdivided in CCD. + bool m_ccdFrictionEnabled = false; ///< Whether friction is applied when resolving CCD collisions. + + bool m_computeCenterOfMass = true; + bool m_computeInertiaTensor = true; + bool m_computeMass = true; + + //! If set, non-simulated shapes will also be included in the mass properties calculation. + bool m_includeAllShapesInMassCalculation = false; + }; + + /// Dynamic rigid body. + class RigidBody + : public WorldBody + { + public: + + AZ_CLASS_ALLOCATOR(RigidBody, AZ::SystemAllocator, 0); + AZ_RTTI(RigidBody, "{156E459F-7BB7-4B4E-ADA0-2130D96B7E80}", WorldBody); + + public: + RigidBody() = default; + explicit RigidBody(const RigidBodyConfiguration& settings); + + + virtual void AddShape(AZStd::shared_ptr shape) = 0; + virtual void RemoveShape(AZStd::shared_ptr shape) = 0; + virtual AZ::u32 GetShapeCount() { return 0; } + virtual AZStd::shared_ptr GetShape(AZ::u32 /*index*/) { return nullptr; } + + virtual AZ::Vector3 GetCenterOfMassWorld() const = 0; + virtual AZ::Vector3 GetCenterOfMassLocal() const = 0; + + virtual AZ::Matrix3x3 GetInverseInertiaWorld() const = 0; + virtual AZ::Matrix3x3 GetInverseInertiaLocal() const = 0; + + virtual float GetMass() const = 0; + virtual float GetInverseMass() const = 0; + virtual void SetMass(float mass) = 0; + virtual void SetCenterOfMassOffset(const AZ::Vector3& comOffset) = 0; + + /// Retrieves the velocity at center of mass; only linear velocity, no rotational velocity contribution. + virtual AZ::Vector3 GetLinearVelocity() const = 0; + virtual void SetLinearVelocity(const AZ::Vector3& velocity) = 0; + virtual AZ::Vector3 GetAngularVelocity() const = 0; + virtual void SetAngularVelocity(const AZ::Vector3& angularVelocity) = 0; + virtual AZ::Vector3 GetLinearVelocityAtWorldPoint(const AZ::Vector3& worldPoint) = 0; + virtual void ApplyLinearImpulse(const AZ::Vector3& impulse) = 0; + virtual void ApplyLinearImpulseAtWorldPoint(const AZ::Vector3& impulse, const AZ::Vector3& worldPoint) = 0; + virtual void ApplyAngularImpulse(const AZ::Vector3& angularImpulse) = 0; + + virtual float GetLinearDamping() const = 0; + virtual void SetLinearDamping(float damping) = 0; + virtual float GetAngularDamping() const = 0; + virtual void SetAngularDamping(float damping) = 0; + + virtual bool IsAwake() const = 0; + virtual void ForceAsleep() = 0; + virtual void ForceAwake() = 0; + virtual float GetSleepThreshold() const = 0; + virtual void SetSleepThreshold(float threshold) = 0; + + virtual bool IsKinematic() const = 0; + virtual void SetKinematic(bool kinematic) = 0; + virtual void SetKinematicTarget(const AZ::Transform& targetPosition) = 0; + + virtual bool IsGravityEnabled() const = 0; + virtual void SetGravityEnabled(bool enabled) = 0; + virtual void SetSimulationEnabled(bool enabled) = 0; + virtual void SetCCDEnabled(bool enabled) = 0; + + //! Recalculates mass, inertia and center of mass based on the flags passed. + //! @param flags MassComputeFlags specifying which properties should be recomputed. + //! @param centerOfMassOffsetOverride Optional override of the center of mass. Note: This parameter will be ignored if COMPUTE_COM is passed in flags. + //! @param inertiaTensorOverride Optional override of the inertia. Note: This parameter will be ignored if COMPUTE_INERTIA is passed in flags. + //! @param massOverride Optional override of the mass. Note: This parameter will be ignored if COMPUTE_MASS is passed in flags. + virtual void UpdateMassProperties(MassComputeFlags flags = MassComputeFlags::DEFAULT, + const AZ::Vector3* centerOfMassOffsetOverride = nullptr, + const AZ::Matrix3x3* inertiaTensorOverride = nullptr, + const float* massOverride = nullptr) = 0; + }; + + /// Bitwise operators for MassComputeFlags + inline MassComputeFlags operator|(MassComputeFlags lhs, MassComputeFlags rhs) + { + return aznumeric_cast(aznumeric_cast(lhs) | aznumeric_cast(rhs)); + } + + inline MassComputeFlags operator&(MassComputeFlags lhs, MassComputeFlags rhs) + { + return aznumeric_cast(aznumeric_cast(lhs) & aznumeric_cast(rhs)); + } + + /// Static rigid body. + class RigidBodyStatic + : public WorldBody + { + public: + AZ_CLASS_ALLOCATOR(RigidBodyStatic, AZ::SystemAllocator, 0); + AZ_RTTI(RigidBodyStatic, "{13A677BB-7085-4EDB-BCC8-306548238692}", WorldBody); + + virtual void AddShape(const AZStd::shared_ptr& shape) = 0; + virtual AZ::u32 GetShapeCount() { return 0; } + virtual AZStd::shared_ptr GetShape(AZ::u32 /*index*/) { return nullptr; } + }; +} // namespace Physics diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityBoundsUnionSystem.cpp b/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityBoundsUnionSystem.cpp index 7623c772c5..e9b0d4609e 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityBoundsUnionSystem.cpp +++ b/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityBoundsUnionSystem.cpp @@ -84,7 +84,7 @@ namespace AzFramework { if (IVisibilitySystem* visibilitySystem = AZ::Interface::Get()) { - visibilitySystem->RemoveEntry(instance_it->second.m_visibilityEntry); + visibilitySystem->GetDefaultVisibilityScene()->RemoveEntry(instance_it->second.m_visibilityEntry); m_entityVisibilityBoundsUnionInstanceMapping.erase(instance_it); } } @@ -104,7 +104,7 @@ namespace AzFramework if (visibilitySystem && !worldEntityBoundsUnion.IsClose(instance.m_visibilityEntry.m_boundingVolume)) { instance.m_visibilityEntry.m_boundingVolume = worldEntityBoundsUnion; - visibilitySystem->InsertOrUpdateEntry(instance.m_visibilityEntry); + visibilitySystem->GetDefaultVisibilityScene()->InsertOrUpdateEntry(instance.m_visibilityEntry); } } } diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityQuery.cpp b/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityQuery.cpp index 8a2e48535f..fd119c8199 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityQuery.cpp +++ b/Code/Framework/AzFramework/AzFramework/Visibility/EntityVisibilityQuery.cpp @@ -56,10 +56,10 @@ namespace AzFramework m_octreeDebug.Clear(); m_visibleEntityIds.clear(); - visSystem->Enumerate( + visSystem->GetDefaultVisibilityScene()->Enumerate( viewFrustum, [&viewFrustum, &visibleEntityIdsOut = m_visibleEntityIds, - &octreeDebug = m_octreeDebug](const AzFramework::IVisibilitySystem::NodeData& nodeData) + &octreeDebug = m_octreeDebug](const AzFramework::IVisibilityScene::NodeData& nodeData) { if (ed_visibility_showDebug) { diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/IVisibilitySystem.h b/Code/Framework/AzFramework/AzFramework/Visibility/IVisibilitySystem.h index 46fef2ab5a..e7dc783a30 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/IVisibilitySystem.h +++ b/Code/Framework/AzFramework/AzFramework/Visibility/IVisibilitySystem.h @@ -13,11 +13,13 @@ #pragma once #include +#include #include #include #include #include #include +#include #include #include @@ -45,12 +47,15 @@ namespace AzFramework TypeFlags m_typeFlags = TYPE_None; }; - //! @class IVisibilitySystem - //! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries. - class IVisibilitySystem + //! @class IVisibilityScene + //! @brief This is the interface for managing objects and visibility queries for a given scene. + class IVisibilityScene { public: - AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}"); + AZ_RTTI(IVisibilityScene, "{822BC414-3CE3-40B4-A9A2-A42EA5B9499F}"); + + IVisibilityScene() = default; + virtual ~IVisibilityScene() = default; struct NodeData { @@ -59,8 +64,8 @@ namespace AzFramework }; using EnumerateCallback = AZStd::function; - IVisibilitySystem() = default; - virtual ~IVisibilitySystem() = default; + //! Get the unique scene name, used to look up the scene in the IVisibilitySystem. Duplicate names will assert on creation. + virtual const AZ::Name& GetName() const = 0; //! Insert or update an entry within the visibility system. //! This encompasses the following three scenarios: @@ -68,11 +73,11 @@ namespace AzFramework // 2. A previously added entry moves to a new position within its current node in the spatial hash. // 3. A previously added entry moves to a new node in the spatial hash. // (causing it to be removed from its original node and added to its new node) - //! @param visibilityEntry data for the object being added to the visibility system + //! @param visibilityEntry data for the object being added/updated virtual void InsertOrUpdateEntry(VisibilityEntry& visibilityEntry) = 0; //! Removes an entry from the visibility system. - //! @param visibilityEntry data for the object being added to the visibility system + //! @param visibilityEntry data for the object being removed virtual void RemoveEntry(VisibilityEntry& visibilityEntry) = 0; //! Intersects an axis aligned bounding box against the visibility system. @@ -99,6 +104,34 @@ namespace AzFramework //! Return the number of VisibilityEntries that have been added to the system virtual uint32_t GetEntryCount() const = 0; + }; + + //! @class IVisibilitySystem + //! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries. + class IVisibilitySystem + { + public: + AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}"); + + IVisibilitySystem() = default; + virtual ~IVisibilitySystem() = default; + + //! Return the default IVisibilityScene for entities. + virtual IVisibilityScene* GetDefaultVisibilityScene() = 0; + + //! Create a new IVisibilityScene that is uniquely identified by the scene name. + virtual IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) = 0; + + //! Destroy the visibility scene. + //! This does not destroy the entities that are a part of the scene, only the visibility scene. + //! This will set the visScene to nullptr + virtual void DestroyVisibilityScene(IVisibilityScene* visScene) = 0; + + //! Find the IVisibilityScene that is identified by sceneName. + virtual IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) = 0; + + //! Logs stats about the visibility system to the console. + virtual void DumpStats(const AZ::ConsoleCommandContainer& arguments) = 0; AZ_DISABLE_COPY_MOVE(IVisibilitySystem); }; diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp index 95c638c5cb..cdb7ce0dd9 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp @@ -15,7 +15,7 @@ namespace AzFramework { - AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the octreeSystemComponent will degenerate to a quadtree split along the X/Y plane"); + AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the visibility octrees will degenerate to a quadtree split along the X/Y plane"); AZ_CVAR(float, bg_octreeMaxWorldExtents, 16384.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum supported world size by the world octreeSystemComponent"); AZ_CVAR(uint32_t, bg_octreeNodeMaxEntries, 64, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of entries to allow in any node before forcing a split"); AZ_CVAR(uint32_t, bg_octreeNodeMinEntries, 32, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of entries to allow in a node resulting from a merge operation"); @@ -67,9 +67,9 @@ namespace AzFramework } - void OctreeNode::Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry) + void OctreeNode::Insert(OctreeScene& octreeScene, VisibilityEntry* entry) { - AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeSystemComponent"); + AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeScene"); // If this is not a leaf node, try to insert into the child nodes if (m_children != nullptr) @@ -80,7 +80,7 @@ namespace AzFramework { if (AZ::ShapeIntersection::Contains(m_children[child].m_bounds, boundingVolume)) { - return m_children[child].Insert(octreeSystemComponent, entry); + return m_children[child].Insert(octreeScene, entry); } } } @@ -90,8 +90,8 @@ namespace AzFramework if ((m_children == nullptr) && (m_entries.size() >= bg_octreeNodeMaxEntries)) { // If we're not already split, and our entry list gets too large, split this node - Split(octreeSystemComponent); - Insert(octreeSystemComponent, entry); + Split(octreeScene); + Insert(octreeScene, entry); } else { @@ -102,7 +102,7 @@ namespace AzFramework } - void OctreeNode::Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry) + void OctreeNode::Update(OctreeScene& octreeScene, VisibilityEntry* entry) { AZ_Assert(entry->m_internalNode == this, "Update invoked for an entry bound to a different OctreeNode"); @@ -116,7 +116,7 @@ namespace AzFramework } // Remove the entry from our current node, since it is no longer contained - Remove(octreeSystemComponent, entry); + Remove(octreeScene, entry); // Traverse up our ancestor nodes to find the first node that fully contains the entry // This strategy assumes an entry will typically move a small distance relative to the total world @@ -125,14 +125,14 @@ namespace AzFramework { if (AZ::ShapeIntersection::Contains(insertCheck->m_bounds, boundingVolume)) { - return insertCheck->Insert(octreeSystemComponent, entry); + return insertCheck->Insert(octreeScene, entry); } insertCheck = insertCheck->m_parent; } } - void OctreeNode::Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry) + void OctreeNode::Remove(OctreeScene& octreeScene, VisibilityEntry* entry) { AZ_Assert(entry->m_internalNode == this, "Remove invoked for an entry bound to a different OctreeNode"); AZ_Assert(m_entries[entry->m_internalNodeIndex] == entry, "Visibility entry data is corrupt"); @@ -150,29 +150,30 @@ namespace AzFramework if (m_parent != nullptr) { - m_parent->TryMerge(octreeSystemComponent); + m_parent->TryMerge(octreeScene); } } - void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const { EnumerateHelper(aabb, callback); } - void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const { EnumerateHelper(sphere, callback); } - void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const { EnumerateHelper(frustum, callback); } - void OctreeNode::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const + + void OctreeNode::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const { // Invoke the callback for the current node if (!m_entries.empty()) @@ -191,6 +192,7 @@ namespace AzFramework } } + const AZStd::vector& OctreeNode::GetEntries() const { return m_entries; @@ -209,7 +211,7 @@ namespace AzFramework } - void OctreeNode::TryMerge(OctreeSystemComponent& octreeSystemComponent) + void OctreeNode::TryMerge(OctreeScene& octreeScene) { if (IsLeaf()) { @@ -222,7 +224,7 @@ namespace AzFramework const uint32_t childCount = GetChildNodeCount(); for (uint32_t child = 0; child < childCount; ++child) { - m_children[child].TryMerge(octreeSystemComponent); + m_children[child].TryMerge(octreeScene); if (!m_children[child].IsLeaf()) { return; @@ -232,13 +234,13 @@ namespace AzFramework if (potentialNodeCount <= bg_octreeNodeMinEntries) { - Merge(octreeSystemComponent); + Merge(octreeScene); } } template - void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const { AZ_Assert(AZ::ShapeIntersection::Overlaps(boundingVolume, m_bounds), "EnumerateHelper invoked on an octreeSystemComponent node that is not within the bounding volume"); @@ -263,11 +265,11 @@ namespace AzFramework } - void OctreeNode::Split(OctreeSystemComponent& octreeSystemComponent) + void OctreeNode::Split(OctreeScene& octreeScene) { - AZ_Assert(m_children == nullptr, "Split invoked on an octreeSystemComponent node that has already been split"); - m_childNodeIndex = octreeSystemComponent.AllocateChildNodes(); - m_children = octreeSystemComponent.GetChildNodesAtIndex(m_childNodeIndex); + AZ_Assert(m_children == nullptr, "Split invoked on an octreeScene node that has already been split"); + m_childNodeIndex = octreeScene.AllocateChildNodes(); + m_children = octreeScene.GetChildNodesAtIndex(m_childNodeIndex); // Set child split planes and bounding volumes { @@ -308,14 +310,14 @@ namespace AzFramework { entry->m_internalNode = nullptr; entry->m_internalNodeIndex = 0; - Insert(octreeSystemComponent, entry); + Insert(octreeScene, entry); } } - void OctreeNode::Merge(OctreeSystemComponent& octreeSystemComponent) + void OctreeNode::Merge(OctreeScene& octreeScene) { - AZ_Assert(m_children != nullptr, "Merge invoked on an octreeSystemComponent node that does not have children"); + AZ_Assert(m_children != nullptr, "Merge invoked on an octreeScene node that does not have children"); // Move all child entries to our own entry set const uint32_t childCount = GetChildNodeCount(); @@ -330,46 +332,20 @@ namespace AzFramework m_children[child].m_entries.clear(); } - octreeSystemComponent.ReleaseChildNodes(m_childNodeIndex); + octreeScene.ReleaseChildNodes(m_childNodeIndex); m_childNodeIndex = InvalidChildNodeIndex; m_children = nullptr; } - - void OctreeSystemComponent::Reflect(AZ::ReflectContext* context) + OctreeScene::OctreeScene(const AZ::Name& sceneName) + : m_sceneName(sceneName) + , m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents))) { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1); - } + AZ_Assert(!sceneName.IsEmpty(), "sceneName must be a valid string"); } - - void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + OctreeScene::~OctreeScene() { - provided.push_back(AZ_CRC_CE("VisibilityService")); - } - - - void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC_CE("VisibilityService")); - } - - - OctreeSystemComponent::OctreeSystemComponent() - : m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents))) - { - AZ::Interface::Register(this); - IVisibilitySystemRequestBus::Handler::BusConnect(); - } - - - OctreeSystemComponent::~OctreeSystemComponent() - { - IVisibilitySystemRequestBus::Handler::BusDisconnect(); - AZ::Interface::Unregister(this); for (auto page : m_nodeCache) { delete page; @@ -378,21 +354,14 @@ namespace AzFramework m_nodeCache.shrink_to_fit(); } - - void OctreeSystemComponent::Activate() + const AZ::Name& OctreeScene::GetName() const { - ; + return m_sceneName; } - - void OctreeSystemComponent::Deactivate() - { - ; - } - - - void OctreeSystemComponent::InsertOrUpdateEntry(VisibilityEntry& entry) + void OctreeScene::InsertOrUpdateEntry(VisibilityEntry& entry) { + AZStd::lock_guard lock(m_sharedMutex); if (entry.m_internalNode != nullptr) { static_cast(entry.m_internalNode)->Update(*this, &entry); @@ -405,8 +374,9 @@ namespace AzFramework } - void OctreeSystemComponent::RemoveEntry(VisibilityEntry& entry) + void OctreeScene::RemoveEntry(VisibilityEntry& entry) { + AZStd::lock_guard lock(m_sharedMutex); if (entry.m_internalNode) { static_cast(entry.m_internalNode)->Remove(*this, &entry); @@ -415,70 +385,71 @@ namespace AzFramework } - void OctreeSystemComponent::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeScene::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const { + AZStd::shared_lock lock(m_sharedMutex); m_root.Enumerate(aabb, callback); } - void OctreeSystemComponent::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeScene::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const { + AZStd::shared_lock lock(m_sharedMutex); m_root.Enumerate(sphere, callback); } - void OctreeSystemComponent::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const + void OctreeScene::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const { + AZStd::shared_lock lock(m_sharedMutex); m_root.Enumerate(frustum, callback); } - void OctreeSystemComponent::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const + + void OctreeScene::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const { + AZStd::shared_lock lock(m_sharedMutex); m_root.EnumerateNoCull(callback); } - uint32_t OctreeSystemComponent::GetEntryCount() const + + uint32_t OctreeScene::GetEntryCount() const { return m_entryCount; } - OctreeNode& OctreeSystemComponent::GetRoot() - { - return m_root; - } - - uint32_t OctreeSystemComponent::GetNodeCount() const + uint32_t OctreeScene::GetNodeCount() const { return m_nodeCount; } - uint32_t OctreeSystemComponent::GetFreeNodeCount() const + uint32_t OctreeScene::GetFreeNodeCount() const { // Each entry represents GetChildNodeCount() nodes return aznumeric_cast(m_freeOctreeNodes.size() * GetChildNodeCount()); } - uint32_t OctreeSystemComponent::GetPageCount() const + uint32_t OctreeScene::GetPageCount() const { return aznumeric_cast(m_nodeCache.size()); } - uint32_t OctreeSystemComponent::GetChildNodeCount() const + uint32_t OctreeScene::GetChildNodeCount() const { return AzFramework::GetChildNodeCount(); } - void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) + void OctreeScene::DumpStats() { - AZ_TracePrintf("Console", "OctreeNode::EntryCount = %u", GetEntryCount()); - AZ_TracePrintf("Console", "OctreeNode::NodeCount = %u", GetNodeCount()); - AZ_TracePrintf("Console", "OctreeNode::FreeNodeCount = %u", GetFreeNodeCount()); - AZ_TracePrintf("Console", "OctreeNode::PageCount = %u", GetPageCount()); - AZ_TracePrintf("Console", "OctreeNode::ChildNodeCount = %u", GetChildNodeCount()); + AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::EntryCount = %u", GetName().GetCStr(), GetEntryCount()); + AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::NodeCount = %u", GetName().GetCStr(), GetNodeCount()); + AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::FreeNodeCount = %u", GetName().GetCStr(), GetFreeNodeCount()); + AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::PageCount = %u", GetName().GetCStr(), GetPageCount()); + AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::ChildNodeCount = %u", GetName().GetCStr(), GetChildNodeCount()); } @@ -496,7 +467,7 @@ namespace AzFramework } - uint32_t OctreeSystemComponent::AllocateChildNodes() + uint32_t OctreeScene::AllocateChildNodes() { const uint32_t childCount = GetChildNodeCount(); m_nodeCount += childCount; @@ -540,18 +511,124 @@ namespace AzFramework } - void OctreeSystemComponent::ReleaseChildNodes(uint32_t nodeIndex) + void OctreeScene::ReleaseChildNodes(uint32_t nodeIndex) { m_nodeCount -= GetChildNodeCount(); m_freeOctreeNodes.push(nodeIndex); } - OctreeNode* OctreeSystemComponent::GetChildNodesAtIndex(uint32_t nodeIndex) const + OctreeNode* OctreeScene::GetChildNodesAtIndex(uint32_t nodeIndex) const { uint32_t childPage; uint32_t childOffset; ExtractPageAndOffsetFromIndex(nodeIndex, childPage, childOffset); return &(*m_nodeCache[childPage])[childOffset]; } + + + void OctreeSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1); + } + } + + + void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("OctreeService")); + } + + + void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("OctreeService")); + } + + + OctreeSystemComponent::OctreeSystemComponent() + { + AZ::Interface::Register(this); + IVisibilitySystemRequestBus::Handler::BusConnect(); + + m_defaultScene = aznew OctreeScene(AZ::Name("DefaultVisibilityScene")); + } + + + OctreeSystemComponent::~OctreeSystemComponent() + { + AZ_Assert(m_scenes.empty(), "All IVisibilityScenes must be destroyed before shutdown"); + + delete m_defaultScene; + + IVisibilitySystemRequestBus::Handler::BusDisconnect(); + AZ::Interface::Unregister(this); + } + + + void OctreeSystemComponent::Activate() + { + ; + } + + + void OctreeSystemComponent::Deactivate() + { + ; + } + + IVisibilityScene* OctreeSystemComponent::GetDefaultVisibilityScene() + { + return m_defaultScene; + } + + IVisibilityScene* OctreeSystemComponent::CreateVisibilityScene(const AZ::Name& sceneName) + { + AZ_Assert(FindVisibilityScene(sceneName) == nullptr, "Scene with same name already created!"); + OctreeScene* newScene = aznew OctreeScene(sceneName); + m_scenes.push_back(newScene); + return newScene; + } + + + void OctreeSystemComponent::DestroyVisibilityScene(IVisibilityScene* visScene) + { + for (auto iter = m_scenes.begin(); iter != m_scenes.end(); ++iter) + { + if (*iter == visScene) + { + delete visScene; + m_scenes.erase(iter); + return; + } + } + AZ_Assert(false, "visScene[\"%s\"] not found in the OctreeSystemComponent", visScene->GetName().GetCStr()); + } + + + IVisibilityScene* OctreeSystemComponent::FindVisibilityScene(const AZ::Name& sceneName) + { + for (OctreeScene* scene : m_scenes) + { + if(scene->GetName() == sceneName) + { + return scene; + } + } + return nullptr; + } + + + void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) + { + for (OctreeScene* scene : m_scenes) + { + AZ_TracePrintf("Console", "============================================"); + scene->DumpStats(); + } + AZ_TracePrintf("Console", "============================================"); + } } diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.h b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.h index c89ba93b7f..8a5362c003 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.h @@ -15,14 +15,15 @@ #include #include #include -#include #include #include #include +#include namespace AzFramework { class OctreeSystemComponent; + class OctreeScene; //! An internal node within the tree. //! It contains all objects that are *fully contained* by the node, if an object spans multiple child nodes that object will be stored in the parent. @@ -40,25 +41,25 @@ namespace AzFramework OctreeNode& operator=(OctreeNode&& rhs); //! Inserts a VisibilityEntry into this OctreeNode, potentially triggering a split. - void Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry); + void Insert(OctreeScene& octreeScene, VisibilityEntry* entry); //! Updates a VisibilityEntry that is currently bound to this OctreeNode. //! The provided entry must be bound to this node, but may no longer be bound to this node upon function exit. - void Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry); + void Update(OctreeScene& octreeScene, VisibilityEntry* entry); //! Removes a VisibilityEntry from this OctreeNode. //! The provided entry must be bound to this node. - void Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry); + void Remove(OctreeScene& octreeScene, VisibilityEntry* entry); //! Recursively enumerates any OctreeNodes and their children that intersect the provided bounding volume. //! @{ - void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const; - void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const; - void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const; + void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const; + void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const; + void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const; //! @} //! Recursively enumerate *all* OctreeNodes that have any entries in them (without any culling). - void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const; + void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const; //! Returns the set of entries bound to this node. const AZStd::vector& GetEntries() const; @@ -71,13 +72,13 @@ namespace AzFramework private: - void TryMerge(OctreeSystemComponent& octreeSystemComponent); + void TryMerge(OctreeScene& octreeScene); template - void EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const; + void EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const; - void Split(OctreeSystemComponent& octreeSystemComponent); - void Merge(OctreeSystemComponent& octreeSystemComponent); + void Split(OctreeScene& octreeScene); + void Merge(OctreeScene& octreeScene); // The page is stored in the upper 16-bits of the child node index, the offset into the page is the lower 16-bits // This gives us a maximum of 65,536 pages and 65,536 nodes per page, for a total of 2^32 - 1 total pages (-1 reserved for the invalid index) @@ -90,60 +91,47 @@ namespace AzFramework }; //! Implementation of the visibility system interface. - //! This uses a simple adaptive octreeSystemComponent to support partitioning an object set and efficiently running gathers and visibility queries. - class OctreeSystemComponent - : public AZ::Component - , public IVisibilitySystemRequestBus::Handler + //! This uses a simple adaptive octree to support partitioning an object set for a specific scene and efficiently running gathers and visibility queries. + class OctreeScene + : public IVisibilityScene { public: + AZ_RTTI(OctreeScene, "{A88E4D86-11F1-4E3F-A91A-66DE99502B93}"); + AZ_CLASS_ALLOCATOR(OctreeScene, AZ::SystemAllocator, 0); + AZ_DISABLE_COPY_MOVE(OctreeScene); - AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}"); + explicit OctreeScene(const AZ::Name& sceneName); + virtual ~OctreeScene(); - static void Reflect(AZ::ReflectContext* context); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - OctreeSystemComponent(); - virtual ~OctreeSystemComponent(); - - //! AZ::Component overrides. - //! @{ - void Activate() override; - void Deactivate() override; - //! @} - - //! IVisibilitySystem overrides. + //! IVisibilityScene overrides. //! @{ + const AZ::Name& GetName() const override; void InsertOrUpdateEntry(VisibilityEntry& entry) override; void RemoveEntry(VisibilityEntry& entry) override; - void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const override; - void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const override; - void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const override; - void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const override; + void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const override; + void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const override; + void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const override; + void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const override; uint32_t GetEntryCount() const override; //! @} - //! Returns the OctreeSystemComponent's root node. - OctreeNode& GetRoot(); - - //! OctreeSystemComponent stats + //! Stats //! @{ uint32_t GetNodeCount() const; uint32_t GetFreeNodeCount() const; uint32_t GetPageCount() const; uint32_t GetChildNodeCount() const; - void DumpStats(const AZ::ConsoleCommandContainer& arguments); + void DumpStats(); //! @} private: - uint32_t AllocateChildNodes(); void ReleaseChildNodes(uint32_t nodeIndex); OctreeNode* GetChildNodesAtIndex(uint32_t nodeIndex) const; - // Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats' - AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window"); + mutable AZStd::shared_mutex m_sharedMutex; + AZ::Name m_sceneName; //< The uniquely identifying name for the visibility scene. OctreeNode m_root; //< The root node for the octreeSystemComponent. uint32_t m_entryCount = 0; //< Metric tracking the number of entries inserted into the octreeSystemComponent. @@ -158,4 +146,47 @@ namespace AzFramework friend class OctreeNode; // For access to the node allocator methods }; + + //! Implementation of the visibility system interface. + //! This manages creating, destroying, and finding the underlying octrees that are associated with specific scenes + class OctreeSystemComponent + : public AZ::Component + , public IVisibilitySystemRequestBus::Handler + { + public: + AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}"); + + // Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats' + AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window"); + + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + OctreeSystemComponent(); + virtual ~OctreeSystemComponent(); + + //! AZ::Component overrides. + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + + //! IVisibilitySystem overrides + //! @{ + IVisibilityScene* GetDefaultVisibilityScene() override; + IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) override; + void DestroyVisibilityScene(IVisibilityScene* visScene) override; + IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) override; + void DumpStats(const AZ::ConsoleCommandContainer& arguments) override; + //! @} + + private: + //! The default scene used for most entities (e.g. gameplay, networking) + OctreeScene* m_defaultScene = nullptr; + + //! Other scenes (e.g. each rendering scene) are stored here and looked up by name. + AZStd::vector m_scenes; //using a vector<> here because we'll generally have a small number of scenes + + }; } diff --git a/Code/Framework/AzFramework/Platform/Android/AzFramework/IO/LocalFileIO_Android.cpp b/Code/Framework/AzFramework/Platform/Android/AzFramework/IO/LocalFileIO_Android.cpp index 4d025e1b20..b2cbe33438 100644 --- a/Code/Framework/AzFramework/Platform/Android/AzFramework/IO/LocalFileIO_Android.cpp +++ b/Code/Framework/AzFramework/Platform/Android/AzFramework/IO/LocalFileIO_Android.cpp @@ -16,13 +16,14 @@ #include #include #include +#include #include #include #include #if __ANDROID_API__ == 19 - // The following were apparently introduced in API 21, however in earlier versions of the + // The following were apparently introduced in API 21, however in earlier versions of the // platform specific headers they were defines. In the move to unified headers, the following // defines were removed from stat.h #ifndef stat64 @@ -52,7 +53,7 @@ namespace AZ if (AZ::Android::Utils::IsApkPath(resolvedPath)) { - return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath)); + return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath).c_str()); } struct stat result; @@ -108,7 +109,7 @@ namespace AZ if (isInAPK) { - AZ::OSString strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str()); + AZ::IO::FixedMaxPath strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str()); char tempBuffer[AZ_MAX_PATH_LEN] = {0}; diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp index a3ada465f8..770c0741f9 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp @@ -21,7 +21,7 @@ namespace AzFramework { AZStd::string GetPersistentName() { - AZStd::string persistentName = "Lumberyard"; + AZStd::string persistentName = "Open 3D Engine"; char procPath[AZ_MAX_PATH_LEN]; AZ::Utils::GetExecutablePathReturnType ret = AZ::Utils::GetExecutablePath(procPath, AZ_MAX_PATH_LEN); diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp index 660bb544a0..fd49f37dc8 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp @@ -56,7 +56,7 @@ namespace AzFramework bool m_isInBorderlessWindowFullScreenState = false; //!< Was a borderless window used to enter full screen state? }; - const char* NativeWindowImpl_Win32::s_defaultClassName = "LumberyardWin32Class"; + const char* NativeWindowImpl_Win32::s_defaultClassName = "O3DEWin32Class"; NativeWindow::Implementation* NativeWindow::Implementation::Create() { diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Input/Devices/Motion/InputDeviceMotion_iOS.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Input/Devices/Motion/InputDeviceMotion_iOS.mm index 8ce98afe3c..71037038a0 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Input/Devices/Motion/InputDeviceMotion_iOS.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Input/Devices/Motion/InputDeviceMotion_iOS.mm @@ -85,7 +85,7 @@ namespace AzFramework //! //! return another vector relative to the specified display orientation, and such that the //! +y axis points out the back of the screen and z+ axis points out the top of the device. - //! This flipping of axes is to match Lumberyard's z-up and left-handed coordinate system. + //! This flipping of axes is to match Open 3D Engine's z-up and left-handed coordinate system. //! //! \param[in] x The x component of the vector to be aligned //! \param[in] y The y component of the vector to be aligned diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index 4bd4ed5a40..f4fc9364f7 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -28,9 +28,9 @@ namespace AzGameFramework GameApplication::GameApplication() { } - - GameApplication::GameApplication(int* argc, char*** argv) - : Application(argc, argv) + + GameApplication::GameApplication(int argc, char** argv) + : Application(&argc, &argv) { } @@ -108,7 +108,7 @@ namespace AzGameFramework } void GameApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const - { + { appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; }; diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.h b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.h index 99735c9191..71b876c04b 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.h +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.h @@ -24,7 +24,7 @@ namespace AzGameFramework AZ_CLASS_ALLOCATOR(GameApplication, AZ::SystemAllocator, 0); GameApplication(); - GameApplication(int* argc, char*** argvS); + GameApplication(int argc, char** argvS); ~GameApplication(); AZ::ComponentTypeList GetRequiredSystemComponents() const override; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/AzQtComponentsAPI.h b/Code/Framework/AzQtComponents/AzQtComponents/AzQtComponentsAPI.h index 42e76551b3..e4e635658a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/AzQtComponentsAPI.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/AzQtComponentsAPI.h @@ -14,19 +14,17 @@ /** * \mainpage * - * Introduced with Amazon Lumberyard version 1.25 and the release of UI 2.0, Lumberyard's - * custom Qt widget library provides developers with access to the same UI components used - * throughout Lumberyard. Using this library, UI developers can build their own tools and - * extensions for Lumberyard, while maintaining a coherent and standardized UI experience. + * Using this library, UI developers can build their own tools and + * extensions for Open 3D Engine, while maintaining a coherent and standardized UI experience. * This custom library provides new and extended widgets, and includes a set of styles and * user interaction patterns that are applied on top of the Qt framework - the C++ library - * that Lumberyard relies on for its UI. The library can be extended to support your own customizations and modifications. + * that Open 3D Engine relies on for its UI. The library can be extended to support your own customizations and modifications. * * With this UI 2.0 API reference guide, we're working towards offering a full and comprehensive - * API refernce for all tools developers that are extending Lumberyard. The API reference + * API refernce for all tools developers that are extending Open 3D Engine. The API reference * is intended for C++ programmers building tools. For UX designers looking to understand * the best patterns and practices when making a tool to comfortably integrate with - * the Lumberyard editor, see the [UI 2.0 design guide](https://docs.aws.amazon.com/lumberyard/latest/ui/). + * the Open 3D Engine editor, see the [UI 2.0 design guide](https://docs.aws.amazon.com/lumberyard/latest/ui/). */ #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FilteredSearchWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FilteredSearchWidget.cpp index 6508b9f2f9..2cfe2a7abf 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FilteredSearchWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FilteredSearchWidget.cpp @@ -17,7 +17,7 @@ #include #include -#include "Components/ui_FilteredSearchWidget.h" +#include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/LumberyardStylesheet.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/O3DEStylesheet.h similarity index 85% rename from Code/Framework/AzQtComponents/AzQtComponents/Components/LumberyardStylesheet.h rename to Code/Framework/AzQtComponents/AzQtComponents/Components/O3DEStylesheet.h index bbc307639d..b881ebe9e1 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/LumberyardStylesheet.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/O3DEStylesheet.h @@ -16,10 +16,10 @@ namespace AzQtComponents { // Here for backwards compatibility with the old name of this class - class LumberyardStylesheet : public StyleManager + class O3DEStylesheet : public StyleManager { public: - LumberyardStylesheet(QObject* parent) : StyleManager(parent) {} + O3DEStylesheet(QObject* parent) : StyleManager(parent) {} }; } // namespace AzQtComponents diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h index 7f82a7b4c4..d1b2cd8eda 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h @@ -39,7 +39,7 @@ namespace AzQtComponents } // namespace Internal /** - * The UI 2.0 Lumberyard Qt Style. + * The UI 2.0 Open 3D Engine Qt Style. * * Should not need to be used directly; use the AzQtComponents::StyleManager instead. * diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.h index 404c0869cd..e7b5b61cc2 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.h @@ -37,7 +37,7 @@ namespace AzQtComponents class AutoCustomWindowDecorations; /** - * Wrapper around classes dealing with Lumberyard style. + * Wrapper around classes dealing with Open 3D Engine style. * * New applications should work like this: * diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ColorPicker/Palette.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ColorPicker/Palette.h index 67b3c512df..7d3c82ae22 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ColorPicker/Palette.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ColorPicker/Palette.h @@ -24,7 +24,7 @@ class QMimeData; namespace AzQtComponents { - static const QString MIME_TYPE_PALETTE = QStringLiteral("application/x-lumberyard-color-palette+xml"); + static const QString MIME_TYPE_PALETTE = QStringLiteral("application/x-o3de-color-palette+xml"); class PaletteModel; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Internal/OverlayWidgetLayer.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Internal/OverlayWidgetLayer.cpp index 7925b22614..41e8683663 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Internal/OverlayWidgetLayer.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Internal/OverlayWidgetLayer.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include namespace AzQtComponents @@ -264,4 +264,4 @@ namespace AzQtComponents } // namespace Internal } // namespace AzQtComponents -#include "Components/Widgets/Internal/moc_OverlayWidgetLayer.cpp" \ No newline at end of file +#include "Components/Widgets/Internal/moc_OverlayWidgetLayer.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/MessageBox.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/MessageBox.h index 1a181a18e9..b992183ac8 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/MessageBox.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/MessageBox.h @@ -20,7 +20,7 @@ namespace AzQtComponents class Style; /** - * Lumberyard specific wrapper to do MessageBox type stuff, specifically to automatically handle + * Open 3D Engine specific wrapper to do MessageBox type stuff, specifically to automatically handle * checking/writing "do not ask this question again" checkbox/settings. * * Called AzMessageBox instead of MessageBox because for windows.h does #define MessageBox MessageBoxA / MessageBoxW diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/WindowDecorationWrapper.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/WindowDecorationWrapper.cpp index 4e621835bf..5a7e68b21a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/WindowDecorationWrapper.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/WindowDecorationWrapper.cpp @@ -179,7 +179,7 @@ namespace AzQtComponents { m_guestWidget = nullptr; - // the Lumberyard Editor has code that checks for Modal widgets, and blocks on doing other things + // the Open 3D Engine Editor has code that checks for Modal widgets, and blocks on doing other things // if there are still active Modal dialogs. // So we need to ensure that this WindowDecorationWrapper doesn't report itself as being modal // after the guest widget has been deleted. diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/AssetBrowserFolderPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/AssetBrowserFolderPage.cpp index 33fb361a77..6cfc06a420 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/AssetBrowserFolderPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/AssetBrowserFolderPage.cpp @@ -10,7 +10,7 @@ * */ #include "AssetBrowserFolderPage.h" -#include "Gallery/ui_AssetBrowserFolderPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BreadCrumbsPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BreadCrumbsPage.cpp index 007a24429f..2ead6fc295 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BreadCrumbsPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BreadCrumbsPage.cpp @@ -11,7 +11,7 @@ */ #include "BreadCrumbsPage.h" -#include "Gallery/ui_BreadCrumbsPage.h" +#include #include #include @@ -107,4 +107,4 @@ BreadCrumbsPage::~BreadCrumbsPage() { } -#include "Gallery/moc_BreadCrumbsPage.cpp" \ No newline at end of file +#include "Gallery/moc_BreadCrumbsPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BrowseEditPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BrowseEditPage.cpp index 6a7645256b..0c4c50f543 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BrowseEditPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/BrowseEditPage.cpp @@ -11,7 +11,7 @@ */ #include "BrowseEditPage.h" -#include "Gallery/ui_BrowseEditPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ButtonPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ButtonPage.cpp index 8f0b258fa8..530bb5b433 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ButtonPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ButtonPage.cpp @@ -12,7 +12,7 @@ #include "ButtonPage.h" #include "FixedStateButton.h" -#include "Gallery/ui_ButtonPage.h" +#include #include @@ -110,4 +110,4 @@ ButtonPage::~ButtonPage() { } -#include "Gallery/moc_ButtonPage.cpp" \ No newline at end of file +#include "Gallery/moc_ButtonPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CardPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CardPage.cpp index d27360d934..f3d4fe20ad 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CardPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CardPage.cpp @@ -11,7 +11,7 @@ */ #include "CardPage.h" -#include "Gallery/ui_CardPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CheckBoxPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CheckBoxPage.cpp index 4d1fc36474..702124773c 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CheckBoxPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/CheckBoxPage.cpp @@ -11,7 +11,7 @@ */ #include "CheckBoxPage.h" -#include "Gallery/ui_CheckBoxPage.h" +#include #include @@ -71,4 +71,4 @@ CheckBoxPage::~CheckBoxPage() { } -#include "Gallery/moc_CheckBoxPage.cpp" \ No newline at end of file +#include "Gallery/moc_CheckBoxPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorLabelPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorLabelPage.cpp index c3dbe609cb..b2fed3f55e 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorLabelPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorLabelPage.cpp @@ -11,7 +11,7 @@ */ #include "ColorLabelPage.h" -#include "Gallery/ui_ColorLabelPage.h" +#include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorPickerPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorPickerPage.cpp index ce5d601eba..9f4f882347 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorPickerPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ColorPickerPage.cpp @@ -11,7 +11,7 @@ */ #include "ColorPickerPage.h" -#include "Gallery/ui_ColorPickerPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComboBoxPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComboBoxPage.cpp index 24f50e6902..edc93db9b6 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComboBoxPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComboBoxPage.cpp @@ -11,7 +11,7 @@ */ #include "ComboBoxPage.h" -#include "Gallery/ui_ComboBoxPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComponentDemoWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComponentDemoWidget.cpp index fec350137d..3e7c1eabea 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComponentDemoWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ComponentDemoWidget.cpp @@ -11,7 +11,7 @@ */ #include "ComponentDemoWidget.h" -#include "Gallery/ui_ComponentDemoWidget.h" +#include "AzQtComponents/Gallery/ui_ComponentDemoWidget.h" #include "AssetBrowserFolderPage.h" #include "BreadCrumbsPage.h" #include "BrowseEditPage.h" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/DragAndDropPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/DragAndDropPage.cpp index fd55c7e02a..ae90334b87 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/DragAndDropPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/DragAndDropPage.cpp @@ -11,7 +11,7 @@ */ #include "DragAndDropPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/FilteredSearchWidgetPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/FilteredSearchWidgetPage.cpp index 2f419220e2..a8a7cb60ff 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/FilteredSearchWidgetPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/FilteredSearchWidgetPage.cpp @@ -11,7 +11,7 @@ */ #include "FilteredSearchWidgetPage.h" -#include "Gallery/ui_FilteredSearchWidgetPage.h" +#include FilteredSearchWidgetPage::FilteredSearchWidgetPage(QWidget* parent) : QWidget(parent) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.ico b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.ico new file mode 100644 index 0000000000..d0948c09d5 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe52372c907d680df52dbf32d863a4007a15db90e9ad35fbe153870a72e2d0ef +size 108402 diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.rc b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.rc new file mode 100644 index 0000000000..fb44fadeb4 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/Gallery.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "Gallery.ico" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/GradientSliderPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/GradientSliderPage.cpp index 85f5ca2a9b..76bc1e3a28 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/GradientSliderPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/GradientSliderPage.cpp @@ -12,7 +12,7 @@ #include "GradientSliderPage.h" #include -#include "Gallery/ui_GradientSliderPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/HyperlinkPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/HyperlinkPage.cpp index bb8951f1a4..0d06f250ff 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/HyperlinkPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/HyperlinkPage.cpp @@ -11,7 +11,7 @@ */ #include "HyperlinkPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/LineEditPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/LineEditPage.cpp index 042f4d0d1e..fb9a59b020 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/LineEditPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/LineEditPage.cpp @@ -11,7 +11,7 @@ */ #include "LineEditPage.h" -#include "Gallery/ui_LineEditPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/MenuPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/MenuPage.cpp index c21ece683e..8220ba5d52 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/MenuPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/MenuPage.cpp @@ -11,7 +11,7 @@ */ #include "MenuPage.h" -#include +#include #include @@ -83,7 +83,7 @@ action->setChecked(true); auto submenu = menu->addMenu(QStringLiteral("Submenu")); submenu->addAction(actionText); -// Note: some Lumberyard menus (like the one in the MainWindow) forcefully hide icons by design. +// Note: some Open 3D Engine menus (like the one in the MainWindow) forcefully hide icons by design. diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ProgressIndicatorPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ProgressIndicatorPage.cpp index 85baf2f395..dc14bffa68 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ProgressIndicatorPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ProgressIndicatorPage.cpp @@ -11,7 +11,7 @@ */ #include "ProgressIndicatorPage.h" -#include "Gallery/ui_ProgressIndicatorPage.h" +#include ProgressIndicatorPage::ProgressIndicatorPage(QWidget* parent) : QWidget(parent) @@ -75,4 +75,4 @@ ProgressIndicatorPage::~ProgressIndicatorPage() { } -#include "Gallery/moc_ProgressIndicatorPage.cpp" \ No newline at end of file +#include "Gallery/moc_ProgressIndicatorPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/RadioButtonPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/RadioButtonPage.cpp index 7df0401842..11042c1365 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/RadioButtonPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/RadioButtonPage.cpp @@ -11,7 +11,7 @@ */ #include "RadioButtonPage.h" -#include "Gallery/ui_RadioButtonPage.h" +#include #include @@ -59,4 +59,4 @@ RadioButtonPage::~RadioButtonPage() { } -#include "Gallery/moc_RadioButtonPage.cpp" \ No newline at end of file +#include "Gallery/moc_RadioButtonPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ReflectedPropertyEditorPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ReflectedPropertyEditorPage.cpp index 067a5a9a48..f044efda61 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ReflectedPropertyEditorPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ReflectedPropertyEditorPage.cpp @@ -11,7 +11,7 @@ */ #include "ReflectedPropertyEditorPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ScrollBarPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ScrollBarPage.cpp index ef246e2221..d4c8920c22 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ScrollBarPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ScrollBarPage.cpp @@ -11,7 +11,7 @@ */ #include "ScrollBarPage.h" -#include +#include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SegmentControlPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SegmentControlPage.cpp index fa4a8c59e1..3d8b1aa8fd 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SegmentControlPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SegmentControlPage.cpp @@ -11,7 +11,7 @@ */ #include "SegmentControlPage.h" -#include "Gallery/ui_SegmentControlPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderComboPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderComboPage.cpp index 4a442fda40..997979a89b 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderComboPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderComboPage.cpp @@ -11,7 +11,7 @@ */ #include "SliderComboPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderPage.cpp index 5a311565a4..27ee34c776 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SliderPage.cpp @@ -11,7 +11,7 @@ */ #include "SliderPage.h" -#include "Gallery/ui_SliderPage.h" +#include #include @@ -155,4 +155,4 @@ SliderPage::~SliderPage() { } -#include "Gallery/moc_SliderPage.cpp" \ No newline at end of file +#include "Gallery/moc_SliderPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SpinBoxPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SpinBoxPage.cpp index 01afdac7ff..434e000b1c 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SpinBoxPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SpinBoxPage.cpp @@ -11,7 +11,7 @@ */ #include "SpinBoxPage.h" -#include "Gallery/ui_SpinBoxPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SplitterPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SplitterPage.cpp index 88bc752775..08d174699e 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SplitterPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SplitterPage.cpp @@ -11,7 +11,7 @@ */ #include "SplitterPage.h" -#include +#include SplitterPage::SplitterPage(QWidget* parent) : QWidget(parent) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyleSheetPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyleSheetPage.cpp index 61e12ebd03..a8c1f1ebf7 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyleSheetPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyleSheetPage.cpp @@ -11,7 +11,7 @@ */ #include "StyleSheetPage.h" -#include "Gallery/ui_StyleSheetPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyledDockWidgetPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyledDockWidgetPage.cpp index 0336bdfe4a..11214a6841 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyledDockWidgetPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/StyledDockWidgetPage.cpp @@ -11,7 +11,7 @@ */ #include "StyledDockWidgetPage.h" -#include "Gallery/ui_StyledDockWidgetPage.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SvgLabelPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SvgLabelPage.cpp index 2569b4daed..06d64ef9c3 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SvgLabelPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/SvgLabelPage.cpp @@ -11,7 +11,7 @@ */ #include "SvgLabelPage.h" -#include "Gallery/ui_SvgLabelPage.h" +#include #include #include @@ -118,4 +118,4 @@ void SvgLabelPage::dropEvent(QDropEvent *event) theImage->load(firstUrl.toLocalFile()); m_initialSize = theImage->renderer()->defaultSize(); onResetSize(); -} \ No newline at end of file +} diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TabWidgetPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TabWidgetPage.cpp index 0c942dc29b..ef38bc2245 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TabWidgetPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TabWidgetPage.cpp @@ -11,7 +11,7 @@ */ #include "TabWidgetPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TableViewPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TableViewPage.cpp index 56f097df5d..c70a34a9a9 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TableViewPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TableViewPage.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TitleBarPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TitleBarPage.cpp index dce13e26e5..c31f533574 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TitleBarPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TitleBarPage.cpp @@ -11,7 +11,7 @@ */ #include "TitleBarPage.h" -#include +#include TitleBarPage::TitleBarPage(QWidget* parent) : QWidget(parent) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToggleSwitchPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToggleSwitchPage.cpp index bfc84b965e..816525591b 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToggleSwitchPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToggleSwitchPage.cpp @@ -11,7 +11,7 @@ */ #include "ToggleSwitchPage.h" -#include +#include #include @@ -59,4 +59,4 @@ ToggleSwitchPage::~ToggleSwitchPage() { } -#include "Gallery/moc_ToggleSwitchPage.cpp" \ No newline at end of file +#include "Gallery/moc_ToggleSwitchPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToolBarPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToolBarPage.cpp index a5e303b3f2..5937d496de 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToolBarPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/ToolBarPage.cpp @@ -11,7 +11,7 @@ */ #include "ToolBarPage.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TreeViewPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TreeViewPage.cpp index 4fa2a145c7..823fadbf68 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TreeViewPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TreeViewPage.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include namespace { diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TypographyPage.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TypographyPage.cpp index acedfec4fb..267b0fcdf2 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TypographyPage.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/TypographyPage.cpp @@ -11,7 +11,7 @@ */ #include "TypographyPage.h" -#include +#include #include #include @@ -123,4 +123,4 @@ TypographyPage::~TypographyPage() { } -#include "Gallery/moc_TypographyPage.cpp" \ No newline at end of file +#include "Gallery/moc_TypographyPage.cpp" diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp index cffe20cb34..23b113cf7b 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include "ComponentDemoWidget.h" @@ -136,7 +136,7 @@ int main(int argc, char **argv) QApplication::setOrganizationName("Amazon"); QApplication::setOrganizationDomain("amazon.com"); - QApplication::setApplicationName("LumberyardWidgetGallery"); + QApplication::setApplicationName("O3DEWidgetGallery"); QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/PropertyEditorStandalone/main.cpp b/Code/Framework/AzQtComponents/AzQtComponents/PropertyEditorStandalone/main.cpp index 3ba2d96451..f2afb63a64 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/PropertyEditorStandalone/main.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/PropertyEditorStandalone/main.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/DeploymentsWidget.h b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/DeploymentsWidget.h index 2d1ee24cae..4b49883dc9 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/DeploymentsWidget.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/DeploymentsWidget.h @@ -14,7 +14,7 @@ #define DEPLOYMENTSWIDGET_H #if !defined(Q_MOC_RUN) -#include "StyleGallery/ui_deploymentswidget.h" +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/ViewportTitleDlg.cpp b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/ViewportTitleDlg.cpp index ba322e8375..eb6916f20a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/ViewportTitleDlg.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/ViewportTitleDlg.cpp @@ -16,7 +16,7 @@ #include "ViewportTitleDlg.h" -#include "StyleGallery/ui_ViewportTitleDlg.h" +#include #include ViewportTitleDlg::ViewportTitleDlg(QWidget* pParent) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/main.cpp b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/main.cpp index 0fc03e58cc..0d3827b43a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/main.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/main.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "MyCombo.h" #include @@ -183,7 +183,7 @@ int main(int argc, char **argv) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication app(argc, argv); - AzQtComponents::LumberyardStylesheet stylesheet(&app); + AzQtComponents::O3DEStylesheet stylesheet(&app); AZ::IO::FixedMaxPath engineRootPath; { AZ::ComponentApplication componentApplication(argc, argv); @@ -210,7 +210,7 @@ int main(int argc, char **argv) action->setMenu(fileMenu); auto openDock = fileMenu->addAction("Open dockwidget"); QObject::connect(openDock, &QAction::triggered, w, [&w] { - auto dock = new AzQtComponents::StyledDockWidget(QLatin1String("Amazon Lumberyard"), w); + auto dock = new AzQtComponents::StyledDockWidget(QLatin1String("Open 3D Engine"), w); auto button = new QPushButton("Click to dock"); auto wid = new QWidget(); auto widLayout = new QVBoxLayout(wid); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/mainwidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/mainwidget.cpp index 4c3cfe2adf..2cbdea45c3 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/mainwidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/StyleGallery/mainwidget.cpp @@ -10,7 +10,7 @@ * */ #include "mainwidget.h" -#include +#include #include #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/ScreenGrabber_win.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/ScreenGrabber_win.cpp index 747a7c3615..4539336b86 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/ScreenGrabber_win.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/ScreenGrabber_win.cpp @@ -117,7 +117,7 @@ namespace AzQtComponents // the correct size, but with garbage data in the last scanline. We crop this in the callback. m_magnifier = CreateWindowW( WC_MAGNIFIERW, - L"Lumberyard Color Picker Eyedropper Helper", + L"Open 3D Engine Color Picker Eyedropper Helper", WS_CHILD | WS_VISIBLE, 0, 0, diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake index fdbe6deb94..30929b712b 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake @@ -45,7 +45,7 @@ set(FILES Components/FilteredSearchWidget.ui Components/GlobalEventFilter.h Components/GlobalEventFilter.cpp - Components/LumberyardStylesheet.h + Components/O3DEStylesheet.h Components/Titlebar.cpp Components/Titlebar.h Components/TitleBarOverdrawHandler.cpp diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_gallery_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_gallery_files.cmake index d36e81b3d2..a9364efab4 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_gallery_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_gallery_files.cmake @@ -124,4 +124,5 @@ set(FILES Gallery/TreeViewPage.ui Gallery/TreeViewPage.cpp Gallery/TreeViewPage.h + Gallery/Gallery.rc ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index fc641cea33..0c631cf09e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -601,7 +601,7 @@ namespace AzToolsFramework virtual ResolveToolPathOutcome ResolveConfigToolsPath(const char* toolApplicationName) const = 0; /** - * LUMBERYARD INTERNAL USE ONLY. + * Open 3D Engine Internal use only. * * Run a specific redo command separate from the undo/redo system. * In many cases before a modifcation on an entity takes place, it is first packaged into diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 307d06129d..352048f5f0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -92,7 +92,7 @@ namespace AzToolsFramework namespace Internal { static const char* s_engineConfigFileName = "engine.json"; - static const char* s_engineConfigEngineVersionKey = "LumberyardVersion"; + static const char* s_engineConfigEngineVersionKey = "O3DEVersion"; static const char* s_startupLogWindow = "Startup"; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index a2773adf54..ef9f190309 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -155,7 +155,7 @@ namespace AzToolsFramework void CreateAndAddEntityFromComponentTags(const AZStd::vector& requiredTags, const char* entityName) override; - /* LUMBERYARD INTERNAL USE ONLY. */ + /* Open 3D Engine INTERNAL USE ONLY. */ void RunRedoSeparately(UndoSystem::URSequencePoint* redoCommand) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp index 69eba765e4..9ab50a803c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp @@ -23,7 +23,7 @@ #include AZ_PUSH_DISABLE_WARNING(4251 4244, "-Wunknown-warning-option") // disable warnings spawned by QT -#include "AssetBrowser/AssetPicker/ui_AssetPickerDialog.h" +#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Previewer/EmptyPreviewer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Previewer/EmptyPreviewer.cpp index 468ebb502d..99b235b2f4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Previewer/EmptyPreviewer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Previewer/EmptyPreviewer.cpp @@ -17,7 +17,7 @@ // 4251: class needs to have dll-interface to be used by clients of class // 4800: forcing value to bool 'true' or 'false' (performance warning) AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") -#include "AssetBrowser/Previewer/ui_EmptyPreviewer.h" +#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -45,4 +45,4 @@ namespace AzToolsFramework } } -#include \ No newline at end of file +#include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/FilterByWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/FilterByWidget.cpp index e5e1de4fc0..d0c5ec3837 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/FilterByWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/FilterByWidget.cpp @@ -11,7 +11,7 @@ */ #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING #include @@ -39,4 +39,4 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework -#include "AssetBrowser/Search/moc_FilterByWidget.cpp" \ No newline at end of file +#include "AssetBrowser/Search/moc_FilterByWidget.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchAssetTypeSelectorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchAssetTypeSelectorWidget.cpp index 189beea209..3d62c1d01b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchAssetTypeSelectorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchAssetTypeSelectorWidget.cpp @@ -18,7 +18,7 @@ #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING #include @@ -154,4 +154,4 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework -#include "AssetBrowser/Search/moc_SearchAssetTypeSelectorWidget.cpp" \ No newline at end of file +#include "AssetBrowser/Search/moc_SearchAssetTypeSelectorWidget.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchParametersWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchParametersWidget.cpp index b30adc0f18..09a8f84167 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchParametersWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/SearchParametersWidget.cpp @@ -12,7 +12,7 @@ #include "SearchParametersWidget.h" AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include "AssetBrowser/Search/ui_SearchParametersWidget.h" +#include AZ_POP_DISABLE_WARNING #include @@ -68,4 +68,4 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework -#include "AssetBrowser/Search/moc_SearchParametersWidget.cpp" \ No newline at end of file +#include "AssetBrowser/Search/moc_SearchParametersWidget.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h index 1aaed74e0f..697396b09e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h @@ -54,7 +54,7 @@ namespace AzToolsFramework //! Set unique asset browser name, used to persist tree expansion states void SetName(const QString& name); - // LUMBERYARD_DEPRECATED + // O3DE_DEPRECATED void LoadState(const QString& name); void SaveState() const; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp index 610b5a185b..603c7a8023 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp @@ -19,9 +19,9 @@ #include #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING -#include +#include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityModel.cpp index 18b2dacefb..9caca69b34 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityModel.cpp @@ -707,7 +707,7 @@ namespace AzToolsFramework { QMessageBox::warning(AzToolsFramework::GetActiveWindow(), QStringLiteral("Can't instantiate the selected slice"), - QString("The slice may contain UI elements that can't be instantiated in the main Lumberyard editor. " + QString("The slice may contain UI elements that can't be instantiated in the main Open 3D Engine editor. " "Use the UI Editor to instantiate this slice or select another one."), QMessageBox::Ok); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorManager.h index 85d5724cbd..5f57738b8c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorManager.h @@ -89,7 +89,7 @@ namespace AzToolsFramework const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteraction& mouseInteraction); - // LUMBERYARD_DEPRECATED(LY-117150) + // O3DE_DEPRECATED(LY-117150) /// Check if the modifier key state has changed - if so we may need to refresh /// certain manipulator bounds. AZ_DEPRECATED( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceEntityScrubber.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceEntityScrubber.h index 193d9ad496..a3945f8cf8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceEntityScrubber.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceEntityScrubber.h @@ -31,7 +31,7 @@ namespace AzToolsFramework class InstanceEntityScrubber { public: - AZ_RTTI(InstanceEntityScrubber, "{0BC12562-C240-48AD-89C6-EDF572C9B485}"); + AZ_TYPE_INFO(InstanceEntityScrubber, "{0BC12562-C240-48AD-89C6-EDF572C9B485}"); explicit InstanceEntityScrubber(Instance::EntityList& entities); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index a5056328ee..bd02f3cd9b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -219,11 +219,10 @@ namespace AzToolsFramework entitiesInInstance.emplace_back(entity.get()); } - InstanceEntityScrubber** instanceEntityScrubber = jsonDeserializerContext.GetMetadata().Find(); - if (instanceEntityScrubber && (*instanceEntityScrubber)) - + InstanceEntityScrubber* instanceEntityScrubber = jsonDeserializerContext.GetMetadata().Find(); + if (instanceEntityScrubber) { - (*instanceEntityScrubber)->AddEntitiesToScrub(entitiesInInstance); + instanceEntityScrubber->AddEntitiesToScrub(entitiesInInstance); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 979d85151a..d53aeaa241 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -10,6 +10,7 @@ * */ +#include #include #include #include @@ -78,6 +79,11 @@ namespace AzToolsFramework bool LoadInstanceFromPrefabDom(Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags) { + // When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will + // be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload + // is avoided. + AZ::Data::AssetManager::Instance().SuspendAssetRelease(); + InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetLoadingInstance(instance); if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId) @@ -91,10 +97,12 @@ namespace AzToolsFramework // data has strict typing and doesn't look for inheritance both have to be explicitly added so they're found both locations. settings.m_metadata.Add(static_cast(&entityIdMapper)); settings.m_metadata.Add(&entityIdMapper); - + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Load(instance, prefabDom, settings); + AZ::Data::AssetManager::Instance().ResumeAssetRelease(); + if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted) { AZ_Error("Prefab", false, @@ -110,6 +118,11 @@ namespace AzToolsFramework bool LoadInstanceFromPrefabDom( Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadInstanceFlags flags) { + // When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will + // be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload + // is avoided. + AZ::Data::AssetManager::Instance().SuspendAssetRelease(); + InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetLoadingInstance(instance); if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId) @@ -123,12 +136,12 @@ namespace AzToolsFramework // data has strict typing and doesn't look for inheritance both have to be explicitly added so they're found both locations. settings.m_metadata.Add(static_cast(&entityIdMapper)); settings.m_metadata.Add(&entityIdMapper); - - InstanceEntityScrubber instanceEntityScrubber(newlyAddedEntities); - settings.m_metadata.Add(&instanceEntityScrubber); + settings.m_metadata.Create(newlyAddedEntities); AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Load(instance, prefabDom, settings); + AZ::Data::AssetManager::Instance().ResumeAssetRelease(); + if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted) { AZ_Error( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceUtilities.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceUtilities.cpp index fc61d5717f..75070d9b41 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceUtilities.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceUtilities.cpp @@ -2662,7 +2662,7 @@ namespace AzToolsFramework QString cleanAssetSafeFolder(QDir::cleanPath(assetSafeFolder.c_str())); // Compare using clean paths so slash direction does not matter. // Note that this comparison is case sensitive because some file systems - // Lumberyard supports are case sensitive. + // Open 3D Engine supports are case sensitive. if (cleanSaveAs.startsWith(cleanAssetSafeFolder)) { isPathSafeForAssets = true; @@ -4017,8 +4017,8 @@ namespace AzToolsFramework // Detach entities action currently acts on entities and all descendants, so include those as part of the selection AzToolsFramework::EntityIdList selectedDetachEntities(selectedTransformHierarchyEntities.begin(), selectedTransformHierarchyEntities.end()); - // A selection in Lumberyard is usually singular, but a selection can have more than one entity. - // No Lumberyard systems support multiple selections, or multiple different groups of selected entities. + // A selection in Open 3D Engine is usually singular, but a selection can have more than one entity. + // No Open 3D Engine systems support multiple selections, or multiple different groups of selected entities. QString detachEntitiesActionText(QObject::tr("Selection")); QString detachEntitiesTooltipText; if (selectedDetachEntities.size() == 1) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp index 20e3bfc59a..c0b0b67c68 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp @@ -71,7 +71,7 @@ namespace AzToolsFramework AZ_Assert(!s_perforceConn, "You may only have one Perforce component.\n"); m_shutdownThreadSignal = false; m_waitingOnTrust = false; - m_autoChangelistDescription = "*Lumberyard Auto"; + m_autoChangelistDescription = "*Open 3D Engine Auto"; m_connectionState = SourceControlState::Disabled; m_validConnection = false; m_testConnection = false; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.cpp index 442e576489..affdce6e55 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.cpp @@ -24,7 +24,7 @@ namespace AzToolsFramework { QString ComponentTypeMimeData::GetMimeType() { - return "application/x-amazon-lumberyard-editorcomponenttypes"; + return "application/x-amazon-o3de-editorcomponenttypes"; } AZStd::unique_ptr ComponentTypeMimeData::Create(const ClassDataContainer& container) @@ -99,7 +99,7 @@ namespace AzToolsFramework QString ComponentMimeData::GetMimeType() { - return "application/x-amazon-lumberyard-editorcomponentdata"; + return "application/x-amazon-o3de-editorcomponentdata"; } AZStd::unique_ptr ComponentMimeData::Create(const ComponentDataContainer& components) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentBase.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentBase.h index c8ee2f8c8f..e1c42ecdf6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentBase.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentBase.h @@ -15,7 +15,7 @@ * Header file for the editor component base class. * Derive from this class to create a version of a component to use in the * editor, as opposed to the version of the component that is used during run time. - * To learn more about editor components, see the [Lumberyard Developer Guide] + * To learn more about editor components, see the [Open 3D Engine Developer Guide] * (http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-editor-components.html). */ @@ -52,7 +52,7 @@ namespace AzToolsFramework * To create one or more game components to represent your editor component * in runtime, use BuildGameEntity(). * - * To learn more about editor components, see the [Lumberyard Developer Guide] + * To learn more about editor components, see the [Open 3D Engine Developer Guide] * (http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-editor-components.html). */ class EditorComponentBase diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.cpp index 0119933cad..6365334502 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.cpp @@ -408,7 +408,7 @@ namespace AzToolsFramework QString fullLayerPath(layerFolder.filePath(myLayerFileName)); - // Lumberyard will read in the layer in whatever format it's in, so there's no need to check what the save format is set to. + // Open 3D Engine will read in the layer in whatever format it's in, so there's no need to check what the save format is set to. // The save format is also set in this object that is being loaded, so it wouldn't even be available. m_loadedLayer = AZ::Utils::LoadObjectFromFile(fullLayerPath.toUtf8().data()); @@ -1051,7 +1051,6 @@ namespace AzToolsFramework currentFailure)); // FileIO doesn't support removing directory, so use Qt. - // QDir::IsEmpty isn't available until a newer version fo Qt than Lumberyard is using. if (layerTempFolder.entryInfoList( QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System | QDir::Hidden).count() == 0) { @@ -1485,7 +1484,7 @@ namespace AzToolsFramework if (!newLayerEntityId.IsValid()) { - return LayerResult(LayerResultStatus::Error, "Lumberyard was unable to create a layer entity."); + return LayerResult(LayerResultStatus::Error, "Open 3D Engine was unable to create a layer entity."); } // If this new layer has a parent, then set its parent. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.h index db01687768..d32ec92c76 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorLayerComponent.h @@ -58,7 +58,7 @@ namespace AzToolsFramework AZ::Color m_color = AZ::Color::CreateOne(); // Default to text files, so the save history is easier to understand in source control. // This attribute only effects writing layers, and is safe to store here instead of on the component. - // When reading files off disk, Lumberyard figures out the correct format automatically. + // When reading files off disk, Open 3D Engine figures out the correct format automatically. bool m_saveAsBinary = false; // The layer entity needs to be invisible to all other systems, so they don't show up in the viewport. @@ -338,7 +338,7 @@ namespace AzToolsFramework EditorLayer* m_loadedLayer = nullptr; AZStd::string m_layerFileName; - // Lumberyard's serialization system requires everything in the editor to have a serialized to disk counterpart. + // Open 3D Engine's serialization system requires everything in the editor to have a serialized to disk counterpart. // Layers have their data split into two categories: Stuff that should save to the layer file, and stuff that should // save to the layer component in the level. To allow the layer component to edit the data that goes in the layer file, // a placeholder value is serialized. This is only used at edit time, and is copied and cleared during serialization. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp index ac1ec92049..8cc6d46da8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp @@ -112,7 +112,6 @@ namespace LegacyFramework m_applicationEntity = NULL; m_ptrSystemEntity = NULL; m_applicationModule[0] = 0; - m_appRoot[0] = 0; } HMODULE Application::GetMainModule() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/NewLogTabDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/NewLogTabDialog.cpp index 62b11a8048..4924c315b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/NewLogTabDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/NewLogTabDialog.cpp @@ -16,7 +16,7 @@ #include "NewLogTabDialog.h" AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING #include #include @@ -97,4 +97,4 @@ namespace AzToolsFramework } // namespace LogPanel } // namespace AzToolsFramework -#include "UI/Logging/moc_NewLogTabDialog.cpp" \ No newline at end of file +#include "UI/Logging/moc_NewLogTabDialog.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index a3a7e6ee6d..08fc764507 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -49,7 +49,7 @@ #include #include -#include +#include namespace { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 4fb23f2679..1e71b545b5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -644,7 +644,7 @@ namespace AzToolsFramework QString cleanAssetSafeFolder(QDir::cleanPath(assetSafeFolder.c_str())); // Compare using clean paths so slash direction does not matter. // Note that this comparison is case sensitive because some file systems - // Lumberyard supports are case sensitive. + // Open 3D Engine supports are case sensitive. if (cleanSaveAs.startsWith(cleanAssetSafeFolder)) { isPathSafeForAssets = true; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index ec3a4addf2..55c7fb3f65 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -100,7 +100,7 @@ AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") // 4244: con #include AZ_POP_DISABLE_WARNING -#include +#include // This has to live outside of any namespaces due to issues on Linux with calls to Q_INIT_RESOURCE if they are inside a namespace void initEntityPropertyEditorResources() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index d11abbc447..fed9c55f15 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx index 55b2669e91..ef542074a8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx @@ -89,7 +89,7 @@ namespace AzToolsFramework //! When set, disables data access for this property editor. //! This prevents any value refreshes from the inspected values from occurring as well as disabling user input. void PreventDataAccess(bool shouldPrevent); - // LUMBERYARD_DEPRECATED(LY-120821) + // O3DE_DEPRECATED(LY-120821) void PreventRefresh(bool shouldPrevent){PreventDataAccess(shouldPrevent);} void SetAutoResizeLabels(bool autoResizeLabels); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SliceOverridesNotificationWindow.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SliceOverridesNotificationWindow.cpp index 14e7d96204..369bbf3065 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SliceOverridesNotificationWindow.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SliceOverridesNotificationWindow.cpp @@ -11,7 +11,7 @@ */ #include "AzToolsFramework_precompiled.h" AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include "UI/Slice/ui_NotificationWindow.h" +#include AZ_POP_DISABLE_WARNING #include "UI/Slice/Constants.h" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/OverwritePromptDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/OverwritePromptDialog.cpp index 1f95d01e70..af0270fdc2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/OverwritePromptDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/OverwritePromptDialog.cpp @@ -14,7 +14,7 @@ #include "OverwritePromptDialog.hxx" AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -54,4 +54,4 @@ namespace AzToolsFramework } -#include "UI/UICore/moc_OverwritePromptDialog.cpp" \ No newline at end of file +#include "UI/UICore/moc_OverwritePromptDialog.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/ProgressShield.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/ProgressShield.cpp index d9713adccb..637a81e14e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/ProgressShield.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/ProgressShield.cpp @@ -18,7 +18,7 @@ #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' -#include +#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -118,4 +118,4 @@ namespace AzToolsFramework } // namespace AzToolsFramework -#include "UI/UICore/moc_ProgressShield.cpp" \ No newline at end of file +#include "UI/UICore/moc_ProgressShield.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/SaveChangesDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/SaveChangesDialog.cpp index 910f157ad1..5506b24ff6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/SaveChangesDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/UICore/SaveChangesDialog.cpp @@ -14,7 +14,7 @@ #include "SaveChangesDialog.hxx" AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option") -#include +#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -52,4 +52,4 @@ namespace AzToolsFramework } } -#include "UI/UICore/moc_SaveChangesDialog.cpp" \ No newline at end of file +#include "UI/UICore/moc_SaveChangesDialog.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 3f99277a6e..1a3bc0e5a3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -246,7 +246,7 @@ namespace UnitTest R"(... client unittest_workspace)" "\r\n" R"(... status pending)" "\r\n" R"(... changeType public)" "\r\n" - R"(... desc *Lumberyard Auto)" "\r\n" + R"(... desc *Open 3D Engine Auto)" "\r\n" "\r\n"; } else if (m_commandArgs.starts_with("fstat")) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h index 250adc5b86..161ca2d79f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h @@ -214,7 +214,7 @@ namespace AzToolsFramework return AzFramework::ScreenPoint{qpoint.x(), qpoint.y()}; } - /// Map from Qt -> Lumberyard buttons. + /// Map from Qt -> Open 3D Engine buttons.>>>>>>> main inline AZ::u32 TranslateMouseButtons(const Qt::MouseButtons buttons) { AZ::u32 result = 0; @@ -224,7 +224,7 @@ namespace AzToolsFramework return result; } - /// Map from Qt -> Lumberyard modifiers. + /// Map from Qt -> Open 3D Engine modifiers. inline AZ::u32 TranslateKeyboardModifiers(const Qt::KeyboardModifiers modifiers) { AZ::u32 result = 0; @@ -234,13 +234,13 @@ namespace AzToolsFramework return result; } - /// Interface to translate Qt modifiers to Lumberyard modifiers. + /// Interface to translate Qt modifiers to Open 3D Engine modifiers. inline KeyboardModifiers BuildKeyboardModifiers(const Qt::KeyboardModifiers modifiers) { return KeyboardModifiers(TranslateKeyboardModifiers(modifiers)); } - /// Interface to translate Qt buttons to Lumberyard buttons. + /// Interface to translate Qt buttons to Open 3D Engine buttons. inline MouseButtons BuildMouseButtons(const Qt::MouseButtons buttons) { return MouseButtons(TranslateMouseButtons(buttons)); diff --git a/Code/Framework/GridMate/GridMate/Replica/DataSet.h b/Code/Framework/GridMate/GridMate/Replica/DataSet.h index 37393dc491..f91a86dcec 100644 --- a/Code/Framework/GridMate/GridMate/Replica/DataSet.h +++ b/Code/Framework/GridMate/GridMate/Replica/DataSet.h @@ -47,7 +47,7 @@ namespace GridMate * * By default, DataSet::BindInterface only invokes on client/non-authoritative replica chunks. * This switch enables the callback on server/authoritative replica chunks. - * Warning: this change should not be enabled on existing Lumberyard components as they were not written with this option in mind. + * Warning: this change should not be enabled on existing Open 3D Engine components as they were not written with this option in mind. * * New user custom replica chunk will work just fine. */ diff --git a/Code/Framework/Tests/OctreePerformanceTests.cpp b/Code/Framework/Tests/OctreePerformanceTests.cpp index ba18ca44fe..a1979dce8e 100644 --- a/Code/Framework/Tests/OctreePerformanceTests.cpp +++ b/Code/Framework/Tests/OctreePerformanceTests.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #if defined(HAVE_BENCHMARK) @@ -33,7 +34,12 @@ namespace Benchmark m_ownsSystemAllocator = true; } + if (!AZ::NameDictionary::IsReady()) + { + AZ::NameDictionary::Create(); + } m_octreeSystemComponent = new AzFramework::OctreeSystemComponent; + m_visScene = m_octreeSystemComponent->CreateVisibilityScene(AZ::Name("OctreeBenchmarkVisibilityScene")); m_dataArray.resize(1000000); m_queryDataArray.resize(1000); @@ -72,7 +78,9 @@ namespace Benchmark void TearDown([[maybe_unused]] const ::benchmark::State& state) override { + m_octreeSystemComponent->DestroyVisibilityScene(m_visScene); delete m_octreeSystemComponent; + AZ::NameDictionary::Destroy(); m_dataArray.clear(); m_dataArray.shrink_to_fit(); @@ -89,19 +97,17 @@ namespace Benchmark void InsertEntries(uint32_t entryCount) { - AzFramework::IVisibilitySystem* visSystem = AZ::Interface::Get(); for (uint32_t i = 0; i < entryCount; ++i) { - visSystem->InsertOrUpdateEntry(m_dataArray[i]); + m_visScene->InsertOrUpdateEntry(m_dataArray[i]); } } void RemoveEntries(uint32_t entryCount) { - AzFramework::IVisibilitySystem* visSystem = AZ::Interface::Get(); for (uint32_t i = 0; i < entryCount; ++i) { - visSystem->RemoveEntry(m_dataArray[i]); + m_visScene->RemoveEntry(m_dataArray[i]); } } @@ -115,7 +121,8 @@ namespace Benchmark bool m_ownsSystemAllocator = false; AZStd::vector m_dataArray; AZStd::vector m_queryDataArray; - AzFramework::OctreeSystemComponent* m_octreeSystemComponent; + AzFramework::OctreeSystemComponent* m_octreeSystemComponent = nullptr; + AzFramework::IVisibilityScene* m_visScene = nullptr; }; BENCHMARK_F(BM_Octree, InsertDelete1000)(benchmark::State& state) @@ -166,7 +173,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.aabb, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.aabb, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -180,7 +187,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.aabb, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.aabb, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -194,7 +201,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.aabb, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.aabb, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -208,7 +215,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.aabb, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.aabb, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -222,7 +229,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.sphere, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.sphere, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -236,7 +243,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.sphere, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.sphere, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -250,7 +257,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.sphere, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.sphere, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -264,7 +271,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.sphere, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.sphere, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -278,7 +285,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.frustum, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.frustum, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -292,7 +299,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.frustum, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.frustum, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -306,7 +313,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.frustum, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.frustum, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); @@ -320,7 +327,7 @@ namespace Benchmark { for (auto& queryData : m_queryDataArray) { - m_octreeSystemComponent->Enumerate(queryData.frustum, [](const AzFramework::IVisibilitySystem::NodeData&) {}); + m_visScene->Enumerate(queryData.frustum, [](const AzFramework::IVisibilityScene::NodeData&) {}); } } RemoveEntries(EntryCount); diff --git a/Code/Framework/Tests/OctreeTests.cpp b/Code/Framework/Tests/OctreeTests.cpp index d7ba01a500..29c7ef3ff3 100644 --- a/Code/Framework/Tests/OctreeTests.cpp +++ b/Code/Framework/Tests/OctreeTests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -25,8 +26,13 @@ namespace UnitTest { public: void SetUp() override - { - AllocatorsFixture::SetUp(); + { + // Create the SystemAllocator if not available + if (!AZ::AllocatorInstance::IsReady()) + { + AZ::AllocatorInstance::Create(); + m_ownsSystemAllocator = true; + } m_console = aznew AZ::Console(); AZ::Interface::Register(m_console); @@ -41,12 +47,18 @@ namespace UnitTest m_console->PerformCommand("bg_octreeNodeMinEntries 1"); m_console->PerformCommand("bg_octreeMaxWorldExtents 1"); // Create a -1,-1,-1 to 1,1,1 world volume + if (!AZ::NameDictionary::IsReady()) + { + AZ::NameDictionary::Create(); + } m_octreeSystemComponent = new OctreeSystemComponent; + IVisibilityScene* visScene = m_octreeSystemComponent->CreateVisibilityScene(AZ::Name("OctreeUnitTestScene")); + m_octreeScene = azdynamic_cast(visScene); } void TearDown() override { - // Restore octreeSystemComponent cvars for any future tests or benchmarks that might get executed + //Restore octreeSystemComponent cvars for any future tests or benchmarks that might get executed AZStd::string commandString; commandString.format("bg_octreeNodeMaxEntries %u", m_savedMaxEntries); m_console->PerformCommand(commandString.c_str()); @@ -55,17 +67,31 @@ namespace UnitTest commandString.format("bg_octreeMaxWorldExtents %f", m_savedBounds); m_console->PerformCommand(commandString.c_str()); + m_octreeSystemComponent->DestroyVisibilityScene(m_octreeScene); delete m_octreeSystemComponent; + m_octreeSystemComponent = nullptr; + + AZ::NameDictionary::Destroy(); + AZ::Interface::Unregister(m_console); delete m_console; - AllocatorsFixture::TearDown(); + m_console = nullptr; + + // Destroy system allocator only if it was created by this environment + if (m_ownsSystemAllocator) + { + AZ::AllocatorInstance::Destroy(); + m_ownsSystemAllocator = false; + } } + bool m_ownsSystemAllocator = false; OctreeSystemComponent* m_octreeSystemComponent = nullptr; + OctreeScene* m_octreeScene = nullptr; uint32_t m_savedMaxEntries = 0; uint32_t m_savedMinEntries = 0; float m_savedBounds = 0.0f; - AZ::Console* m_console = nullptr; + AZ::Console* m_console; }; TEST_F(OctreeTests, InsertDeleteSingleEntry) @@ -73,14 +99,16 @@ namespace UnitTest AzFramework::VisibilityEntry visEntry; visEntry.m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3::CreateOne()); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry); + m_octreeScene->InsertOrUpdateEntry(visEntry); EXPECT_TRUE(visEntry.m_internalNode != nullptr); EXPECT_TRUE(visEntry.m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); - m_octreeSystemComponent->RemoveEntry(visEntry); + m_octreeScene->RemoveEntry(visEntry); EXPECT_TRUE(visEntry.m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 0); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 0); + + EXPECT_TRUE(true); //TEST } TEST_F(OctreeTests, InsertDeleteSplitMerge) @@ -90,37 +118,37 @@ namespace UnitTest visEntry[1].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.1f), AZ::Vector3( 0.4f)); visEntry[2].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[0]); + m_octreeScene->InsertOrUpdateEntry(visEntry[0]); EXPECT_TRUE(visEntry[0].m_internalNode != nullptr); EXPECT_TRUE(visEntry[0].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[1]); // This should force a split of the root node + m_octreeScene->InsertOrUpdateEntry(visEntry[1]); // This should force a split of the root node EXPECT_TRUE(visEntry[1].m_internalNode != nullptr); EXPECT_TRUE(visEntry[1].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 2); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + m_octreeSystemComponent->GetChildNodeCount()); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 2); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + m_octreeScene->GetChildNodeCount()); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[2]); // This should force a split of the roots +/+/+ child node + m_octreeScene->InsertOrUpdateEntry(visEntry[2]); // This should force a split of the roots +/+/+ child node EXPECT_TRUE(visEntry[2].m_internalNode != nullptr); EXPECT_TRUE(visEntry[2].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 3); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + (2 * m_octreeSystemComponent->GetChildNodeCount())); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 3); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + (2 * m_octreeScene->GetChildNodeCount())); - m_octreeSystemComponent->RemoveEntry(visEntry[2]); + m_octreeScene->RemoveEntry(visEntry[2]); EXPECT_TRUE(visEntry[2].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 2); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + m_octreeSystemComponent->GetChildNodeCount()); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 2); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + m_octreeScene->GetChildNodeCount()); - m_octreeSystemComponent->RemoveEntry(visEntry[1]); + m_octreeScene->RemoveEntry(visEntry[1]); EXPECT_TRUE(visEntry[1].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); - m_octreeSystemComponent->RemoveEntry(visEntry[0]); + m_octreeScene->RemoveEntry(visEntry[0]); EXPECT_TRUE(visEntry[0].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 0); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 0); } TEST_F(OctreeTests, UpdateSingleEntry) @@ -128,23 +156,23 @@ namespace UnitTest AzFramework::VisibilityEntry visEntry; visEntry.m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3::CreateOne()); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry); + m_octreeScene->InsertOrUpdateEntry(visEntry); EXPECT_TRUE(visEntry.m_internalNode != nullptr); EXPECT_TRUE(visEntry.m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); visEntry.m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f)); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry); + m_octreeScene->InsertOrUpdateEntry(visEntry); EXPECT_TRUE(visEntry.m_internalNode != nullptr); EXPECT_TRUE(visEntry.m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); - m_octreeSystemComponent->RemoveEntry(visEntry); + m_octreeScene->RemoveEntry(visEntry); EXPECT_TRUE(visEntry.m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 0); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); } TEST_F(OctreeTests, UpdateSplitMerge) @@ -154,92 +182,92 @@ namespace UnitTest visEntry[1].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.1f), AZ::Vector3( 0.4f)); visEntry[2].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[0]); + m_octreeScene->InsertOrUpdateEntry(visEntry[0]); EXPECT_TRUE(visEntry[0].m_internalNode != nullptr); EXPECT_TRUE(visEntry[0].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[1]); // This should force a split of the root node + m_octreeScene->InsertOrUpdateEntry(visEntry[1]); // This should force a split of the root node EXPECT_TRUE(visEntry[1].m_internalNode != nullptr); EXPECT_TRUE(visEntry[1].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 2); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + m_octreeSystemComponent->GetChildNodeCount()); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 2); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + m_octreeScene->GetChildNodeCount()); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[2]); // This should force a split of the roots +/+/+ child node + m_octreeScene->InsertOrUpdateEntry(visEntry[2]); // This should force a split of the roots +/+/+ child node EXPECT_TRUE(visEntry[2].m_internalNode != nullptr); EXPECT_TRUE(visEntry[2].m_internalNodeIndex == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 3); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + (2 * m_octreeSystemComponent->GetChildNodeCount())); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 3); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + (2 * m_octreeScene->GetChildNodeCount())); visEntry[1].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.9f), AZ::Vector3(-0.6f)); visEntry[2].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.1f), AZ::Vector3( 0.4f)); visEntry[0].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[0]); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[1]); - m_octreeSystemComponent->InsertOrUpdateEntry(visEntry[2]); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 3); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + (2 * m_octreeSystemComponent->GetChildNodeCount())); + m_octreeScene->InsertOrUpdateEntry(visEntry[0]); + m_octreeScene->InsertOrUpdateEntry(visEntry[1]); + m_octreeScene->InsertOrUpdateEntry(visEntry[2]); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 3); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + (2 * m_octreeScene->GetChildNodeCount())); - m_octreeSystemComponent->RemoveEntry(visEntry[2]); + m_octreeScene->RemoveEntry(visEntry[2]); EXPECT_TRUE(visEntry[2].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 2); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1 + m_octreeSystemComponent->GetChildNodeCount()); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 2); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1 + m_octreeScene->GetChildNodeCount()); - m_octreeSystemComponent->RemoveEntry(visEntry[1]); + m_octreeScene->RemoveEntry(visEntry[1]); EXPECT_TRUE(visEntry[1].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 1); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 1); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); - m_octreeSystemComponent->RemoveEntry(visEntry[0]); + m_octreeScene->RemoveEntry(visEntry[0]); EXPECT_TRUE(visEntry[0].m_internalNode == nullptr); - EXPECT_TRUE(m_octreeSystemComponent->GetEntryCount() == 0); - EXPECT_TRUE(m_octreeSystemComponent->GetNodeCount() == 1); + EXPECT_TRUE(m_octreeScene->GetEntryCount() == 0); + EXPECT_TRUE(m_octreeScene->GetNodeCount() == 1); } - void AppendEntries(AZStd::vector& gatheredEntries, const AzFramework::IVisibilitySystem::NodeData& nodeData) + void AppendEntries(AZStd::vector& gatheredEntries, const AzFramework::IVisibilityScene::NodeData& nodeData) { gatheredEntries.insert(gatheredEntries.end(), nodeData.m_entries.begin(), nodeData.m_entries.end()); } template - void EnumerateSingleEntryHelper(OctreeSystemComponent* octreeSystemComponent, const BoundType& bounds) + void EnumerateSingleEntryHelper(IVisibilityScene* visScene, const BoundType& bounds) { AzFramework::VisibilityEntry visEntry; visEntry.m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3::CreateOne()); AZStd::vector gatheredEntries; - octreeSystemComponent->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.empty()); - octreeSystemComponent->InsertOrUpdateEntry(visEntry); - octreeSystemComponent->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->InsertOrUpdateEntry(visEntry); + visScene->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &visEntry); visEntry.m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f)); - octreeSystemComponent->InsertOrUpdateEntry(visEntry); + visScene->InsertOrUpdateEntry(visEntry); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &visEntry); - octreeSystemComponent->RemoveEntry(visEntry); + visScene->RemoveEntry(visEntry); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bounds, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.empty()); } TEST_F(OctreeTests, EnumerateSphereSingleEntry) { AZ::Sphere bounds = AZ::Sphere::CreateUnitSphere(); - EnumerateSingleEntryHelper(m_octreeSystemComponent, bounds); + EnumerateSingleEntryHelper(m_octreeScene, bounds); } TEST_F(OctreeTests, EnumerateAabbSingleEntry) { AZ::Aabb bounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.0f), AZ::Vector3(1.0f)); - EnumerateSingleEntryHelper(m_octreeSystemComponent, bounds); + EnumerateSingleEntryHelper(m_octreeScene, bounds); } TEST_F(OctreeTests, EnumerateFrustumSingleEntry) @@ -248,14 +276,14 @@ namespace UnitTest AZ::Quaternion frustumDirection = AZ::Quaternion::CreateIdentity(); AZ::Transform frustumTransform = AZ::Transform::CreateFromQuaternionAndTranslation(frustumDirection, frustumOrigin); AZ::Frustum bounds = AZ::Frustum(AZ::ViewFrustumAttributes(frustumTransform, 1.0f, 2.0f * atanf(0.5f), 1.0f, 3.0f)); - EnumerateSingleEntryHelper(m_octreeSystemComponent, bounds); + EnumerateSingleEntryHelper(m_octreeScene, bounds); } // bound1 should cover the entire spatial hash // bound2 should not cross into the positive Y-axis // bound3 should only intersect the region inside 0.6, 0.6, 0.6 to 0.9, 0.9, 0.9 template - void EnumerateMultipleEntriesHelper(OctreeSystemComponent* octreeSystemComponent, const BoundType& bound1, const BoundType& bound2, const BoundType& bound3) + void EnumerateMultipleEntriesHelper(IVisibilityScene* visScene, const BoundType& bound1, const BoundType& bound2, const BoundType& bound3) { AZStd::vector gatheredEntries; @@ -264,50 +292,50 @@ namespace UnitTest visEntry[1].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.1f), AZ::Vector3( 0.4f)); visEntry[2].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[0]); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[1]); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[2]); + visScene->InsertOrUpdateEntry(visEntry[0]); + visScene->InsertOrUpdateEntry(visEntry[1]); + visScene->InsertOrUpdateEntry(visEntry[2]); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 3); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound2, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound2, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &(visEntry[0])); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound3, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound3, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &(visEntry[2])); visEntry[1].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.9f), AZ::Vector3(-0.6f)); visEntry[2].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.1f), AZ::Vector3( 0.4f)); visEntry[0].m_boundingVolume = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[0]); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[1]); - octreeSystemComponent->InsertOrUpdateEntry(visEntry[2]); + visScene->InsertOrUpdateEntry(visEntry[0]); + visScene->InsertOrUpdateEntry(visEntry[1]); + visScene->InsertOrUpdateEntry(visEntry[2]); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 3); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound2, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound2, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &(visEntry[1])); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound3, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound3, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.size() == 1); EXPECT_TRUE(gatheredEntries[0] == &(visEntry[0])); - octreeSystemComponent->RemoveEntry(visEntry[0]); - octreeSystemComponent->RemoveEntry(visEntry[1]); - octreeSystemComponent->RemoveEntry(visEntry[2]); + visScene->RemoveEntry(visEntry[0]); + visScene->RemoveEntry(visEntry[1]); + visScene->RemoveEntry(visEntry[2]); gatheredEntries.clear(); - octreeSystemComponent->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); + visScene->Enumerate(bound1, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { AppendEntries(gatheredEntries, nodeData); }); EXPECT_TRUE(gatheredEntries.empty()); } @@ -316,7 +344,7 @@ namespace UnitTest AZ::Sphere bound1 = AZ::Sphere::CreateUnitSphere(); AZ::Sphere bound2 = AZ::Sphere(AZ::Vector3(-0.5f), 0.5f); AZ::Sphere bound3 = AZ::Sphere(AZ::Vector3(0.75f), 0.2f); - EnumerateMultipleEntriesHelper(m_octreeSystemComponent, bound1, bound2, bound3); + EnumerateMultipleEntriesHelper(m_octreeScene, bound1, bound2, bound3); } TEST_F(OctreeTests, EnumerateAabbMultipleEntries) @@ -324,7 +352,7 @@ namespace UnitTest AZ::Aabb bound1 = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.0f), AZ::Vector3( 1.0f)); AZ::Aabb bound2 = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.0f), AZ::Vector3(-0.5f)); AZ::Aabb bound3 = AZ::Aabb::CreateFromMinMax(AZ::Vector3( 0.6f), AZ::Vector3( 0.9f)); - EnumerateMultipleEntriesHelper(m_octreeSystemComponent, bound1, bound2, bound3); + EnumerateMultipleEntriesHelper(m_octreeScene, bound1, bound2, bound3); } TEST_F(OctreeTests, EnumerateFrustumMultipleEntries) @@ -335,6 +363,6 @@ namespace UnitTest AZ::Frustum bound1 = AZ::Frustum(AZ::ViewFrustumAttributes(frustumTransform, 1.0f, 2.0f * atanf(0.5f), 1.0f, 3.0f)); AZ::Frustum bound2 = AZ::Frustum(AZ::ViewFrustumAttributes(frustumTransform, 1.0f, 2.0f * atanf(0.5f), 1.0f, 2.0f)); AZ::Frustum bound3 = AZ::Frustum(AZ::ViewFrustumAttributes(frustumTransform, 1.0f, 2.0f * atanf(0.5f), 2.6f, 2.9f)); - EnumerateMultipleEntriesHelper(m_octreeSystemComponent, bound1, bound2, bound3); + EnumerateMultipleEntriesHelper(m_octreeScene, bound1, bound2, bound3); } } diff --git a/Code/LauncherUnified/CMakeLists.txt b/Code/LauncherUnified/CMakeLists.txt index 0d056686b8..cef937684d 100644 --- a/Code/LauncherUnified/CMakeLists.txt +++ b/Code/LauncherUnified/CMakeLists.txt @@ -67,182 +67,7 @@ if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) endif() -get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) -foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJECTS) - # Computes the realpath to the project - # If the project_path is relative, it is evaluated relative to the ${LY_ROOT_FOLDER} - # Otherwise the the absolute project_path is returned with symlinks resolved - file(REAL_PATH ${project_path} project_real_path BASE_DIRECTORY ${LY_ROOT_FOLDER}) - ################################################################################ - # Monolithic game - ################################################################################ - if(LY_MONOLITHIC_GAME) - - # In the monolithic case, we need to register the gem modules, to do so we will generate a StaticModules.inl - # file from StaticModules.in - - get_property(game_gem_dependencies GLOBAL PROPERTY LY_DELAYED_DEPENDENCIES_${project_name}.GameLauncher) - - unset(extern_module_declarations) - unset(module_invocations) - - foreach(game_gem_dependency ${game_gem_dependencies}) - # To match the convention on how gems targets vs gem modules are named, we remove the "Gem::" from prefix - # and remove the ".Static" from the suffix - string(REGEX REPLACE "^Gem::" "Gem_" game_gem_dependency ${game_gem_dependency}) - string(REGEX REPLACE "^Project::" "Project_" game_gem_dependency ${game_gem_dependency}) - # Replace "." with "_" - string(REPLACE "." "_" game_gem_dependency ${game_gem_dependency}) - - string(APPEND extern_module_declarations "extern \"C\" AZ::Module* CreateModuleClass_${game_gem_dependency}();\n") - string(APPEND module_invocations " modulesOut.push_back(CreateModuleClass_${game_gem_dependency}());\n") - - endforeach() - - configure_file(StaticModules.in - ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.GameLauncher/Includes/StaticModules.inl - ) - - set(game_build_dependencies - ${game_gem_dependencies} - Legacy::CrySystem - Legacy::CryFont - Legacy::Cry3DEngine - ) - - if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) - get_property(server_gem_dependencies GLOBAL PROPERTY LY_DELAYED_DEPENDENCIES_${project_name}.ServerLauncher) - - unset(extern_module_declarations) - unset(module_invocations) - - foreach(server_gem_dependency ${server_gem_dependencies}) - # To match the convention on how gems targets vs gem modules are named, we remove the "Gem::" from prefix - # and remove the ".Static" from the suffix - string(REGEX REPLACE "^Gem::" "Gem_" server_gem_dependency ${server_gem_dependency}) - string(REGEX REPLACE "^Project::" "Project_" server_gem_dependency ${server_gem_dependency}) - # Replace "." with "_" - string(REPLACE "." "_" server_gem_dependency ${server_gem_dependency}) - - string(APPEND extern_module_declarations "extern \"C\" AZ::Module* CreateModuleClass_${server_gem_dependency}();\n") - string(APPEND module_invocations " modulesOut.push_back(CreateModuleClass_${server_gem_dependency}());\n") - - endforeach() - - configure_file(StaticModules.in - ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.ServerLauncher/Includes/StaticModules.inl - ) - - set(server_build_dependencies - ${game_gem_dependencies} - Legacy::CrySystem - Legacy::CryFont - Legacy::Cry3DEngine - ) - endif() - - else() - - set(game_runtime_dependencies - Legacy::CrySystem - Legacy::CryFont - Legacy::Cry3DEngine - ) - if(PAL_TRAIT_BUILD_SERVER_SUPPORTED AND NOT LY_MONOLITHIC_GAME) # Only Atom is supported in monolithic builds - set(server_runtime_dependencies - Legacy::CryRenderNULL - ) - endif() - - endif() - - ################################################################################ - # Game - ################################################################################ - ly_add_target( - NAME ${project_name}.GameLauncher ${PAL_TRAIT_LAUNCHERUNIFIED_LAUNCHER_TYPE} - NAMESPACE AZ - FILES_CMAKE - launcher_project_files.cmake - PLATFORM_INCLUDE_FILES - ${pal_dir}/launcher_project_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - COMPILE_DEFINITIONS - PRIVATE - # Adds the name of the project/game - LY_PROJECT_NAME="${project_name}" - # Adds the project path supplied to CMake during configuration - # This is used as a fallback to launch the AssetProcessor - LY_PROJECT_CMAKE_PATH="${project_path}" - # Adds the ${project_name}_GameLauncher target as a define so for the Settings Registry to use - # when loading .setreg file specializations - # This is needed so that only gems for the project game launcher are loaded - LY_CMAKE_TARGET="${project_name}_GameLauncher" - INCLUDE_DIRECTORIES - PRIVATE - . - ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.GameLauncher/Includes # required for StaticModules.inl - BUILD_DEPENDENCIES - PRIVATE - AZ::Launcher.Static - AZ::Launcher.Game.Static - ${game_build_dependencies} - RUNTIME_DEPENDENCIES - ${game_runtime_dependencies} - ) - # Needs to be set manually after ly_add_target to prevent the default location overriding it - set_target_properties(${project_name}.GameLauncher - PROPERTIES - FOLDER ${project_name} - ) - - ################################################################################ - # Server - ################################################################################ - if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) - - get_property(server_projects GLOBAL PROPERTY LY_LAUNCHER_SERVER_PROJECTS) - if(${project_name} IN_LIST server_projects) - - ly_add_target( - NAME ${project_name}.ServerLauncher APPLICATION - NAMESPACE AZ - FILES_CMAKE - launcher_project_files.cmake - PLATFORM_INCLUDE_FILES - ${pal_dir}/launcher_project_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - COMPILE_DEFINITIONS - PRIVATE - # Adds the name of the project/game - LY_PROJECT_NAME="${project_name}" - # Adds the project path supplied to CMake during configuration - # This is used as a fallback to launch the AssetProcessor - LY_PROJECT_CMAKE_PATH="${project_path}" - # Adds the ${project_name}_ServerLauncher target as a define so for the Settings Registry to use - # when loading .setreg file specializations - # This is needed so that only gems for the project server launcher are loaded - LY_CMAKE_TARGET="${project_name}_ServerLauncher" - INCLUDE_DIRECTORIES - PRIVATE - . - ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.ServerLauncher/Includes # required for StaticModules.inl - BUILD_DEPENDENCIES - PRIVATE - AZ::Launcher.Static - AZ::Launcher.Server.Static - ${server_build_dependencies} - RUNTIME_DEPENDENCIES - ${server_runtime_dependencies} - ) - # Needs to be set manually after ly_add_target to prevent the default location overriding it - set_target_properties(${project_name}.ServerLauncher - PROPERTIES - FOLDER ${project_name} - ) - endif() - - endif() - -endforeach() +include(${CMAKE_CURRENT_LIST_DIR}/launcher_generator.cmake) ################################################################################ # Tests diff --git a/Code/LauncherUnified/FindLauncherGenerator.cmake b/Code/LauncherUnified/FindLauncherGenerator.cmake new file mode 100644 index 0000000000..0a975776b8 --- /dev/null +++ b/Code/LauncherUnified/FindLauncherGenerator.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(pal_dir ${LY_ROOT_FOLDER}/LauncherGenerator/Platform/${PAL_PLATFORM_NAME}) +include(${pal_dir}/LauncherUnified_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +include(${LY_ROOT_FOLDER}/LauncherGenerator/launcher_generator.cmake) \ No newline at end of file diff --git a/Code/LauncherUnified/Game.cpp b/Code/LauncherUnified/Game.cpp index c101dd4efa..3d4cb4769f 100644 --- a/Code/LauncherUnified/Game.cpp +++ b/Code/LauncherUnified/Game.cpp @@ -12,7 +12,7 @@ #include -namespace LumberyardLauncher +namespace O3DELauncher { bool WaitForAssetProcessorConnect() { diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index c00bb06be3..cd9d73421b 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include @@ -230,7 +231,7 @@ namespace } -namespace LumberyardLauncher +namespace O3DELauncher { AZ_CVAR(bool, bg_ConnectToAssetProcessor, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "If true, the process will launch and connect to the asset processor"); @@ -357,9 +358,9 @@ namespace LumberyardLauncher return connectedToAssetProcessor; } - //! Compiles the critical assets that are within the Engine directory of Lumberyard + //! Compiles the critical assets that are within the Engine directory of Open 3D Engine //! This code should be in a centralized location, but doesn't belong in AzFramework - //! since it is specific to how Lumberyard projects has assets setup + //! since it is specific to how Open 3D Engine projects has assets setup void CompileCriticalAssets() { // VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others, @@ -385,64 +386,16 @@ namespace LumberyardLauncher AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, "remote_filesystem"); if (allowRemoteFilesystem != 0) { - // The SetInstance calls below will assert if this has already been set and we don't clear first // Application::StartCommon will set a LocalFileIO base first. // This provides an opportunity for the RemoteFileIO to override the direct instance - auto remoteFileIo = new AZ::IO::RemoteFileIO(AZ::IO::FileIOBase::GetDirectInstance()); // Wrap AZ:I::LocalFileIO the direct instance + auto remoteFileIo = new AZ::IO::RemoteFileIO(AZ::IO::FileIOBase::GetDirectInstance()); // Wrap LocalFileIO the direct instance AZ::IO::FileIOBase::SetDirectInstance(nullptr); // Wrap AZ:IO::LocalFileIO the direct instance AZ::IO::FileIOBase::SetDirectInstance(remoteFileIo); } } - //! Add the GameProjectName and Launcher build target name into the settings registry - void AddProjectMetadataToSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry, AZ::CommandLine& commandLine) - { - // Inject the Project Path and Project into the CommandLine parameters to beginning of the command line - // in order to allow it to used as a fallback if the parameters aren't supplied launch parameters already - // Command Line parameters are the bootstrap settings into the Settings Registry, so they precedence - auto projectPathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) - + "/project_path"; - auto projectNameKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) - + "/project_name"; - - AZ::CommandLine::ParamContainer commandLineArgs; - commandLine.Dump(commandLineArgs); - - // Insert the project_name option to the front - const AZStd::string_view launcherProjectName = GetProjectName(); - if (!launcherProjectName.empty()) - { - auto projectNameOptionOverride = AZ::SettingsRegistryInterface::FixedValueString::format(R"(--regset="%s=%.*s")", - projectNameKey.c_str(), aznumeric_cast(launcherProjectName.size()), launcherProjectName.data()); - commandLineArgs.emplace(commandLineArgs.begin(), projectNameOptionOverride); - } - - // Insert the project_path option to the front - const AZStd::string_view projectPath = GetProjectPath(); - if (!projectPath.empty()) - { - auto projectPathOptionOverride = AZ::SettingsRegistryInterface::FixedValueString::format(R"(--regset="%s=%.*s")", - projectPathKey.c_str(), aznumeric_cast(projectPath.size()), projectPath.data()); - commandLineArgs.emplace(commandLineArgs.begin(), projectPathOptionOverride); - } - - commandLine.Parse(commandLineArgs); - - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(settingsRegistry, commandLine, false); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(settingsRegistry); - - const AZStd::string_view buildTargetName = LumberyardLauncher::GetBuildTargetName(); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(settingsRegistry, buildTargetName); - - AZ_TracePrintf("Launcher", R"(Running project "%.*s.)" "\n" - R"(The project name value has been successfully set in the Settings Registry at key "%s/project_name" for Launcher target "%.*s")" "\n", - aznumeric_cast(launcherProjectName.size()), launcherProjectName.data(), - AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey, - aznumeric_cast(buildTargetName.size()), buildTargetName.data()); - } - ReturnCode Run(const PlatformMainInfo& mainInfo) { if (mainInfo.m_updateResourceLimits @@ -454,10 +407,65 @@ namespace LumberyardLauncher // Game Application (AzGameFramework) int gameArgC = mainInfo.m_argC; char** gameArgV = const_cast(mainInfo.m_argV); - int* argCParam = (gameArgC > 0) ? &gameArgC : nullptr; - char*** argVParam = (gameArgC > 0) ? &gameArgV : nullptr; + constexpr size_t MaxCommandArgsCount = 128; + using ArgumentContainer = AZStd::fixed_vector; + ArgumentContainer argContainer(gameArgV, gameArgV + gameArgC); - AzGameFramework::GameApplication gameApplication(argCParam, argVParam); + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + // Inject the Engine Path, Project Path and Project Name into the CommandLine parameters to the command line + // in order to be used in the Settings Registry + + // The command line overrides are stored in the following fixed strings + // until the ComponentApplication constructor can parse the command line parameters + FixedValueString projectNameOptionOverride; + FixedValueString projectPathOptionOverride; + FixedValueString enginePathOptionOverride; + + // Insert the project_name option to the front + const AZStd::string_view launcherProjectName = GetProjectName(); + if (!launcherProjectName.empty()) + { + const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name"; + projectNameOptionOverride = FixedValueString::format(R"(--regset="%s=%.*s")", + projectNameKey.c_str(), aznumeric_cast(launcherProjectName.size()), launcherProjectName.data()); + argContainer.emplace_back(projectNameOptionOverride.data()); + } + + // Non-host platforms cannot use the project path that is #defined within the launcher. + // In this case the the result of AZ::Utils::GetDefaultAppRoot is used instead + AZStd::string_view projectPath; +#if AZ_TRAIT_OS_IS_HOST_OS_PLATFORM + // Insert the project_path option to the front of the command line arguments + projectPath = GetProjectPath(); +#else + // Make sure the defaultAppRootPath variable is in scope long enough until the projectPath string_view is used below + AZStd::optional defaultAppRootPath = AZ::Utils::GetDefaultAppRootPath(); + if (defaultAppRootPath.has_value()) + { + projectPath = *defaultAppRootPath; + } +#endif + if (!projectPath.empty()) + { + const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + + "/project_path"; + projectPathOptionOverride = FixedValueString::format(R"(--regset="%s=%.*s")", + projectPathKey.c_str(), aznumeric_cast(projectPath.size()), projectPath.data()); + argContainer.emplace_back(projectPathOptionOverride.data()); + + // For non-host platforms set the engine root to be the project root + // Since the directories available during execution are limited on those platforms +#if !AZ_TRAIT_OS_IS_HOST_OS_PLATFORM + AZStd::string_view enginePath = projectPath; + const auto enginePathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + + "/engine_path"; + enginePathOptionOverride = FixedValueString ::format(R"(--regset="%s=%.*s")", + enginePathKey.c_str(), aznumeric_cast(enginePath.size()), enginePath.data()); + argContainer.emplace_back(enginePathOptionOverride.data()); +#endif + } + + AzGameFramework::GameApplication gameApplication(aznumeric_cast(argContainer.size()), argContainer.data()); // The settings registry has been created by the AZ::ComponentApplication constructor at this point auto settingsRegistry = AZ::SettingsRegistry::Get(); if (settingsRegistry == nullptr) @@ -466,9 +474,15 @@ namespace LumberyardLauncher return ReturnCode::ErrValidation; } - // Inject the ${LY_GAMEFOLDER} project name define that from the Launcher build target - // into the settings registry - AddProjectMetadataToSettingsRegistry(*settingsRegistry, *gameApplication.GetAzCommandLine()); + const AZStd::string_view buildTargetName = GetBuildTargetName(); + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(*settingsRegistry, buildTargetName); + + AZ_TracePrintf("Launcher", R"(Running project "%.*s.)" "\n" + R"(The project name value has been successfully set in the Settings Registry at key "%s/project_name)" + R"( for Launcher target "%.*s")" "\n", + aznumeric_cast(launcherProjectName.size()), launcherProjectName.data(), + AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey, + aznumeric_cast(buildTargetName.size()), buildTargetName.data()); AZ::SettingsRegistryInterface::FixedValueString pathToAssets; if (!settingsRegistry->Get(pathToAssets, AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) @@ -487,7 +501,7 @@ namespace LumberyardLauncher CryAllocatorsRAII cryAllocatorsRAII; - // System Init Params ("Legacy" Lumberyard) + // System Init Params ("Legacy" Open 3D Engine) SSystemInitParams systemInitParams; memset(&systemInitParams, 0, sizeof(SSystemInitParams)); diff --git a/Code/LauncherUnified/Launcher.h b/Code/LauncherUnified/Launcher.h index 49f6a33f3c..5186517898 100644 --- a/Code/LauncherUnified/Launcher.h +++ b/Code/LauncherUnified/Launcher.h @@ -18,7 +18,7 @@ struct IOutputPrintSink; -namespace LumberyardLauncher +namespace O3DELauncher { struct CryAllocatorsRAII { @@ -98,7 +98,7 @@ namespace LumberyardLauncher const char* GetReturnCodeString(ReturnCode code); - //! The main entry point for all lumberyard launchers + //! The main entry point for all O3DE launchers ReturnCode Run(const PlatformMainInfo& mainInfo = PlatformMainInfo()); ////////////////////////////////////////////////////////////////////////// diff --git a/Code/LauncherUnified/LauncherProject.cpp b/Code/LauncherUnified/LauncherProject.cpp index ebcabb3ffc..e7832cc99f 100644 --- a/Code/LauncherUnified/LauncherProject.cpp +++ b/Code/LauncherUnified/LauncherProject.cpp @@ -16,7 +16,7 @@ #include #endif // defined(AZ_MONOLITHIC_BUILD) -namespace LumberyardLauncher +namespace O3DELauncher { //! This file is to be added only to the ${project}.[Game|Server]Launcher build target //! This function returns the build system target name diff --git a/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp b/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp index 9eac3bb2b2..6455373e58 100644 --- a/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp +++ b/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp @@ -357,7 +357,7 @@ void android_main(android_app* appState) AZ::Android::Utils::ShowSplashScreen(); // run the Lumberyard application - using namespace LumberyardLauncher; + using namespace O3DELauncher; PlatformMainInfo mainInfo; mainInfo.m_updateResourceLimits = IncreaseResourceLimits; diff --git a/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.h b/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.h index 9aa7bb9945..7f2c04e687 100644 --- a/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.h +++ b/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.h @@ -12,7 +12,7 @@ #pragma once -namespace LumberyardLauncher +namespace O3DELauncher { const char* GetAppResourcePath(); } diff --git a/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.mm b/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.mm index 75d029fd4d..523871746e 100644 --- a/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.mm +++ b/Code/LauncherUnified/Platform/Common/Apple/Launcher_Apple.mm @@ -17,7 +17,7 @@ #include -namespace LumberyardLauncher +namespace O3DELauncher { const char* GetAppResourcePath() { diff --git a/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.cpp b/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.cpp index 475ea050e5..5d32bbae3a 100644 --- a/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.cpp +++ b/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.cpp @@ -70,7 +70,7 @@ namespace } -namespace LumberyardLauncher +namespace O3DELauncher { bool IncreaseResourceLimits() { diff --git a/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.h b/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.h index 20df31c9b1..aa9c21adc0 100644 --- a/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.h +++ b/Code/LauncherUnified/Platform/Common/UnixLike/Launcher_UnixLike.h @@ -13,7 +13,7 @@ #include -namespace LumberyardLauncher +namespace O3DELauncher { // Increase the core and stack limits bool IncreaseResourceLimits(); diff --git a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp index 15bcad695f..0c422877b1 100644 --- a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp +++ b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp @@ -87,7 +87,7 @@ int main(int argc, char** argv) InitStackTracer(); - using namespace LumberyardLauncher; + using namespace O3DELauncher; #if !defined(AZ_MONOLITHIC_BUILD) char exePath[AZ_MAX_PATH_LEN] = { 0 }; diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index 4977af99d0..1a491d66ad 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -11,7 +11,7 @@ */ #include -#include +#include #include <../Common/Apple/Launcher_Apple.h> #include <../Common/UnixLike/Launcher_UnixLike.h> @@ -20,7 +20,7 @@ int main(int argc, char* argv[]) { // TODO: Implement for Mac - return static_cast(LumberyardLauncher::ReturnCode::ErrUnitTestNotSupported); + return static_cast(O3DELauncher::ReturnCode::ErrUnitTestNotSupported); } #else @@ -32,8 +32,8 @@ int main(int argc, char* argv[]) // Create a memory pool, a custom AppKit application, and a custom AppKit application delegate. NSAutoreleasePool* autoreleasePool = [[NSAutoreleasePool alloc] init]; - [LumberyardApplication_Mac sharedApplication]; - [NSApp setDelegate: [[LumberyardApplicationDelegate_Mac alloc] init]]; + [O3DEApplication_Mac sharedApplication]; + [NSApp setDelegate: [[O3DEApplicationDelegate_Mac alloc] init]]; // Register some default application behaviours [[NSUserDefaults standardUserDefaults] registerDefaults: @@ -46,8 +46,8 @@ int main(int argc, char* argv[]) [NSApp finishLaunching]; [autoreleasePool release]; - // run the Lumberyard application - using namespace LumberyardLauncher; + // run the Open 3D Engine application + using namespace O3DELauncher; PlatformMainInfo mainInfo; mainInfo.m_updateResourceLimits = IncreaseResourceLimits; diff --git a/Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.mm b/Code/LauncherUnified/Platform/Mac/O3DEApplicationDelegate_Mac.mm similarity index 80% rename from Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.mm rename to Code/LauncherUnified/Platform/Mac/O3DEApplicationDelegate_Mac.mm index f7fe2a5867..981ea33283 100644 --- a/Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/O3DEApplicationDelegate_Mac.mm @@ -11,9 +11,9 @@ */ #include -#include +#include -@implementation LumberyardApplication_Mac +@implementation O3DEApplicationDelegate_Mac -@end // LumberyardApplication_Mac Implementation +@end // O3DEApplicationDelegate_Mac Implementation diff --git a/Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.h b/Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.h similarity index 71% rename from Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.h rename to Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.h index 99492c57cf..6dbfa032c1 100644 --- a/Code/LauncherUnified/Platform/Mac/LumberyardApplication_Mac.h +++ b/Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.h @@ -12,14 +12,14 @@ #include -@interface LumberyardApplication_Mac : NSApplication +@interface O3DEApplication_Mac : NSApplication { } -@end // LumberyardApplication_Mac Interface +@end // O3DEApplication_Mac Interface -@interface LumberyardApplicationDelegate_Mac : NSObject +@interface O3DEApplicationDelegate_Mac : NSObject { } -@end // LumberyardApplicationDelegate_Mac Interface +@end // O3DEApplicationDelegate_Mac Interface diff --git a/Code/LauncherUnified/Platform/Mac/LumberyardApplicationDelegate_Mac.mm b/Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.mm similarity index 79% rename from Code/LauncherUnified/Platform/Mac/LumberyardApplicationDelegate_Mac.mm rename to Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.mm index b671bd56a1..f202d01134 100644 --- a/Code/LauncherUnified/Platform/Mac/LumberyardApplicationDelegate_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/O3DEApplication_Mac.mm @@ -11,9 +11,9 @@ */ #include -#include +#include -@implementation LumberyardApplicationDelegate_Mac +@implementation O3DEApplication_Mac -@end // LumberyardApplicationDelegate_Mac Implementation +@end // O3DEApplication_Mac Implementation diff --git a/Code/LauncherUnified/Platform/Mac/platform_mac_files.cmake b/Code/LauncherUnified/Platform/Mac/platform_mac_files.cmake index 4da929db3b..15acfb550e 100644 --- a/Code/LauncherUnified/Platform/Mac/platform_mac_files.cmake +++ b/Code/LauncherUnified/Platform/Mac/platform_mac_files.cmake @@ -13,9 +13,9 @@ set(FILES Launcher_Mac.mm Launcher_Traits_Mac.h Launcher_Traits_Platform.h - LumberyardApplication_Mac.h - LumberyardApplication_Mac.mm - LumberyardApplicationDelegate_Mac.mm + O3DEApplication_Mac.h + O3DEApplication_Mac.mm + O3DEApplicationDelegate_Mac.mm ../Common/Apple/Launcher_Apple.mm ../Common/Apple/Launcher_Apple.h ../Common/UnixLike/Launcher_UnixLike.cpp diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index a9556d4490..b7f04a7e10 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -17,7 +17,7 @@ int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINS { InitRootDir(); - using namespace LumberyardLauncher; + using namespace O3DELauncher; PlatformMainInfo mainInfo; diff --git a/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake b/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake index fe5183e2f5..93a839ae47 100644 --- a/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake +++ b/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake @@ -29,7 +29,7 @@ endif() if(EXISTS ${ICON_FILE}) set(target_file ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.GameLauncher.rc) - configure_file(Platform/Windows/Launcher.rc.in + configure_file(${CMAKE_CURRENT_LIST_DIR}/Launcher.rc.in ${target_file} @ONLY ) diff --git a/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm b/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm index 2531f616a9..52c616fe64 100644 --- a/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm +++ b/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm @@ -18,8 +18,8 @@ int main(int argc, char* argv[]) NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; UIApplicationMain(argc, argv, - @"LumberyardApplication_iOS", - @"LumberyardApplicationDelegate_iOS"); + @"O3DEApplication_iOS", + @"O3DEApplicationDelegate_iOS"); [pool release]; return 0; } diff --git a/Code/LauncherUnified/Server.cpp b/Code/LauncherUnified/Server.cpp index 842356d2f4..207cf697a4 100644 --- a/Code/LauncherUnified/Server.cpp +++ b/Code/LauncherUnified/Server.cpp @@ -12,7 +12,7 @@ #include -namespace LumberyardLauncher +namespace O3DELauncher { bool WaitForAssetProcessorConnect() { diff --git a/Code/LauncherUnified/Tests/LauncherUnifiedTests.cpp b/Code/LauncherUnified/Tests/LauncherUnifiedTests.cpp index 204c12fcf5..35ea6b486d 100644 --- a/Code/LauncherUnified/Tests/LauncherUnifiedTests.cpp +++ b/Code/LauncherUnified/Tests/LauncherUnifiedTests.cpp @@ -26,7 +26,7 @@ protected: TEST_F(UnifiedLauncherTestFixture, PlatformMainInfoAddArgument_NoCommandLineFunctions_Success) { - LumberyardLauncher::PlatformMainInfo test; + O3DELauncher::PlatformMainInfo test; EXPECT_STREQ(test.m_commandLine, ""); EXPECT_EQ(test.m_argC, 0); @@ -34,7 +34,7 @@ TEST_F(UnifiedLauncherTestFixture, PlatformMainInfoAddArgument_NoCommandLineFunc TEST_F(UnifiedLauncherTestFixture, PlatformMainInfoAddArgument_ValidParams_Success) { - LumberyardLauncher::PlatformMainInfo test; + O3DELauncher::PlatformMainInfo test; const char* testArguments[] = { "-arg", "value1", "-arg2", "value2", "-argspace", "value one"}; for (const char* testArgument : testArguments) @@ -55,7 +55,7 @@ TEST_F(UnifiedLauncherTestFixture, PlatformMainInfoAddArgument_ValidParams_Succe TEST_F(UnifiedLauncherTestFixture, PlatformMainInfoCopyCommandLineArgCArgV_ValidParams_Success) { - LumberyardLauncher::PlatformMainInfo test; + O3DELauncher::PlatformMainInfo test; const char* constTestArguments[] = { "-arg", "value1", "-arg2", "value2", "-argspace", "value one" }; char** testArguments = const_cast(constTestArguments); diff --git a/Code/LauncherUnified/Tests/Test.cpp b/Code/LauncherUnified/Tests/Test.cpp index 86b13250a4..07529b2b0b 100644 --- a/Code/LauncherUnified/Tests/Test.cpp +++ b/Code/LauncherUnified/Tests/Test.cpp @@ -12,7 +12,7 @@ #include -namespace LumberyardLauncher +namespace O3DELauncher { bool WaitForAssetProcessorConnect() { diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake new file mode 100644 index 0000000000..b9abfe13b5 --- /dev/null +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -0,0 +1,190 @@ +# +# 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. +# + +# Launcher targets for a project need to be generated when configuring a project. +# When building the engine source, this file will be included by LauncherUnified's CMakeLists.txt +# When using an installed engine, this file will be included by the FindLauncherGenerator.cmake script +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJECTS) + # Computes the realpath to the project + # If the project_path is relative, it is evaluated relative to the ${LY_ROOT_FOLDER} + # Otherwise the the absolute project_path is returned with symlinks resolved + file(REAL_PATH ${project_path} project_real_path BASE_DIRECTORY ${LY_ROOT_FOLDER}) + ################################################################################ + # Monolithic game + ################################################################################ + if(LY_MONOLITHIC_GAME) + + # In the monolithic case, we need to register the gem modules, to do so we will generate a StaticModules.inl + # file from StaticModules.in + + get_property(game_gem_dependencies GLOBAL PROPERTY LY_DELAYED_DEPENDENCIES_${project_name}.GameLauncher) + + unset(extern_module_declarations) + unset(module_invocations) + + foreach(game_gem_dependency ${game_gem_dependencies}) + # To match the convention on how gems targets vs gem modules are named, we remove the "Gem::" from prefix + # and remove the ".Static" from the suffix + string(REGEX REPLACE "^Gem::" "Gem_" game_gem_dependency ${game_gem_dependency}) + string(REGEX REPLACE "^Project::" "Project_" game_gem_dependency ${game_gem_dependency}) + # Replace "." with "_" + string(REPLACE "." "_" game_gem_dependency ${game_gem_dependency}) + + string(APPEND extern_module_declarations "extern \"C\" AZ::Module* CreateModuleClass_${game_gem_dependency}();\n") + string(APPEND module_invocations " modulesOut.push_back(CreateModuleClass_${game_gem_dependency}());\n") + + endforeach() + + configure_file(StaticModules.in + ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.GameLauncher/Includes/StaticModules.inl + ) + + set(game_build_dependencies + ${game_gem_dependencies} + Legacy::CrySystem + Legacy::CryFont + Legacy::Cry3DEngine + ) + + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + get_property(server_gem_dependencies GLOBAL PROPERTY LY_DELAYED_DEPENDENCIES_${project_name}.ServerLauncher) + + unset(extern_module_declarations) + unset(module_invocations) + + foreach(server_gem_dependency ${server_gem_dependencies}) + # To match the convention on how gems targets vs gem modules are named, we remove the "Gem::" from prefix + # and remove the ".Static" from the suffix + string(REGEX REPLACE "^Gem::" "Gem_" server_gem_dependency ${server_gem_dependency}) + string(REGEX REPLACE "^Project::" "Project_" server_gem_dependency ${server_gem_dependency}) + # Replace "." with "_" + string(REPLACE "." "_" server_gem_dependency ${server_gem_dependency}) + + string(APPEND extern_module_declarations "extern \"C\" AZ::Module* CreateModuleClass_${server_gem_dependency}();\n") + string(APPEND module_invocations " modulesOut.push_back(CreateModuleClass_${server_gem_dependency}());\n") + + endforeach() + + configure_file(StaticModules.in + ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.ServerLauncher/Includes/StaticModules.inl + ) + + set(server_build_dependencies + ${game_gem_dependencies} + Legacy::CrySystem + Legacy::CryFont + Legacy::Cry3DEngine + ) + endif() + + else() + + set(game_runtime_dependencies + Legacy::CrySystem + Legacy::CryFont + Legacy::Cry3DEngine + ) + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED AND NOT LY_MONOLITHIC_GAME) # Only Atom is supported in monolithic builds + set(server_runtime_dependencies + Legacy::CryRenderNULL + ) + endif() + + endif() + + ################################################################################ + # Game + ################################################################################ + ly_add_target( + NAME ${project_name}.GameLauncher ${PAL_TRAIT_LAUNCHERUNIFIED_LAUNCHER_TYPE} + NAMESPACE AZ + FILES_CMAKE + ${CMAKE_CURRENT_LIST_DIR}/launcher_project_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_dir}/launcher_project_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + COMPILE_DEFINITIONS + PRIVATE + # Adds the name of the project/game + LY_PROJECT_NAME="${project_name}" + # Adds the project path supplied to CMake during configuration + # This is used as a fallback to launch the AssetProcessor + LY_PROJECT_CMAKE_PATH="${project_path}" + # Adds the ${project_name}_GameLauncher target as a define so for the Settings Registry to use + # when loading .setreg file specializations + # This is needed so that only gems for the project game launcher are loaded + LY_CMAKE_TARGET="${project_name}_GameLauncher" + INCLUDE_DIRECTORIES + PRIVATE + . + ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.GameLauncher/Includes # required for StaticModules.inl + BUILD_DEPENDENCIES + PRIVATE + AZ::Launcher.Static + AZ::Launcher.Game.Static + ${game_build_dependencies} + RUNTIME_DEPENDENCIES + ${game_runtime_dependencies} + ) + # Needs to be set manually after ly_add_target to prevent the default location overriding it + set_target_properties(${project_name}.GameLauncher + PROPERTIES + FOLDER ${project_name} + ) + + ################################################################################ + # Server + ################################################################################ + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + + get_property(server_projects GLOBAL PROPERTY LY_LAUNCHER_SERVER_PROJECTS) + if(${project_name} IN_LIST server_projects) + + ly_add_target( + NAME ${project_name}.ServerLauncher APPLICATION + NAMESPACE AZ + FILES_CMAKE + ${CMAKE_CURRENT_LIST_DIR}/launcher_project_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_dir}/launcher_project_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + COMPILE_DEFINITIONS + PRIVATE + # Adds the name of the project/game + LY_PROJECT_NAME="${project_name}" + # Adds the project path supplied to CMake during configuration + # This is used as a fallback to launch the AssetProcessor + LY_PROJECT_CMAKE_PATH="${project_path}" + # Adds the ${project_name}_ServerLauncher target as a define so for the Settings Registry to use + # when loading .setreg file specializations + # This is needed so that only gems for the project server launcher are loaded + LY_CMAKE_TARGET="${project_name}_ServerLauncher" + INCLUDE_DIRECTORIES + PRIVATE + . + ${CMAKE_CURRENT_BINARY_DIR}/${project_name}.ServerLauncher/Includes # required for StaticModules.inl + BUILD_DEPENDENCIES + PRIVATE + AZ::Launcher.Static + AZ::Launcher.Server.Static + ${server_build_dependencies} + RUNTIME_DEPENDENCIES + ${server_runtime_dependencies} + ) + # Needs to be set manually after ly_add_target to prevent the default location overriding it + set_target_properties(${project_name}.ServerLauncher + PROPERTIES + FOLDER ${project_name} + ) + endif() + + endif() + +endforeach() \ No newline at end of file diff --git a/Code/Sandbox/Editor/AboutDialog.cpp b/Code/Sandbox/Editor/AboutDialog.cpp index ac77eaed07..e1cd4c7bb0 100644 --- a/Code/Sandbox/Editor/AboutDialog.cpp +++ b/Code/Sandbox/Editor/AboutDialog.cpp @@ -55,7 +55,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_1_27.png")); m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - // Draw the Lumberyard logo from svg + // Draw the Open 3D Engine logo from svg m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); // Prevent re-sizing diff --git a/Code/Sandbox/Editor/AboutDialog.ui b/Code/Sandbox/Editor/AboutDialog.ui index 9a92770c52..0eb2881600 100644 --- a/Code/Sandbox/Editor/AboutDialog.ui +++ b/Code/Sandbox/Editor/AboutDialog.ui @@ -29,7 +29,7 @@ - About Lumberyard Editor + About Open 3D Engine Editor background-color: transparent @@ -92,7 +92,7 @@ - Lumberyard Editor + Open 3D Engine Editor Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop diff --git a/Code/Sandbox/Editor/Alembic/AlembicCompiler.cpp b/Code/Sandbox/Editor/Alembic/AlembicCompiler.cpp index 98013b0bb7..1fd5c1bca8 100644 --- a/Code/Sandbox/Editor/Alembic/AlembicCompiler.cpp +++ b/Code/Sandbox/Editor/Alembic/AlembicCompiler.cpp @@ -153,6 +153,6 @@ void CAlembicCompiler::AddSourceFileOpeners(const char* fullSourceFileName, [[ma } }; - openers.push_back({ "Lumberyard_AlembicCompiler", "Open In Alembic Compiler...", QIcon(), alembicCallback }); + openers.push_back({ "O3DE_AlembicCompiler", "Open In Alembic Compiler...", QIcon(), alembicCallback }); } } diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp index 4a21ae5833..0c99e63c47 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp @@ -283,7 +283,7 @@ void AzAssetBrowserRequestHandler::AddContextMenuActions(QWidget* caller, QMenu* // Add the "Open" menu item. // Note that source file openers are allowed to "veto" the showing of the "Open" menu if it is 100% known that they aren't openable! - // for example, custom data formats that are made by Lumberyard that can not have a program associated in the operating system to view them. + // for example, custom data formats that are made by Open 3D Engine that can not have a program associated in the operating system to view them. // If the only opener that can open that file has no m_opener, then it is not openable. SourceFileOpenerList openers; AssetBrowserInteractionNotificationBus::Broadcast(&AssetBrowserInteractionNotificationBus::Events::AddSourceFileOpeners, fullFilePath.c_str(), sourceID, openers); @@ -553,11 +553,11 @@ void AzAssetBrowserRequestHandler::AddSourceFileOpeners(const char* fullSourceFi if (AZStd::wildcard_match("*.lua", fullSourceFileName)) { AZStd::string fullName(fullSourceFileName); - // LUA files can be opened with the lumberyard LUA editor. + // LUA files can be opened with the O3DE LUA editor. openers.push_back( { - "Lumberyard_LUA_Editor", - "Open in Lumberyard LUA Editor...", + "O3DE_LUA_Editor", + "Open in Open 3D Engine LUA Editor...", QIcon(), [](const char* fullSourceFileNameInCallback, const AZ::Uuid& /*sourceUUID*/) { diff --git a/Code/Sandbox/Editor/CMakeLists.txt b/Code/Sandbox/Editor/CMakeLists.txt index 1e623c4144..726f7ac2c7 100644 --- a/Code/Sandbox/Editor/CMakeLists.txt +++ b/Code/Sandbox/Editor/CMakeLists.txt @@ -135,7 +135,7 @@ ly_add_source_properties( SOURCES CryEdit.cpp PROPERTY COMPILE_DEFINITIONS VALUES - LUMBERYARD_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR} + O3DE_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR} LY_BUILD=${LY_VERSION_BUILD_NUMBER} ${LY_PAL_TOOLS_DEFINES} ) diff --git a/Code/Sandbox/Editor/Controls/ColorGradientCtrl.cpp b/Code/Sandbox/Editor/Controls/ColorGradientCtrl.cpp index 17675bd072..edbf20531b 100644 --- a/Code/Sandbox/Editor/Controls/ColorGradientCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ColorGradientCtrl.cpp @@ -137,10 +137,6 @@ void CColorGradientCtrl::PointToTimeValue(QPoint point, float& time, ISplineInte float CColorGradientCtrl::XOfsToTime(int x) { return m_grid.ClientToWorld(QPoint(x, 0)).x; - - // m_fMinTime to m_fMaxTime time range. - float time = m_fMinTime + (float)((m_fMaxTime - m_fMinTime) * (x - m_rcGradient.left())) / m_rcGradient.width(); - return time; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp index cfca9cd19f..92610021b9 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -672,7 +672,6 @@ CReflectedVar * ReflectedPropertyControl::GetReflectedVarFromCallbackInstance(Az return reinterpret_cast(pNode->GetInstance(0)); else return GetReflectedVarFromCallbackInstance(pNode->GetParent()); - return nullptr; } diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index 91d0d0acef..1c9e7d90d2 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -918,15 +918,15 @@ QMenu* LevelEditorMenuHandler::CreateHelpMenu() QUrl docSearchUrl("https://docs.aws.amazon.com/search/doc-search.html"); QUrlQuery docSearchQuery; - QString lumberyardProductString = QUrl::toPercentEncoding("Amazon Lumberyard"); + QString o3deProductString = QUrl::toPercentEncoding("Open 3D Engine"); // The order of these QueryItems matters. wiki Search URL Formatting docSearchQuery.addQueryItem("searchPath", "documentation-product"); docSearchQuery.addQueryItem("searchQuery", text); - docSearchQuery.addQueryItem("this_doc_product", lumberyardProductString); + docSearchQuery.addQueryItem("this_doc_product", o3deProductString); docSearchQuery.addQueryItem("ref", "lye"); docSearchQuery.addQueryItem("ev", productVersionString); docSearchUrl.setQuery(docSearchQuery); - docSearchUrl.setFragment(QString("facet_doc_product=%1").arg(lumberyardProductString)); + docSearchUrl.setFragment(QString("facet_doc_product=%1").arg(o3deProductString)); QDesktopServices::openUrl(docSearchUrl); } lineEdit->clear(); @@ -948,8 +948,8 @@ QMenu* LevelEditorMenuHandler::CreateHelpMenu() // Glossary documentationMenu.AddAction(ID_DOCUMENTATION_GLOSSARY); - // Lumberyard Documentation - documentationMenu.AddAction(ID_DOCUMENTATION_LUMBERYARD); + // Open 3D Engine Documentation + documentationMenu.AddAction(ID_DOCUMENTATION_O3DE); // GameLift Documentation documentationMenu.AddAction(ID_DOCUMENTATION_GAMELIFT); @@ -980,7 +980,7 @@ QMenu* LevelEditorMenuHandler::CreateHelpMenu() // Report a Bug??? // auto reportBugMenu = helpMenu.Get()->addAction(tr("Report a Bug")); - // About Lumberyard + // About Open 3D Engine helpMenu.AddAction(ID_APP_ABOUT); // Welcome dialog diff --git a/Code/Sandbox/Editor/Core/QtEditorApplication.cpp b/Code/Sandbox/Editor/Core/QtEditorApplication.cpp index fa5c982fc8..7086990643 100644 --- a/Code/Sandbox/Editor/Core/QtEditorApplication.cpp +++ b/Code/Sandbox/Editor/Core/QtEditorApplication.cpp @@ -35,7 +35,7 @@ // AzQtComponents #include -#include +#include #include #include @@ -53,7 +53,7 @@ enum UninitializedFrequency = 9999, }; -Q_LOGGING_CATEGORY(InputDebugging, "lumberyard.editor.input") +Q_LOGGING_CATEGORY(InputDebugging, "o3de.editor.input") // internal, private namespace: namespace @@ -249,17 +249,17 @@ namespace Editor EditorQtApplication::EditorQtApplication(int& argc, char** argv) : QApplication(argc, argv) , m_inWinEventFilter(false) - , m_stylesheet(new AzQtComponents::LumberyardStylesheet(this)) + , m_stylesheet(new AzQtComponents::O3DEStylesheet(this)) , m_idleTimer(new QTimer(this)) { m_idleTimer->setInterval(UninitializedFrequency); - setWindowIcon(QIcon(":/Application/res/lyeditor.ico")); + setWindowIcon(QIcon(":/Application/res/o3de_editor.ico")); // set the default key store for our preferences: setOrganizationName("Amazon"); setOrganizationDomain("amazon.com"); - setApplicationName("Lumberyard"); + setApplicationName("Open 3D Engine"); connect(m_idleTimer, &QTimer::timeout, this, &EditorQtApplication::maybeProcessIdle); @@ -267,7 +267,7 @@ namespace Editor installEventFilter(this); // Disable our debugging input helpers by default - QLoggingCategory::setFilterRules(QStringLiteral("lumberyard.editor.input.*=false")); + QLoggingCategory::setFilterRules(QStringLiteral("o3de.editor.input.*=false")); // Initialize our stylesheet here to allow Gems to register stylesheets when their system components activate. AZ::IO::FixedMaxPath engineRootPath; diff --git a/Code/Sandbox/Editor/Core/QtEditorApplication.h b/Code/Sandbox/Editor/Core/QtEditorApplication.h index 37947bf777..8aa0dca038 100644 --- a/Code/Sandbox/Editor/Core/QtEditorApplication.h +++ b/Code/Sandbox/Editor/Core/QtEditorApplication.h @@ -32,7 +32,7 @@ class QByteArray; namespace AzQtComponents { - class LumberyardStylesheet; + class O3DEStylesheet; } enum EEditorNotifyEvent; @@ -118,7 +118,7 @@ namespace Editor void UninstallFilters(); void maybeProcessIdle(); - AzQtComponents::LumberyardStylesheet* m_stylesheet; + AzQtComponents::O3DEStylesheet* m_stylesheet; bool m_inWinEventFilter = false; diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index ee8dc989b4..6f311fe9ac 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -187,8 +187,8 @@ AZ_POP_DISABLE_WARNING #include -static const char lumberyardEditorClassName[] = "LumberyardEditorClass"; -static const char lumberyardApplicationName[] = "LumberyardApplication"; +static const char O3DEEditorClassName[] = "O3DEEditorClass"; +static const char O3DEApplicationName[] = "O3DEApplication"; static AZ::EnvironmentVariable inEditorBatchMode = nullptr; @@ -378,7 +378,7 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_DOCUMENTATION_GETTINGSTARTEDGUIDE, OnDocumentationGettingStartedGuide) ON_COMMAND(ID_DOCUMENTATION_TUTORIALS, OnDocumentationTutorials) ON_COMMAND(ID_DOCUMENTATION_GLOSSARY, OnDocumentationGlossary) - ON_COMMAND(ID_DOCUMENTATION_LUMBERYARD, OnDocumentationLumberyard) + ON_COMMAND(ID_DOCUMENTATION_O3DE, OnDocumentationO3DE) ON_COMMAND(ID_DOCUMENTATION_GAMELIFT, OnDocumentationGamelift) ON_COMMAND(ID_DOCUMENTATION_RELEASENOTES, OnDocumentationReleaseNotes) ON_COMMAND(ID_DOCUMENTATION_GAMEDEVBLOG, OnDocumentationGameDevBlog) @@ -639,7 +639,7 @@ public: QString appRootOverride; parser.addHelpOption(); parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.setApplicationDescription(QObject::tr("Amazon Lumberyard")); + parser.setApplicationDescription(QObject::tr("Open 3D Engine")); // nsDocumentRevisionDebugMode is an argument that the macOS system passed into an App bundle that is being debugged. // Need to include it here so that Qt argument parser does not error out. bool nsDocumentRevisionsDebugMode = false; @@ -758,13 +758,13 @@ struct SharedData // article Q141752 to locate the previous instance of the application. . BOOL CCryEditApp::FirstInstance(bool bForceNewInstance) { - QSystemSemaphore sem(QString(lumberyardApplicationName) + "_sem", 1); + QSystemSemaphore sem(QString(O3DEApplicationName) + "_sem", 1); sem.acquire(); { - FixDanglingSharedMemory(lumberyardEditorClassName); + FixDanglingSharedMemory(O3DEEditorClassName); } sem.release(); - m_mutexApplication = new QSharedMemory(lumberyardEditorClassName); + m_mutexApplication = new QSharedMemory(O3DEEditorClassName); if (!m_mutexApplication->create(sizeof(SharedData)) && !bForceNewInstance) { m_mutexApplication->attach(); @@ -789,7 +789,7 @@ BOOL CCryEditApp::FirstInstance(bool bForceNewInstance) sem.release(); QTimer* t = new QTimer(this); connect(t, &QTimer::timeout, this, [this]() { - QSystemSemaphore sem(QString(lumberyardApplicationName) + "_sem", 1); + QSystemSemaphore sem(QString(O3DEApplicationName) + "_sem", 1); sem.acquire(); SharedData* data = reinterpret_cast(m_mutexApplication->data()); QString preview = QString::fromLatin1(data->text); @@ -1018,9 +1018,9 @@ QString FormatRichTextCopyrightNotice() { // copyright symbol is HTML Entity = © QString copyrightHtmlSymbol = "©"; - QString copyrightString = QObject::tr("Lumberyard and related materials Copyright %1 %2 Amazon Web Services, Inc., its affiliates or licensors.
By accessing or using these materials, you agree to the terms of the AWS Customer Agreement."); + QString copyrightString = QObject::tr("Open 3D Engine and related materials Copyright %1 %2 Amazon Web Services, Inc., its affiliates or licensors.
By accessing or using these materials, you agree to the terms of the AWS Customer Agreement."); - return copyrightString.arg(copyrightHtmlSymbol).arg(LUMBERYARD_COPYRIGHT_YEAR); + return copyrightString.arg(copyrightHtmlSymbol).arg(O3DE_COPYRIGHT_YEAR); } ///////////////////////////////////////////////////////////////////////////// @@ -1180,8 +1180,8 @@ BOOL CCryEditApp::CheckIfAlreadyRunning() if (!m_bPreviewMode) { - FixDanglingSharedMemory(lumberyardApplicationName); - m_mutexApplication = new QSharedMemory(lumberyardApplicationName); + FixDanglingSharedMemory(O3DEApplicationName); + m_mutexApplication = new QSharedMemory(O3DEApplicationName); if (!m_mutexApplication->create(16)) { // Don't prompt the user in non-interactive export mode. Instead, default to allowing multiple instances to @@ -1189,7 +1189,7 @@ BOOL CCryEditApp::CheckIfAlreadyRunning() // NOTE: If you choose to do this, be sure to export *different* levels, since nothing prevents multiple runs // from trying to write to the same level at the same time. // If we're running interactively, let's ask and make sure the user actually intended to do this. - if (!m_bExportMode && QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Too many apps"), QObject::tr("There is already a Lumberyard application running\nDo you want to start another one?")) != QMessageBox::Yes) + if (!m_bExportMode && QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Too many apps"), QObject::tr("There is already an Open 3D Engine application running\nDo you want to start another one?")) != QMessageBox::Yes) { return false; } @@ -1798,7 +1798,7 @@ BOOL CCryEditApp::InitInstance() GetIEditor()->GetCommandManager()->RegisterAutoCommands(); GetIEditor()->AddUIEnums(); - mainWindowWrapper->enableSaveRestoreGeometry("amazon", "lumberyard", "mainWindowGeometry"); + mainWindowWrapper->enableSaveRestoreGeometry("amazon", "O3DE", "mainWindowGeometry"); m_pDocManager->OnFileNew(); if (IsInRegularEditorMode()) @@ -2090,7 +2090,7 @@ void CCryEditApp::OnAppAbout() aboutDlg.exec(); } -// App command to run the Welcome to Lumberyard dialog +// App command to run the Welcome to Open 3D Engine dialog void CCryEditApp::OnAppShowWelcomeScreen() { // This logic is a simplified version of the startup @@ -2182,7 +2182,7 @@ void CCryEditApp::OnDocumentationGlossary() QDesktopServices::openUrl(QUrl(webLink)); } -void CCryEditApp::OnDocumentationLumberyard() +void CCryEditApp::OnDocumentationO3DE() { QString webLink = tr("https://docs.aws.amazon.com/lumberyard/userguide"); QDesktopServices::openUrl(QUrl(webLink)); @@ -5399,7 +5399,7 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr, if (sTitleStr.isEmpty()) { - sTitleStr = QObject::tr("Lumberyard Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD); + sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD); } if (!sPreTitleStr.isEmpty()) diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 2ec5010df4..7480b34e5a 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -196,7 +196,7 @@ public: void OnUpdateShowWelcomeScreen(QAction* action); void OnDocumentationTutorials(); void OnDocumentationGlossary(); - void OnDocumentationLumberyard(); + void OnDocumentationO3DE(); void OnDocumentationGamelift(); void OnDocumentationReleaseNotes(); void OnDocumentationGameDevBlog(); diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp b/Code/Sandbox/Editor/DatabaseFrameWnd.cpp index e8936c9337..89843c8247 100644 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp +++ b/Code/Sandbox/Editor/DatabaseFrameWnd.cpp @@ -1336,7 +1336,7 @@ bool LibraryItemTreeModel::DoesGroupExist([[maybe_unused]] const QString& groupN QStringList LibraryItemTreeModel::mimeTypes() const { QStringList mimeTypes; - mimeTypes << QStringLiteral("application/x-lumberyard-libraryitems"); + mimeTypes << QStringLiteral("application/x-o3de-libraryitems"); return mimeTypes; } @@ -1412,9 +1412,9 @@ bool LibraryItemTreeModel::MoveItem(CBaseLibraryItem* item, const QModelIndex& t bool LibraryItemTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, const QModelIndex& index) { - if (data->hasFormat("application/x-lumberyard-libraryitems")) + if (data->hasFormat("application/x-o3de-libraryitems")) { - QByteArray array = data->data("application/x-lumberyard-libraryitems"); + QByteArray array = data->data("application/x-o3de-libraryitems"); QModelIndex targetParent = index; @@ -1474,7 +1474,7 @@ QMimeData* LibraryItemTreeModel::mimeData(const QModelIndexList& indexes) const } QMimeData* data = new QMimeData; - data->setData(QStringLiteral("application/x-lumberyard-libraryitems"), array); + data->setData(QStringLiteral("application/x-o3de-libraryitems"), array); return data; } diff --git a/Code/Sandbox/Editor/EditorCryEdit.rc b/Code/Sandbox/Editor/EditorCryEdit.rc index ce178d32ce..76d5d53476 100644 --- a/Code/Sandbox/Editor/EditorCryEdit.rc +++ b/Code/Sandbox/Editor/EditorCryEdit.rc @@ -1 +1 @@ -IDI_ICON1 ICON DISCARDABLE "res\\lyeditor.ico" \ No newline at end of file +IDI_ICON1 ICON DISCARDABLE "res\\o3de_editor.ico" \ No newline at end of file diff --git a/Code/Sandbox/Editor/EditorPanelUtils.cpp b/Code/Sandbox/Editor/EditorPanelUtils.cpp index 9757aeef70..06c7056a47 100644 --- a/Code/Sandbox/Editor/EditorPanelUtils.cpp +++ b/Code/Sandbox/Editor/EditorPanelUtils.cpp @@ -242,7 +242,7 @@ public: virtual bool HotKey_LoadExisting() override { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); QString group = "Hotkeys/"; HotKey_BuildDefaults(); @@ -278,7 +278,7 @@ public: virtual void HotKey_SaveCurrent() override { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); QString group = "Hotkeys/"; settings.remove("Hotkeys/"); settings.sync(); diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp index 4f960d5b74..b10d564031 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp @@ -101,10 +101,10 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_stylusMode, "Stylus Mode", "Stylus Mode for tablets and other pointing devices") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu.") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enablePrefabSystem, "Enable Prefab System (EXPERIMENTAL)", "Enable this option to preview Lumberyard's new prefab system. Enabling this setting removes slice support for level entities; you will need to restart the Editor for the change to take effect."); + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enablePrefabSystem, "Enable Prefab System (EXPERIMENTAL)", "Enable this option to preview Open 3D Engine's new prefab system. Enabling this setting removes slice support for level entities; you will need to restart the Editor for the change to take effect."); editContext->Class("Messaging", "") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Lumberyard at startup", "Show Welcome to Lumberyard at startup") + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showCircularDependencyError, "Show Error: Circular dependency", "Show an error message when adding a slice instance to the target slice would create a cyclic asset dependency. All other valid overrides will be saved even if this is turned off."); editContext->Class("Undo", "") diff --git a/Code/Sandbox/Editor/FeedbackDialog/FeedbackDialog.cpp b/Code/Sandbox/Editor/FeedbackDialog/FeedbackDialog.cpp index 90a0c55ca3..34206ba89c 100644 --- a/Code/Sandbox/Editor/FeedbackDialog/FeedbackDialog.cpp +++ b/Code/Sandbox/Editor/FeedbackDialog/FeedbackDialog.cpp @@ -21,10 +21,10 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING namespace { QString feedbackText = "

We love getting feedback from our customers.

" - "Feedback from our community helps us to constantly improve Lumberyard.

" + "Feedback from our community helps us to constantly improve Open 3D Engine.

" "In addition to using our forums and AWS support channels, you can always email us with your comments and suggestions at " - "lumberyard-feedback@amazon.com. " - "While we do not respond to everyone who submits feedback, we read everything and aspire to use your feedback to improve Lumberyard for everyone."; + "o3de-feedback@amazon.com. " + "While we do not respond to everyone who submits feedback, we read everything and aspire to use your feedback to improve Open 3D Engine for everyone."; } diff --git a/Code/Sandbox/Editor/GraphicsSettingsDialog.cpp b/Code/Sandbox/Editor/GraphicsSettingsDialog.cpp index a4e404bcfb..516e723d6b 100644 --- a/Code/Sandbox/Editor/GraphicsSettingsDialog.cpp +++ b/Code/Sandbox/Editor/GraphicsSettingsDialog.cpp @@ -151,7 +151,7 @@ GraphicsSettingsDialog::GraphicsSettingsDialog(QWidget* parent /* = nullptr */) m_ui->m_platformEntry->addItem(platform); } - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("GraphicsSettingsDialog"); if (settings.contains("Platform")) @@ -179,7 +179,7 @@ GraphicsSettingsDialog::GraphicsSettingsDialog(QWidget* parent /* = nullptr */) GraphicsSettingsDialog::~GraphicsSettingsDialog() { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("GraphicsSettingsDialog"); auto platformCheck = [this](AZStd::pair& stringConfigPair) { return stringConfigPair.second == m_currentPlatform; }; @@ -561,7 +561,7 @@ void GraphicsSettingsDialog::LoadPlatformConfigurations() setUpdatesEnabled(true); - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("GraphicsSettingsDialog"); settings.beginGroup("cvarGroup"); @@ -624,7 +624,7 @@ void GraphicsSettingsDialog::CleanUI() { setUpdatesEnabled(false); - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("GraphicsSettingsDialog"); settings.beginGroup("cvarGroup"); diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index f9878b2c8d..4a0a73c9ac 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -1432,10 +1432,10 @@ AZStd::string CEditorImpl::LoadProjectIdFromProjectData() QByteArray editorProjectNameUtf8 = editorProjectName.toUtf8(); AZ::Uuid id = AZ::Uuid::CreateName(editorProjectNameUtf8.constData()); - // The projects that Lumberyard ships with had their project IDs hand-generated based on the name of the level. + // The projects that Open 3D Engine ships with had their project IDs hand-generated based on the name of the level. // Therefore, if the UUID from the project name is the same as the UUID in the file, it's one of our projects // and we can therefore send the name back, making it easier for Metrics to determine which level it was. - // We are checking to see if this is a project we ship with Lumberyard, and therefore we can unobfuscate non-customer information. + // We are checking to see if this is a project we ship with Open 3D Engine, and therefore we can unobfuscate non-customer information. if (id != AZ::Uuid(projectId.data())) { return projectId; @@ -2097,7 +2097,7 @@ namespace void CEditorImpl::LoadSettings() { - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("Lumberyard")); + QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); settings.beginGroup(QStringLiteral("Editor")); settings.beginGroup(QStringLiteral("CoordSys")); @@ -2116,7 +2116,7 @@ void CEditorImpl::LoadSettings() void CEditorImpl::SaveSettings() const { - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("Lumberyard")); + QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); settings.beginGroup(QStringLiteral("Editor")); settings.beginGroup(QStringLiteral("CoordSys")); diff --git a/Code/Sandbox/Editor/KeyboardCustomizationSettings.cpp b/Code/Sandbox/Editor/KeyboardCustomizationSettings.cpp index ce76beae6f..279fd7a99f 100644 --- a/Code/Sandbox/Editor/KeyboardCustomizationSettings.cpp +++ b/Code/Sandbox/Editor/KeyboardCustomizationSettings.cpp @@ -109,7 +109,7 @@ void KeyboardCustomizationSettings::LoadDefaults() void KeyboardCustomizationSettings::Load() { - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("Lumberyard")); + QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); settings.beginGroup(QStringLiteral("Keyboard Shortcuts")); settings.beginGroup(m_group); @@ -156,7 +156,7 @@ void KeyboardCustomizationSettings::LoadFromSnapshot(const Snapshot& snapshot) void KeyboardCustomizationSettings::Save() { - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("Lumberyard")); + QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); settings.beginGroup(QStringLiteral("Keyboard Shortcuts")); settings.beginGroup(m_group); @@ -189,7 +189,7 @@ KeyboardCustomizationSettings::Snapshot KeyboardCustomizationSettings::CreateSna void KeyboardCustomizationSettings::ExportToFile(QWidget* parent) { - QString fileName = QFileDialog::getSaveFileName(parent, QObject::tr("Export Keyboard Shortcuts"), QStringLiteral("lumberyard.keys"), QObject::tr("Keyboard Settings (*.keys)")); + QString fileName = QFileDialog::getSaveFileName(parent, QObject::tr("Export Keyboard Shortcuts"), QStringLiteral("o3de.keys"), QObject::tr("Keyboard Settings (*.keys)")); if (fileName.isEmpty()) { return; @@ -205,7 +205,7 @@ void KeyboardCustomizationSettings::ExportToFile(QWidget* parent) QJsonObject store; store.insert("version", "1.0"); - store.insert("Content-Type", "application/x-lumberyard-sdk-keyboard-settings+json"); + store.insert("Content-Type", "application/x-o3de-sdk-keyboard-settings+json"); QJsonObject groups; for (auto instance = m_instances.constBegin(); instance != m_instances.constEnd(); instance++) @@ -262,7 +262,7 @@ void KeyboardCustomizationSettings::ImportFromFile(QWidget* parent) QJsonDocument imported(QJsonDocument::fromJson(rawData)); QJsonObject store = imported.object(); - if (store.value("Content-Type") != "application/x-lumberyard-sdk-keyboard-settings+json" || store.value("version") != "1.0") + if (store.value("Content-Type") != "application/x-o3de-sdk-keyboard-settings+json" || store.value("version") != "1.0") { QMessageBox::critical(parent, QObject::tr("Shortcut Import Error"), QObject::tr("\"%1\" doesn't appear to contain keyboard settings").arg(fileName)); return; diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp index ebf4b5d285..d30db3f5f3 100644 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp +++ b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp @@ -292,7 +292,7 @@ QLensFlareAtomicListModel::Item* QLensFlareAtomicListModel::ItemFromIndex(QModel QStringList QLensFlareAtomicListModel::mimeTypes() const { return { - QStringLiteral("application/x-lumberyard-flaretypes") + QStringLiteral("application/x-o3de-flaretypes") }; } @@ -308,7 +308,7 @@ QMimeData* QLensFlareAtomicListModel::mimeData(const QModelIndexList& indexes) c stream << static_cast(FlareTypeFromIndex(index)); } - data->setData(QStringLiteral("application/x-lumberyard-flaretypes"), encoded); + data->setData(QStringLiteral("application/x-o3de-flaretypes"), encoded); return data; } diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp index 81604703f5..763b5bf19b 100644 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp +++ b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp @@ -1173,7 +1173,7 @@ LensFlareItemTreeModel::LensFlareItemTreeModel(CDatabaseFrameWnd* pParent) QStringList LensFlareItemTreeModel::mimeTypes() const { QStringList mimeTypes = LibraryItemTreeModel::mimeTypes(); - mimeTypes << QStringLiteral("application/x-lumberyard-flaretypes"); + mimeTypes << QStringLiteral("application/x-o3de-flaretypes"); return mimeTypes; } @@ -1184,9 +1184,9 @@ bool LensFlareItemTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction return true; } - if (data->hasFormat(QStringLiteral("application/x-lumberyard-flaretypes"))) + if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) { - QByteArray encoded = data->data(QStringLiteral("application/x-lumberyard-flaretypes")); + QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); QDataStream stream(&encoded, QIODevice::ReadOnly); while (!stream.atEnd()) diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp index 019f9bd050..be687a5469 100644 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp +++ b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp @@ -737,8 +737,8 @@ bool LensFlareElementTreeModel::removeRows(int row, int count, const QModelIndex QStringList LensFlareElementTreeModel::mimeTypes() const { QStringList types; - types << QStringLiteral("application/x-lumberyard-flareelements"); - types << QStringLiteral("application/x-lumberyard-flaretypes"); + types << QStringLiteral("application/x-o3de-flareelements"); + types << QStringLiteral("application/x-o3de-flaretypes"); return types; } @@ -754,7 +754,7 @@ QMimeData* LensFlareElementTreeModel::mimeData(const QModelIndexList& indexes) c array.append(reinterpret_cast(&pElement), sizeof(CLensFlareElement*)); } - data->setData(QStringLiteral("application/x-lumberyard-flareelements"), array); + data->setData(QStringLiteral("application/x-o3de-flareelements"), array); return data; } @@ -1052,11 +1052,11 @@ bool LensFlareElementTreeModel::MoveElement(CLensFlareElement* pElement, int row bool LensFlareElementTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, int row, [[maybe_unused]] int column, const QModelIndex& parent) { - if (data->hasFormat(QStringLiteral("application/x-lumberyard-flaretypes"))) + if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) { // drop from atomic list - QByteArray encoded = data->data(QStringLiteral("application/x-lumberyard-flaretypes")); + QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); QDataStream stream(&encoded, QIODevice::ReadOnly); while (!stream.atEnd()) @@ -1070,9 +1070,9 @@ bool LensFlareElementTreeModel::dropMimeData(const QMimeData* data, [[maybe_unus return true; } - else if (data->hasFormat(QStringLiteral("application/x-lumberyard-flareelements"))) + else if (data->hasFormat(QStringLiteral("application/x-o3de-flareelements"))) { - QByteArray array = data->data("application/x-lumberyard-flareelements"); + QByteArray array = data->data("application/x-o3de-flareelements"); int count = array.size() / sizeof(CLensFlareElement*); auto ppElements = reinterpret_cast(array.data()); diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 2534fd8796..ab5e0cf559 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -406,7 +406,7 @@ MainWindow::MainWindow(QWidget* parent) , m_undoStateAdapter(new UndoStackStateAdapter(this)) , m_keyboardCustomization(nullptr) , m_activeView(nullptr) - , m_settings("amazon", "lumberyard") // TODO_KDAB: Replace with a central settings class + , m_settings("amazon", "O3DE") // TODO_KDAB: Replace with a central settings class , m_toolbarManager(new ToolbarManager(m_actionManager, this)) , m_assetImporterManager(new AssetImporterManager(this)) , m_levelEditorMenuHandler(new LevelEditorMenuHandler(this, m_viewPaneManager, m_settings)) @@ -1373,7 +1373,7 @@ void MainWindow::InitActions() am->AddAction(ID_DOCUMENTATION_GLOSSARY, tr("Glossary")) .SetReserved(); - am->AddAction(ID_DOCUMENTATION_LUMBERYARD, tr("Lumberyard Documentation")) + am->AddAction(ID_DOCUMENTATION_O3DE, tr("Open 3D Engine Documentation")) .SetReserved(); am->AddAction(ID_DOCUMENTATION_GAMELIFT, tr("GameLift Documentation")) .SetReserved(); @@ -1391,11 +1391,11 @@ void MainWindow::InitActions() am->AddAction(ID_DOCUMENTATION_FEEDBACK, tr("Give Us Feedback")) .SetReserved(); - am->AddAction(ID_APP_ABOUT, tr("&About Lumberyard")) + am->AddAction(ID_APP_ABOUT, tr("&About Open 3D Engine")) .SetStatusTip(tr("Display program information, version number and copyright")) .SetReserved(); am->AddAction(ID_APP_SHOW_WELCOME, tr("&Welcome")) - .SetStatusTip(tr("Show the Welcome to Lumberyard dialog box")) + .SetStatusTip(tr("Show the Welcome to Open 3D Engine dialog box")) .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateShowWelcomeScreen); // Editors Toolbar actions diff --git a/Code/Sandbox/Editor/MainWindow.qrc b/Code/Sandbox/Editor/MainWindow.qrc index b064460638..476159fbfd 100644 --- a/Code/Sandbox/Editor/MainWindow.qrc +++ b/Code/Sandbox/Editor/MainWindow.qrc @@ -75,7 +75,7 @@ res/source_control-warning_v2.svg - res/lyeditor.ico + res/o3de_editor.ico res/Eye.svg diff --git a/Code/Sandbox/Editor/Material/MaterialManager.cpp b/Code/Sandbox/Editor/Material/MaterialManager.cpp index e1daf65666..8f4269bb3e 100644 --- a/Code/Sandbox/Editor/Material/MaterialManager.cpp +++ b/Code/Sandbox/Editor/Material/MaterialManager.cpp @@ -665,7 +665,7 @@ void CMaterialManager::AddSourceFileOpeners(const char* fullSourceFileName, [[ma } }; - openers.push_back({ "Lumberyard_MaterialEditor", "Open In Material Editor...", QIcon(), materialCallback }); + openers.push_back({ "O3DE_MaterialEditor", "Open In Material Editor...", QIcon(), materialCallback }); } } diff --git a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp b/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp index 3c80f7c5e7..5de75a7c39 100644 --- a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp +++ b/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp @@ -393,8 +393,6 @@ namespace return EFTT_SPECULAR_2; } throw std::runtime_error("Invalid texture name."); - - return EFTT_MAX; } template diff --git a/Code/Sandbox/Editor/PluginManager.cpp b/Code/Sandbox/Editor/PluginManager.cpp index b618c6443f..252118bdd2 100644 --- a/Code/Sandbox/Editor/PluginManager.cpp +++ b/Code/Sandbox/Editor/PluginManager.cpp @@ -184,7 +184,7 @@ bool CPluginManager::LoadPlugins(const char* pPathWithMask) continue; } - // Lumberyard: + // Open 3D Engine: // Query the plugin settings, check for manual load... TPfnQueryPluginSettings pfnQuerySettings = reinterpret_cast(hPlugin->resolve("QueryPluginSettings")); diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index 9f0a858b40..a4bd2c1143 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -373,7 +373,7 @@ #define ID_DOCUMENTATION_GETTINGSTARTEDGUIDE 36023 #define ID_DOCUMENTATION_TUTORIALS 36024 #define ID_DOCUMENTATION_GLOSSARY 36025 -#define ID_DOCUMENTATION_LUMBERYARD 36026 +#define ID_DOCUMENTATION_O3DE 36026 #define ID_DOCUMENTATION_GAMELIFT 36027 #define ID_DOCUMENTATION_RELEASENOTES 36028 #define ID_DOCUMENTATION_GAMEDEVBLOG 36029 diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index cd95eef5ea..0f25b6ac6d 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -1090,7 +1090,7 @@ void SEditorSettings::ConvertPath(const AZStd::string_view sourcePath, AZStd::st { // This API accepts pipe-separated paths like "Category1|Category2|AttributeName" // But the SettingsManager requires 2 arguments, a Category like "Category1\Category2" and an attribute "AttributeName" - // The reason for the difference is to have this API be consistent with the path syntax in Lumberyard Python APIs. + // The reason for the difference is to have this API be consistent with the path syntax in Open 3D Engine Python APIs. // Find the last pipe separator ("|") in the path int lastSeparator = sourcePath.find_last_of("|"); diff --git a/Code/Sandbox/Editor/ShortcutDispatcher.h b/Code/Sandbox/Editor/ShortcutDispatcher.h index dbd3e40077..51a2eb0749 100644 --- a/Code/Sandbox/Editor/ShortcutDispatcher.h +++ b/Code/Sandbox/Editor/ShortcutDispatcher.h @@ -45,10 +45,10 @@ class QKeyEvent; More documentation on Qt shortcuts ------------------------------------------- - Here's some more detailed info regarding shortcuts in Qt. Not specific Lumberyard but + Here's some more detailed info regarding shortcuts in Qt. Not specific Open 3D Engine but useful as not explained in Qt docs much. - P.S.: The following text details the strategy used in an earlier Lumberyard version. Not sure which + P.S.: The following text details the strategy used in an earlier Open 3D Engine version. Not sure which shortcut context type it uses nowadays, but eitherway, the following text is educational, and all the traps still exist in current Qt (5.11). diff --git a/Code/Sandbox/Editor/StartupLogoDialog.cpp b/Code/Sandbox/Editor/StartupLogoDialog.cpp index 36cd223be7..38cf1bc5f6 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.cpp +++ b/Code/Sandbox/Editor/StartupLogoDialog.cpp @@ -48,14 +48,14 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_1_27.png")); m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - // Draw the Lumberyard logo from svg + // Draw the Open 3D Engine logo from svg m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); m_ui->m_TransparentConfidential->setObjectName("copyrightNotice"); m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText); m_ui->m_TransparentConfidential->setText(richTextCopyrightNotice); - setWindowTitle(tr("Starting Lumberyard Editor")); + setWindowTitle(tr("Starting Open 3D Engine Editor")); setStyleSheet( "CStartupLogoDialog > QLabel { background: transparent; color: 'white' }\ CStartupLogoDialog > QLabel#copyrightNotice { color: #AAAAAA; font-size: 9px; } "); diff --git a/Code/Sandbox/Editor/ThumbnailGenerator.cpp b/Code/Sandbox/Editor/ThumbnailGenerator.cpp index 2c6bb67960..c2f03a1944 100644 --- a/Code/Sandbox/Editor/ThumbnailGenerator.cpp +++ b/Code/Sandbox/Editor/ThumbnailGenerator.cpp @@ -193,45 +193,6 @@ void CThumbnailGenerator::GenerateForDirectory(const QString& path) //GetIEditor()->ShowConsole( false ); } -void CThumbnailGenerator::GenerateForFile(const QString& fileName) +void CThumbnailGenerator::GenerateForFile([[maybe_unused]] const QString& fileName) { - return; - - I3DEngine* engine = GetIEditor()->Get3DEngine(); - - int thumbSize = 128; - CImageEx image; - image.Allocate(thumbSize, thumbSize); - - char drive[_MAX_DRIVE]; - char fdir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char fext[_MAX_EXT]; - char bmpFile[1024]; - - _splitpath_s(fileName.toUtf8().data(), drive, fdir, fname, fext); - - _makepath_s(bmpFile, drive, fdir, fname, ".tmb"); - FileTimeType ft1, ft2; - GetThumbFileTime(fileName.toUtf8().data(), ft1); - GetThumbFileTime(bmpFile, ft2); - // Both cgf and bmp have same time stamp. - if (ThumbFileTimeIsEqual(ft1, ft2)) - { - return; - } - - _smart_ptr obj = engine->LoadStatObjAutoRef(fileName.toUtf8().data(), NULL, NULL, false); - if (obj) - { - assert(!"IStatObj::MakeObjectPicture does not exist anymore"); - // obj->MakeObjectPicture( (unsigned char*)image.GetData(),thumbSize ); - - CImageUtil::SaveBitmap(bmpFile, image); - SetThumbFileTime(bmpFile, ft1); -#if defined(AZ_PLATFORM_WINDOWS) - SetFileAttributes(bmpFile, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); -#endif - obj->Release(); - } } diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index 5a131b494a..4679f9cb6a 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -217,7 +217,7 @@ public: ToolbarManager::ToolbarManager(ActionManager* actionManager, MainWindow* mainWindow) : m_mainWindow(mainWindow) , m_actionManager(actionManager) - , m_settings("amazon", "lumberyard") + , m_settings("amazon", "O3DE") , m_expanderWatcher(new AmazonToolBarExpanderWatcher()) { // Note that we don't actually save/load from AmazonToolbar::List diff --git a/Code/Sandbox/Editor/TrackView/TrackViewDialog.cpp b/Code/Sandbox/Editor/TrackView/TrackViewDialog.cpp index 391c5bf7f4..a7a801e35a 100644 --- a/Code/Sandbox/Editor/TrackView/TrackViewDialog.cpp +++ b/Code/Sandbox/Editor/TrackView/TrackViewDialog.cpp @@ -1870,7 +1870,7 @@ void CTrackViewDialog::ReadMiscSettings() ////////////////////////////////////////////////////////////////////////// void CTrackViewDialog::SaveLayouts() { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("TrackView"); QByteArray stateData = this->saveState(); settings.setValue("layout", stateData); @@ -1886,7 +1886,7 @@ void CTrackViewDialog::SaveLayouts() ////////////////////////////////////////////////////////////////////////// void CTrackViewDialog::ReadLayouts() { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("TrackView"); setViewMode(static_cast(settings.value("lastViewMode").toInt())); diff --git a/Code/Sandbox/Editor/TrackView/TrackViewPythonFuncs.cpp b/Code/Sandbox/Editor/TrackView/TrackViewPythonFuncs.cpp index 35f1a74340..a031b0d930 100644 --- a/Code/Sandbox/Editor/TrackView/TrackViewPythonFuncs.cpp +++ b/Code/Sandbox/Editor/TrackView/TrackViewPythonFuncs.cpp @@ -481,8 +481,6 @@ namespace default: throw std::runtime_error("Unsupported key type"); } - - return AZStd::any(); } AZStd::any PyTrackViewGetKeyValue(const char* paramName, int trackIndex, int keyIndex, const char* nodeName, const char* parentDirectorName) diff --git a/Code/Sandbox/Editor/Util/ImageUtil.cpp b/Code/Sandbox/Editor/Util/ImageUtil.cpp index c451e9d18e..ae44833a75 100644 --- a/Code/Sandbox/Editor/Util/ImageUtil.cpp +++ b/Code/Sandbox/Editor/Util/ImageUtil.cpp @@ -288,8 +288,6 @@ bool CImageUtil::LoadImage(const QString& fileName, CImageEx& image, bool* pQual { return CImageUtil::Load(fileName, image); } - - return false; } ////////////////////////////////////////////////////////////////////////// @@ -320,8 +318,6 @@ bool CImageUtil::SaveImage(const QString& fileName, CImageEx& image) { return Save(fileName, image); } - - return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.cpp b/Code/Sandbox/Editor/ViewportTitleDlg.cpp index 305d4cdf6a..5d558eba98 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.cpp +++ b/Code/Sandbox/Editor/ViewportTitleDlg.cpp @@ -980,7 +980,7 @@ void CViewportTitleDlg::UpdateSearchOptionsText() void CViewportTitleDlg::LoadCustomPresets(const QString& section, const QString& keyName, QStringList& outCustompresets) { - QSettings settings("Amazon", "Lumberyard"); // Temporary solution until we have the global Settings class. + QSettings settings("Amazon", "O3DE"); // Temporary solution until we have the global Settings class. settings.beginGroup(section); outCustompresets = settings.value(keyName).toStringList(); settings.endGroup(); @@ -988,7 +988,7 @@ void CViewportTitleDlg::LoadCustomPresets(const QString& section, const QString& void CViewportTitleDlg::SaveCustomPresets(const QString& section, const QString& keyName, const QStringList& custompresets) { - QSettings settings("Amazon", "Lumberyard"); // Temporary solution until we have the global Settings class. + QSettings settings("Amazon", "O3DE"); // Temporary solution until we have the global Settings class. settings.beginGroup(section); settings.setValue(keyName, custompresets); settings.endGroup(); diff --git a/Code/Sandbox/Editor/WelcomeScreen/WelcomeScreenDialog.ui b/Code/Sandbox/Editor/WelcomeScreen/WelcomeScreenDialog.ui index e7adc1bade..be0d175a09 100644 --- a/Code/Sandbox/Editor/WelcomeScreen/WelcomeScreenDialog.ui +++ b/Code/Sandbox/Editor/WelcomeScreen/WelcomeScreenDialog.ui @@ -32,7 +32,7 @@ Qt::TabFocus
- Welcome to Lumberyard + Welcome to Open 3D Engine diff --git a/Code/Sandbox/Editor/res/lyeditor.ico b/Code/Sandbox/Editor/res/lyeditor.ico deleted file mode 100644 index 532ca4d19c..0000000000 --- a/Code/Sandbox/Editor/res/lyeditor.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c9a6ddbfc423c717a03dacab45e134166a1b06030b4caf418d0a6a69c2d82d2 -size 114333 diff --git a/Code/Sandbox/Editor/res/o3de_editor.ico b/Code/Sandbox/Editor/res/o3de_editor.ico new file mode 100644 index 0000000000..0680ceea19 --- /dev/null +++ b/Code/Sandbox/Editor/res/o3de_editor.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c042fce57915fc749abc7b37de765fd697c3c4d7de045a3d44805aa0ce29901a +size 107016 diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index 2710b7acf1..4a03dcd7dc 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -438,45 +438,8 @@ void CComponentEntityObject::OnEntityIconChanged(const AZ::Data::AssetId& entity SetupEntityIcon(); } -void CComponentEntityObject::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) +void CComponentEntityObject::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, [[maybe_unused]] AZ::EntityId newParent) { - return; - - if (m_parentingReentryGuard) // Ignore if action originated from Sandbox. - { - EditorActionScope parentChange(m_parentingReentryGuard); - - CComponentEntityObject* currentParent = static_cast(GetParent()); - - if (!currentParent && !newParent.IsValid()) - { - // No change in parent. - return; - } - - if (currentParent && currentParent->GetAssociatedEntityId() == newParent) - { - // No change in parent. - return; - } - - DetachThis(); - - if (newParent.IsValid()) - { - CComponentEntityObject* componentEntity = CComponentEntityObject::FindObjectForEntity(newParent); - - if (componentEntity) - { - // The action is originating from Sandbox, so ignore the return events. - EditorActionScope transformChange(m_transformReentryGuard); - - componentEntity->AttachChild(this); - } - } - - InvalidateTM(0); - } } void CComponentEntityObject::OnMeshCreated(const AZ::Data::Asset& asset) diff --git a/Code/Sandbox/Plugins/EditorAssetImporter/AssetBrowserContextProvider.cpp b/Code/Sandbox/Plugins/EditorAssetImporter/AssetBrowserContextProvider.cpp index 5713e14a36..0e94ff80cf 100644 --- a/Code/Sandbox/Plugins/EditorAssetImporter/AssetBrowserContextProvider.cpp +++ b/Code/Sandbox/Plugins/EditorAssetImporter/AssetBrowserContextProvider.cpp @@ -75,7 +75,7 @@ namespace AZ return; } - openers.push_back({ "Lumberyard_FBX_Settings_Edit", "Edit Settings...", QIcon(), [](const char* fullSourceFileNameInCallback, const AZ::Uuid& /*sourceUUID*/) + openers.push_back({ "O3DE_FBX_Settings_Edit", "Edit Settings...", QIcon(), [](const char* fullSourceFileNameInCallback, const AZ::Uuid& /*sourceUUID*/) { AZStd::string sourceName(fullSourceFileNameInCallback); // because the below call absolutely requires a AZStd::string. AssetImporterPlugin::GetInstance()->EditImportSettings(sourceName); diff --git a/Code/Sandbox/Plugins/EditorAssetImporter/AssetImporterPlugin.cpp b/Code/Sandbox/Plugins/EditorAssetImporter/AssetImporterPlugin.cpp index dbe3b343a0..c04f81f50c 100644 --- a/Code/Sandbox/Plugins/EditorAssetImporter/AssetImporterPlugin.cpp +++ b/Code/Sandbox/Plugins/EditorAssetImporter/AssetImporterPlugin.cpp @@ -88,6 +88,12 @@ AZStd::unique_ptr AssetImporterPlugin::LoadSceneLibrary void AssetImporterPlugin::EditImportSettings(const AZStd::string& sourceFilePath) { const QtViewPane* assetImporterPane = GetIEditor()->OpenView(m_toolName.c_str()); + + if(!assetImporterPane) + { + return; + } + AssetImporterWindow* assetImporterWindow = qobject_cast(assetImporterPane->Widget()); if (!assetImporterWindow) { diff --git a/Code/Sandbox/Plugins/EditorCommon/EditorCommon.rc b/Code/Sandbox/Plugins/EditorCommon/EditorCommon.rc index 1e1917e8c2f5f0bbc4bfc5076444762dc73015fc..715fc2952c60834133b0468573b2657f18e7b88b 100644 GIT binary patch delta 73 ycmaDM{6lyHAFH%KLjgl7LmqWa?%`)@o+F3f6O2G6Dcg#1AGetCamera()->SetApertureMode(FbxCamera::eVertical); entityData.keyValue = aznumeric_cast(pNode->GetCamera()->ComputeFieldOfView(entityData.keyValue)); } @@ -821,7 +821,7 @@ bool CFBXExporter::ImportFromFile(const char* filename, Export::IData* pData) return false; } - // record the original axis system used in the import file and then convert the file to Lumberyard's coord system, + // record the original axis system used in the import file and then convert the file to Open 3D Engine's coord system, // which matches Max's (Z-Up, negative Y-forward cameras) int upSign = 1; FbxAxisSystem importFileAxisSystem = pFBXScene->GetGlobalSettings().GetAxisSystem(); @@ -877,13 +877,13 @@ bool CFBXExporter::ImportFromFile(const char* filename, Export::IData* pData) if (pCamera) { - // Converts Y-Up, -Z-forward cameras to Lumberyards Z-Up, Y-forward cameras + // Converts Y-Up, -Z-forward cameras to Open 3D Engine Z-Up, Y-forward cameras // It is needed regardless of the scene up vector pNode->SetPostRotation(FbxNode::eSourcePivot, s_POST_ROTATION_FOR_ZFORWARD_CAMERAS); } else { - // Objects from a Y-Up scene (i.e. not cameras). 'undo' the extra transform that the Lumberyard Tool + // Objects from a Y-Up scene (i.e. not cameras). 'undo' the extra transform that the Open 3D Engine Tool // bakes in to .cgf files from YUp scenes. pNode->SetPostRotation(FbxNode::eSourcePivot, s_POST_ROTATION_FOR_YUP_OBJECTS); } diff --git a/Code/Sandbox/Plugins/ProjectSettingsTool/PlatformSettings_Ios.h b/Code/Sandbox/Plugins/ProjectSettingsTool/PlatformSettings_Ios.h index 38187414e1..79243d5208 100644 --- a/Code/Sandbox/Plugins/ProjectSettingsTool/PlatformSettings_Ios.h +++ b/Code/Sandbox/Plugins/ProjectSettingsTool/PlatformSettings_Ios.h @@ -131,7 +131,7 @@ namespace ProjectSettingsTool : m_bundleName("") , m_bundleDisplayName("") , m_executableName("") - , m_bundleIdentifier("com.amazon.lumberyard.UnknownProject") + , m_bundleIdentifier("com.amazon.o3de.UnknownProject") , m_versionName("1.0.0") , m_versionNumber("1.0.0") , m_developmentRegion("en_US") diff --git a/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSNativeSDKInit.h b/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSNativeSDKInit.h index 1203c77b21..3c7baab241 100644 --- a/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSNativeSDKInit.h +++ b/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSNativeSDKInit.h @@ -28,7 +28,7 @@ AZ_POP_DISABLE_WARNING namespace AWSNativeSDKInit { - // Entry point for Lumberyard managing the AWSNativeSDK's initialization and shutdown requirements + // Entry point for Open 3D Engine managing the AWSNativeSDK's initialization and shutdown requirements // Use an AZ::Environment variable to enforce only one init and shutdown class InitializationManager { @@ -38,7 +38,7 @@ namespace AWSNativeSDKInit InitializationManager(); ~InitializationManager(); - // Call to guarantee that the API is initialized with proper Lumberyard settings. + // Call to guarantee that the API is initialized with proper Open 3D Engine settings. // It's fine to call this from every module which needs to use the NativeSDK // Creates a static shared pointer using the AZ EnvironmentVariable system. // This will prevent a the AWS SDK from going through the shutdown routine until all references are gone, or diff --git a/Code/Tools/AssetBundler/assetbundlerbatch_exe_files.cmake b/Code/Tools/AssetBundler/assetbundlerbatch_exe_files.cmake index 3be5b791f4..be746ff05c 100644 --- a/Code/Tools/AssetBundler/assetbundlerbatch_exe_files.cmake +++ b/Code/Tools/AssetBundler/assetbundlerbatch_exe_files.cmake @@ -11,4 +11,5 @@ set(FILES source/main.cpp + source/AssetBundlerBatch.rc ) diff --git a/Code/Tools/AssetBundler/source/AssetBundlerBatch.ico b/Code/Tools/AssetBundler/source/AssetBundlerBatch.ico new file mode 100644 index 0000000000..51eae6ce2b --- /dev/null +++ b/Code/Tools/AssetBundler/source/AssetBundlerBatch.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5b63adf64ca5b940bb9ff35a198e41f956e248b0c9bff349d36885a8e6bfcf +size 103824 diff --git a/Code/Tools/AssetBundler/source/AssetBundlerBatch.rc b/Code/Tools/AssetBundler/source/AssetBundlerBatch.rc new file mode 100644 index 0000000000..32d4affb51 --- /dev/null +++ b/Code/Tools/AssetBundler/source/AssetBundlerBatch.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "AssetBundlerBatch.ico" diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp index 4c551463f5..bb4fee2ceb 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp @@ -2619,9 +2619,9 @@ namespace AssetBundler AZ_Printf(AppWindowName, "\n"); AZ_Printf(AppWindowName, "Some args in this tool take paths as arguments, and there are two main types:\n"); AZ_Printf(AppWindowName, " \"path\" - This refers to an Engine-Root-Relative path.\n"); - AZ_Printf(AppWindowName, " - Example: \"C:\\Lumberyard\\dev\\AutomatedTesting\\test.txt\" can be represented as \"AutomatedTesting\\test.txt\".\n"); + AZ_Printf(AppWindowName, " - Example: \"C:\\O3DE\\dev\\SamplesProject\\test.txt\" can be represented as \"SamplesProject\\test.txt\".\n"); AZ_Printf(AppWindowName, " \"cache path\" - This refers to a Cache-Relative path.\n"); - AZ_Printf(AppWindowName, " - Example: \"C:\\Lumberyard\\dev\\AutomatedTesting\\Cache\\pc\\animations\\skeletonlist.xml\" is represented as \"animations\\skeletonlist.xml\".\n"); + AZ_Printf(AppWindowName, " - Example: \"C:\\O3DE\\dev\\Cache\\SamplesProject\\pc\\samplesproject\\animations\\skeletonlist.xml\" is represented as \"animations\\skeletonlist.xml\".\n"); AZ_Printf(AppWindowName, "\n"); OutputHelpSeeds(); @@ -2678,7 +2678,7 @@ namespace AssetBundler AZ_Printf(AppWindowName, " --%-25s-The specified files and all dependencies will be ignored when generating the Asset List file.\n", SkipArg); AZ_Printf(AppWindowName, "%-31s---Takes in a comma-separated list of either: cache paths to pre-processed assets, or wildcard patterns.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Automatically include all default Seed List files in generated Asset List File.\n", AddDefaultSeedListFilesFlag); - AZ_Printf(AppWindowName, "%-31s---This will include Seed List files for the Lumberyard Engine and all enabled Gems.\n", ""); + AZ_Printf(AppWindowName, "%-31s---This will include Seed List files for the Open 3D Engine Engine and all enabled Gems.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Specifies the platform(s) to generate an Asset List file for.\n", PlatformArg); AZ_Printf(AppWindowName, "%-31s---Requires an existing cache of assets for the input platform(s).\n", ""); AZ_Printf(AppWindowName, "%-31s---Defaults to all enabled platforms. Platforms can be changed by modifying AssetProcessorPlatformConfig.setreg.\n", ""); @@ -2757,7 +2757,7 @@ namespace AssetBundler AZ_Printf(AppWindowName, " --%-25s-[Required] Specifies the Bundle Settings file to operate on by path. Must include (.%s) file extension.\n", BundleSettingsFileArg, AssetBundleSettings::GetBundleSettingsFileExtension()); AZ_Printf(AppWindowName, " --%-25s-Sets the Asset List file to use for Bundle generation. Must include (.%s) file extension.\n", AssetListFileArg, AssetSeedManager::GetAssetListFileExtension()); AZ_Printf(AppWindowName, " --%-25s-Sets the path where generated Bundles will be stored. Must include (.%s) file extension.\n", OutputBundlePathArg, AssetBundleSettings::GetBundleFileExtension()); - AZ_Printf(AppWindowName, " --%-25s-Determines which version of Lumberyard Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); + AZ_Printf(AppWindowName, " --%-25s-Determines which version of Open 3D Engine Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); AZ_Printf(AppWindowName, " --%-25s-Sets the maximum size for a single Bundle (in MB). Default size is (%i MB).\n", MaxBundleSizeArg, AssetBundleSettings::GetMaxBundleSizeInMB()); AZ_Printf(AppWindowName, "%-31s---Bundles larger than this limit will be divided into a series of smaller Bundles and named accordingly.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Specifies the platform(s) referenced by all Bundle Settings operations.\n", PlatformArg); @@ -2774,7 +2774,7 @@ namespace AssetBundler AZ_Printf(AppWindowName, "%-31s---If any other args are specified, they will override the values stored inside this file.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Sets the Asset List files to use for Bundle generation. Must include (.%s) file extension.\n", AssetListFileArg, AssetSeedManager::GetAssetListFileExtension()); AZ_Printf(AppWindowName, " --%-25s-Sets the paths where generated Bundles will be stored. Must include (.%s) file extension.\n", OutputBundlePathArg, AssetBundleSettings::GetBundleFileExtension()); - AZ_Printf(AppWindowName, " --%-25s-Determines which versions of Lumberyard Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); + AZ_Printf(AppWindowName, " --%-25s-Determines which versions of Open 3D Engine Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); AZ_Printf(AppWindowName, " --%-25s-Sets the maximum size for Bundles (in MB). Default size is (%i MB).\n", MaxBundleSizeArg, AssetBundleSettings::GetMaxBundleSizeInMB()); AZ_Printf(AppWindowName, "%-31s---Bundles larger than this limit will be divided into a series of smaller Bundles and named accordingly.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Specifies the platform(s) that will be referenced when generating Bundles.\n", PlatformArg); @@ -2791,7 +2791,7 @@ namespace AssetBundler AZ_Printf(AppWindowName, "%-31s---Takes in a cache path to a pre-processed asset. A cache path is a path relative to \"ProjectPath\\Cache\\platform\\\"\n", ""); AZ_Printf(AppWindowName, " --%-25s-Specifies the Bundle Settings file to operate on by path. Must include (.%s) file extension.\n", BundleSettingsFileArg, AssetBundleSettings::GetBundleSettingsFileExtension()); AZ_Printf(AppWindowName, " --%-25s-Sets the path where generated Bundles will be stored. Must include (.%s) file extension.\n", OutputBundlePathArg, AssetBundleSettings::GetBundleFileExtension()); - AZ_Printf(AppWindowName, " --%-25s-Determines which version of Lumberyard Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); + AZ_Printf(AppWindowName, " --%-25s-Determines which version of Open 3D Engine Bundles to generate. Current version is (%i).\n", BundleVersionArg, AzFramework::AssetBundleManifest::CurrentBundleVersion); AZ_Printf(AppWindowName, " --%-25s-Sets the maximum size for a single Bundle (in MB). Default size is (%i MB).\n", MaxBundleSizeArg, AssetBundleSettings::GetMaxBundleSizeInMB()); AZ_Printf(AppWindowName, "%-31s---Bundles larger than this limit will be divided into a series of smaller Bundles and named accordingly.\n", ""); AZ_Printf(AppWindowName, " --%-25s-Specifies the platform(s) that will be referenced when generating Bundles.\n", PlatformArg); diff --git a/Code/Tools/AssetBundler/source/utils/utils.cpp b/Code/Tools/AssetBundler/source/utils/utils.cpp index 35c46f4227..b1595f7dd8 100644 --- a/Code/Tools/AssetBundler/source/utils/utils.cpp +++ b/Code/Tools/AssetBundler/source/utils/utils.cpp @@ -485,7 +485,7 @@ namespace AssetBundler return AZ::Failure(AZStd::string::format( "Unable to locate the Project Cache path from Settings Registry at key %s." - " Please run the Lumberyard Asset Processor to generate a Cache and build assets.", + " Please run the Open 3D Engine Asset Processor to generate a Cache and build assets.", AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder)); } @@ -503,7 +503,7 @@ namespace AssetBundler if (tempPlatformList.empty()) { - return AZ::Failure(AZStd::string("Cache is empty. Please run the Lumberyard Asset Processor to generate a Cache and build assets.")); + return AZ::Failure(AZStd::string("Cache is empty. Please run the Open 3D Engine Asset Processor to generate a Cache and build assets.")); } for (const QString& platform : tempPlatformList) @@ -520,7 +520,7 @@ namespace AssetBundler if (assetCatalogFilePath.empty()) { return AZ::Failure(AZStd::string::format( - "Unable to retrieve cache platform path from Settings Registry at key: %s. Please run the Lumberyard Asset Processor to generate platform-specific cache folders and build assets.", + "Unable to retrieve cache platform path from Settings Registry at key: %s. Please run the Open 3D Engine Asset Processor to generate platform-specific cache folders and build assets.", AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder)); } diff --git a/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.ico b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.ico new file mode 100644 index 0000000000..78908a8b37 --- /dev/null +++ b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bb66cade9f4f42c6db0a4e43f0c2be87b185d788353330c4165ace4f8c44289 +size 107101 diff --git a/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.rc b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.rc new file mode 100644 index 0000000000..fdc805bf52 --- /dev/null +++ b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilder.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "AssetBuilder.ico" diff --git a/Code/Tools/AssetProcessor/AssetBuilder/asset_builder_files.cmake b/Code/Tools/AssetProcessor/AssetBuilder/asset_builder_files.cmake index 2ce16735af..32a6097d89 100644 --- a/Code/Tools/AssetProcessor/AssetBuilder/asset_builder_files.cmake +++ b/Code/Tools/AssetProcessor/AssetBuilder/asset_builder_files.cmake @@ -19,4 +19,5 @@ set(FILES AssetBuilderInfo.cpp TraceMessageHook.h TraceMessageHook.cpp + AssetBuilder.rc ) \ No newline at end of file diff --git a/Code/Tools/AssetProcessor/Platform/Linux/AssetProcessor_Traits_Linux.h b/Code/Tools/AssetProcessor/Platform/Linux/AssetProcessor_Traits_Linux.h index 09c255b487..3fd8d357e6 100644 --- a/Code/Tools/AssetProcessor/Platform/Linux/AssetProcessor_Traits_Linux.h +++ b/Code/Tools/AssetProcessor/Platform/Linux/AssetProcessor_Traits_Linux.h @@ -11,5 +11,5 @@ */ #pragma once -#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "/rc" -#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM true \ No newline at end of file +#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "rc" +#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM true diff --git a/Code/Tools/AssetProcessor/Platform/Mac/AssetProcessor_Traits_Mac.h b/Code/Tools/AssetProcessor/Platform/Mac/AssetProcessor_Traits_Mac.h index b6803bd9c4..1aa7306fda 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/AssetProcessor_Traits_Mac.h +++ b/Code/Tools/AssetProcessor/Platform/Mac/AssetProcessor_Traits_Mac.h @@ -11,5 +11,5 @@ */ #pragma once -#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "/rc" -#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM false \ No newline at end of file +#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "rc" +#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM false diff --git a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor.rc b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor.rc index 94fb086867..a87b910e24 100644 --- a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor.rc +++ b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor.rc @@ -1 +1 @@ -IDI_ICON1 ICON DISCARDABLE "../../native/ui/style/lyassetprocessor.ico" +IDI_ICON1 ICON DISCARDABLE "../../native/ui/style/o3de_assetprocessor.ico" diff --git a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.ico b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.ico new file mode 100644 index 0000000000..b0df71b8d6 --- /dev/null +++ b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c05ee28bfca3a0411afd13fb2b5fcecd5ca9b5e74627e5f6837d3c9cea25b715 +size 107497 diff --git a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.rc b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.rc new file mode 100644 index 0000000000..0dfb493fb2 --- /dev/null +++ b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessorBatch.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "AssetProcessorBatch.ico" diff --git a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor_Traits_Windows.h b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor_Traits_Windows.h index 929f955f3c..3c0bcfe52d 100644 --- a/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor_Traits_Windows.h +++ b/Code/Tools/AssetProcessor/Platform/Windows/AssetProcessor_Traits_Windows.h @@ -11,5 +11,5 @@ */ #pragma once -#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "/rc.exe" -#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM false \ No newline at end of file +#define ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH "rc.exe" +#define ASSETPROCESSOR_TRAIT_CASE_SENSITIVE_FILESYSTEM false diff --git a/Code/Tools/AssetProcessor/assetprocessor_batch_files.cmake b/Code/Tools/AssetProcessor/assetprocessor_batch_files.cmake index 1089f6dda4..dfc2832e18 100644 --- a/Code/Tools/AssetProcessor/assetprocessor_batch_files.cmake +++ b/Code/Tools/AssetProcessor/assetprocessor_batch_files.cmake @@ -12,4 +12,5 @@ set(FILES native/main_batch.cpp native/AssetProcessorBatchBuildTarget.cpp + Platform/Windows/AssetProcessorBatch.rc ) diff --git a/Code/Tools/AssetProcessor/native/AssetManager/FileStateCache.cpp b/Code/Tools/AssetProcessor/native/AssetManager/FileStateCache.cpp index 7bd5f58b69..b1384df0c2 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/FileStateCache.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/FileStateCache.cpp @@ -149,7 +149,10 @@ namespace AssetProcessor { return normalized.toLower(); } - return normalized; + else + { + return normalized; + } } void FileStateCache::AddOrUpdateFileInternal(QFileInfo fileInfo) diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp index a8e03bd3ac..d403b97359 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp @@ -476,7 +476,9 @@ namespace AssetProcessor // CheckDeletedSourceFile actually expects the database name as the second value // iter.key is the full path normalized. iter.value is the database path. // we need the relative path too, which involves removing the scan folder outputprefix it present: - CheckDeletedSourceFile(iter.key(), iter.value().m_sourceRelativeToWatchFolder, iter.value().m_sourceDatabaseName); + CheckDeletedSourceFile( + iter.key(), iter.value().m_sourceRelativeToWatchFolder, iter.value().m_sourceDatabaseName, + AZStd::chrono::system_clock::now()); } // we want to remove any left over scan folders from the database only after @@ -1524,7 +1526,7 @@ namespace AssetProcessor // even if the entry already exists, // overwrite the entry here, so if you modify, then delete it, its the latest action thats always on the list. - m_filesToExamine[normalizedFilePath] = FileEntry(normalizedFilePath, source.m_isDelete, source.m_isFromScanner); + m_filesToExamine[normalizedFilePath] = FileEntry(normalizedFilePath, source.m_isDelete, source.m_isFromScanner, source.m_initialProcessTime); // this block of code adds anything which DEPENDS ON the file that was changed, back into the queue so that files // that depend on it also re-analyze in case they need rebuilding. However, files that are deleted will be added @@ -1773,40 +1775,31 @@ namespace AssetProcessor return successfullyRemoved; } - void AssetProcessorManager::CheckDeletedSourceFile(QString normalizedPath, QString relativePath, QString databaseSourceFile) + void AssetProcessorManager::CheckDeletedSourceFile(QString normalizedPath, QString relativePath, QString databaseSourceFile, + AZStd::chrono::system_clock::time_point initialProcessTime) { // getting here means an input asset has been deleted // and no overrides exist for it. // we must delete its products. using namespace AzToolsFramework::AssetDatabase; + + // If we fail to delete a product, the deletion event gets requeued + // To avoid retrying forever, we keep track of the time of the first deletion failure and only retry + // if less than this amount of time has passed. + constexpr int MaxRetryPeriodMS = 500; + AZStd::chrono::duration duration = AZStd::chrono::system_clock::now() - initialProcessTime; - // Check if this file causes any file types to be re-evaluated - CheckMetaDataRealFiles(normalizedPath); - - // when a source is deleted, we also have to queue anything that depended on it, for re-processing: - SourceFileDependencyEntryContainer results; - m_stateData->GetSourceFileDependenciesByDependsOnSource(databaseSourceFile, SourceFileDependencyEntry::DEP_Any, results); - // the jobIdentifiers that have identified it as a job dependency - for (SourceFileDependencyEntry& existingEntry : results) + if (initialProcessTime > AZStd::chrono::system_clock::time_point{} + && duration >= AZStd::chrono::milliseconds(MaxRetryPeriodMS)) { - // this row is [Source] --> [Depends on Source]. - QString absolutePath = m_platformConfig->FindFirstMatchingFile(QString::fromUtf8(existingEntry.m_source.c_str())); - if (!absolutePath.isEmpty()) - { - AssessFileInternal(absolutePath, false); - } - // also, update it in the database to be missing, ie, add the "missing file" prefix: - existingEntry.m_dependsOnSource = QString(PlaceHolderFileName + relativePath).toUtf8().constData(); - m_stateData->RemoveSourceFileDependency(existingEntry.m_sourceDependencyID); - m_stateData->SetSourceFileDependency(existingEntry); + AZ_Warning(AssetProcessor::ConsoleChannel, false, "Failed to delete product(s) from source file `%s` after retrying for %fms. Giving up.", + normalizedPath.toUtf8().constData(), duration.count()); + return; } - // now that the right hand column (in terms of [thing] -> [depends on thing]) has been updated, eliminate anywhere its on the left hand side: - results.clear(); - m_stateData->GetDependsOnSourceBySource(databaseSourceFile.toUtf8().constData(), SourceFileDependencyEntry::DEP_Any, results); - m_stateData->RemoveSourceFileDependencies(results); - + bool deleteFailure = false; AzToolsFramework::AssetDatabase::SourceDatabaseEntryContainer sources; + if (m_stateData->GetSourcesBySourceName(databaseSourceFile, sources)) { for (const auto& source : sources) @@ -1827,7 +1820,13 @@ namespace AssetProcessor { // DeleteProducts will make an attempt to retry deleting each product // We can't just re-queue the whole file with CheckSource because we're deleting bits from the database as we go - AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Delete failed on %s.\n", normalizedPath.toUtf8().constData()); + deleteFailure = true; + CheckSource(FileEntry( + normalizedPath, true, false, + initialProcessTime > AZStd::chrono::system_clock::time_point{} ? initialProcessTime + : AZStd::chrono::system_clock::now())); + AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Delete failed on %s. Will retry!\n", normalizedPath.toUtf8().constData()); + continue; } } else @@ -1843,13 +1842,48 @@ namespace AssetProcessor Q_EMIT JobRemoved(jobInfo); } } - // delete the source from the database too since otherwise it believes we have no products. - m_stateData->RemoveSource(source.m_sourceID); + + if (!deleteFailure) + { + // delete the source from the database too since otherwise it believes we have no products. + m_stateData->RemoveSource(source.m_sourceID); + } } } + if(deleteFailure) + { + return; + } + + // Check if this file causes any file types to be re-evaluated + CheckMetaDataRealFiles(normalizedPath); - Q_EMIT SourceDeleted(databaseSourceFile); // note that this removes it from the RC Queue Model, also + // when a source is deleted, we also have to queue anything that depended on it, for re-processing: + SourceFileDependencyEntryContainer results; + m_stateData->GetSourceFileDependenciesByDependsOnSource(databaseSourceFile, SourceFileDependencyEntry::DEP_Any, results); + // the jobIdentifiers that have identified it as a job dependency + for (SourceFileDependencyEntry& existingEntry : results) + { + // this row is [Source] --> [Depends on Source]. + QString absolutePath = m_platformConfig->FindFirstMatchingFile(QString::fromUtf8(existingEntry.m_source.c_str())); + if (!absolutePath.isEmpty()) + { + AssessFileInternal(absolutePath, false); + } + // also, update it in the database to be missing, ie, add the "missing file" prefix: + existingEntry.m_dependsOnSource = QString(PlaceHolderFileName + relativePath).toUtf8().constData(); + m_stateData->RemoveSourceFileDependency(existingEntry.m_sourceDependencyID); + m_stateData->SetSourceFileDependency(existingEntry); + } + + // now that the right hand column (in terms of [thing] -> [depends on thing]) has been updated, eliminate anywhere its on the left + // hand side: + results.clear(); + m_stateData->GetDependsOnSourceBySource(databaseSourceFile.toUtf8().constData(), SourceFileDependencyEntry::DEP_Any, results); + m_stateData->RemoveSourceFileDependencies(results); + + Q_EMIT SourceDeleted(databaseSourceFile); // note that this removes it from the RC Queue Model, also } void AssetProcessorManager::AddKnownFoldersRecursivelyForFile(QString fullFile, QString root) @@ -2568,7 +2602,7 @@ namespace AssetProcessor jobdetail.m_jobParam[AZ_CRC(AutoFailReasonKey)] = AZStd::string::format( "Source file ( %s ) contains non ASCII characters.\n" - "Lumberyard currently only supports file paths having ASCII characters and therefore asset processor will not be able to process this file.\n" + "Open 3D Engine currently only supports file paths having ASCII characters and therefore asset processor will not be able to process this file.\n" "Please rename the source file to fix this error.\n", normalizedPath.toUtf8().data()); @@ -2641,7 +2675,7 @@ namespace AssetProcessor AZ::Uuid sourceUUID = AssetUtilities::CreateSafeSourceUUIDFromName(databasePathToFile.toUtf8().data()); AzToolsFramework::AssetSystem::SourceFileNotificationMessage message(AZ::OSString(sourceFile.toUtf8().constData()), AZ::OSString(scanFolderInfo->ScanPath().toUtf8().constData()), AzToolsFramework::AssetSystem::SourceFileNotificationMessage::FileRemoved, sourceUUID); EBUS_EVENT(AssetProcessor::ConnectionBus, Send, 0, message); - CheckDeletedSourceFile(normalizedPath, relativePathToFile, databasePathToFile); + CheckDeletedSourceFile(normalizedPath, relativePathToFile, databasePathToFile, examineFile.m_initialProcessTime); } else { diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h index c4d82d57d0..4c203567e9 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h @@ -116,13 +116,15 @@ namespace AssetProcessor QString m_fileName; bool m_isDelete = false; bool m_isFromScanner = false; + AZStd::chrono::system_clock::time_point m_initialProcessTime{}; FileEntry() = default; - FileEntry(const QString& fileName, bool isDelete, bool isFromScanner=false) + FileEntry(const QString& fileName, bool isDelete, bool isFromScanner = false, AZStd::chrono::system_clock::time_point initialProcessTime = {}) : m_fileName(fileName) , m_isDelete(isDelete) , m_isFromScanner(isFromScanner) + , m_initialProcessTime(initialProcessTime) { } @@ -305,7 +307,9 @@ namespace AssetProcessor void CheckSource(const FileEntry& source); void CheckMissingJobs(QString relativeSourceFile, const ScanFolderInfo* scanFolder, const AZStd::vector& jobsThisTime); void CheckDeletedProductFile(QString normalizedPath); - void CheckDeletedSourceFile(QString normalizedPath, QString relativePath, QString databaseSourceFile); + void CheckDeletedSourceFile( + QString normalizedPath, QString relativePath, QString databaseSourceFile, + AZStd::chrono::system_clock::time_point initialProcessTime); void CheckModifiedSourceFile(QString normalizedPath, QString databaseSourceFile, const ScanFolderInfo* scanFolderInfo); bool AnalyzeJob(JobDetails& details); void CheckDeletedCacheFolder(QString normalizedPath); diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp index 8a8e7d6b08..30a7978c50 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp @@ -424,12 +424,12 @@ namespace AssetProcessor bool InternalRecognizerBasedBuilder::FindRC(QString& rcAbsolutePathOut) { - char executableDirectory[AZ_MAX_PATH_LEN]; - if (AZ::Utils::GetExecutableDirectory(executableDirectory, AZStd::size(executableDirectory)) == AZ::Utils::ExecutablePathResult::Success) + AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory(); + executableDirectory /= ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH; + if (AZ::IO::SystemFile::Exists(executableDirectory.c_str())) { - rcAbsolutePathOut = QString("%1/%2").arg(executableDirectory).arg(QString(ASSETPROCESSOR_TRAIT_LEGACY_RC_RELATIVE_PATH)); - - return AZ::IO::SystemFile::Exists(rcAbsolutePathOut.toUtf8().data()); + rcAbsolutePathOut = QString::fromUtf8(executableDirectory.c_str(), executableDirectory.Native().size()); + return true; } return false; diff --git a/Code/Tools/AssetProcessor/native/tests/assetdatabase/AssetDatabaseTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetdatabase/AssetDatabaseTest.cpp index d057e06a9f..12b202e804 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetdatabase/AssetDatabaseTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetdatabase/AssetDatabaseTest.cpp @@ -81,7 +81,7 @@ namespace UnitTests // Product: "someproduct4.dds" subid: 4 void CreateCoverageTestData() { - m_data->m_scanFolder = { "c:/lumberyard/dev", "dev", "rootportkey", "" }; + m_data->m_scanFolder = { "c:/O3DE/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(m_data->m_scanFolder)); m_data->m_sourceFile1 = { m_data->m_scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint1"}; @@ -239,7 +239,7 @@ namespace UnitTests // we'll create all of those first (except product) before starting the product test. //add a scanfolder. None of this has to exist in real disk, this is a db test only. - ScanFolderDatabaseEntry scanFolder {"c:/lumberyard/dev", "dev", "rootportkey", ""}; + ScanFolderDatabaseEntry scanFolder {"c:/O3DE/dev", "dev", "rootportkey", ""}; EXPECT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); ASSERT_NE(scanFolder.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId); @@ -278,7 +278,7 @@ namespace UnitTests // to add a product legitimately you have to have a full chain of primary keys, chain is: // ScanFolder --> Source --> job --> product. // we'll create all of those first (except product) before starting the product test. - ScanFolderDatabaseEntry scanFolder{ "c:/lumberyard/dev", "dev", "rootportkey", "" }; + ScanFolderDatabaseEntry scanFolder{ "c:/O3DE/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" }; @@ -323,7 +323,7 @@ namespace UnitTests // this is actually a very common case (same job id, same subID) TEST_F(AssetDatabaseTest, SetProduct_SpecificPK_Succeeds_SameSubID_SameJobID) { - ScanFolderDatabaseEntry scanFolder{ "c:/lumberyard/dev", "dev", "rootportkey", "" }; + ScanFolderDatabaseEntry scanFolder{ "c:/O3DE/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" }; ASSERT_TRUE(m_data->m_connection.SetSource(sourceEntry)); diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp index 6c2bf754c1..d8afda1b2c 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp @@ -4540,9 +4540,17 @@ void ModtimeScanningTest::TearDown() void ModtimeScanningTest::ProcessAssetJobs() { + m_data->m_productPaths.clear(); + for (const auto& processResult : m_data->m_processResults) { auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName + ".arc1"); + m_data->m_productPaths.emplace( + QDir(processResult.m_jobEntry.m_watchFolderPath) + .absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName) + .toUtf8() + .constData(), + file); // Create the file on disk ASSERT_TRUE(UnitTestUtils::CreateDummyFile(file, "products.")); @@ -4793,6 +4801,123 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAg ExpectWork(2, 2); } +struct LockedFileTest + : ModtimeScanningTest + , AssetProcessor::ConnectionBus::Handler +{ + MOCK_METHOD3(SendRaw, size_t (unsigned, unsigned, const QByteArray&)); + MOCK_METHOD3(SendPerPlatform, size_t (unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage&, const QString&)); + MOCK_METHOD4(SendRawPerPlatform, size_t (unsigned, unsigned, const QByteArray&, const QString&)); + MOCK_METHOD2(SendRequest, unsigned (const AzFramework::AssetSystem::BaseAssetProcessorMessage&, const ResponseCallback&)); + MOCK_METHOD2(SendResponse, size_t (unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage&)); + MOCK_METHOD1(RemoveResponseHandler, void (unsigned)); + + size_t Send(unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage&) override + { + if(m_callback) + { + m_callback(); + } + + return 0; + } + + void SetUp() override + { + ModtimeScanningTest::SetUp(); + + ConnectionBus::Handler::BusConnect(0); + } + + void TearDown() override + { + ConnectionBus::Handler::BusDisconnect(); + + ModtimeScanningTest::TearDown(); + } + + AZStd::function m_callback; +}; + +TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeleteFails) +{ + auto theFile = m_data->m_absolutePath[1].toUtf8(); + const char* theFileString = theFile.constData(); + auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString); + + { + QFile file(theFileString); + file.remove(); + } + + ASSERT_GT(m_data->m_productPaths.size(), 0); + QFile product(productPath); + + ASSERT_TRUE(product.open(QIODevice::ReadOnly)); + + // Check if we can delete the file now, if we can't, proceed with the test + // If we can, it means the OS running this test doesn't lock open files so there's nothing to test + if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData())) + { + QMetaObject::invokeMethod( + m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString))); + + EXPECT_TRUE(BlockUntilIdle(5000)); + + EXPECT_TRUE(QFile::exists(productPath)); + EXPECT_EQ(m_data->m_deletedSources.size(), 0); + } + else + { + SUCCEED() << "Skipping test. OS does not lock open files."; + } +} + +TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased) +{ + auto theFile = m_data->m_absolutePath[1].toUtf8(); + const char* theFileString = theFile.constData(); + auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString); + + { + QFile file(theFileString); + file.remove(); + } + + ASSERT_GT(m_data->m_productPaths.size(), 0); + QFile product(productPath); + + ASSERT_TRUE(product.open(QIODevice::ReadOnly)); + + // Check if we can delete the file now, if we can't, proceed with the test + // If we can, it means the OS running this test doesn't lock open files so there's nothing to test + if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData())) + { + AZStd::thread workerThread; + + m_callback = [&product, &workerThread]() { + workerThread = AZStd::thread([&product]() { + AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(60)); + product.close(); + }); + }; + + QMetaObject::invokeMethod( + m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString))); + + EXPECT_TRUE(BlockUntilIdle(5000)); + + EXPECT_FALSE(QFile::exists(productPath)); + EXPECT_EQ(m_data->m_deletedSources.size(), 1); + + workerThread.join(); + } + else + { + SUCCEED() << "Skipping test. OS does not lock open files."; + } +} + TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFilesSameHash_BothProcess) { using namespace AzToolsFramework::AssetSystem; diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h index fafb2f4ec3..3c61e87e5d 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h @@ -174,6 +174,7 @@ struct ModtimeScanningTest QString m_relativePathFromWatchFolder[3]; AZStd::vector m_absolutePath; AZStd::vector m_processResults; + AZStd::unordered_multimap m_productPaths; AZStd::vector m_deletedSources; AZStd::shared_ptr m_builderTxtBuilder; MockBuilderInfoHandler m_mockBuilderInfoHandler; diff --git a/Code/Tools/AssetProcessor/native/ui/ProductAssetDetailsPanel.cpp b/Code/Tools/AssetProcessor/native/ui/ProductAssetDetailsPanel.cpp index 02615c2416..a57bdf8be6 100644 --- a/Code/Tools/AssetProcessor/native/ui/ProductAssetDetailsPanel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/ProductAssetDetailsPanel.cpp @@ -112,7 +112,7 @@ namespace AssetProcessor [&](AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry) { assetId = AZ::Data::AssetId(sourceEntry.m_sourceGuid, productItemData->m_databaseInfo.m_subID); - // Use a decimal value to display the sub ID and not hex. Lumberyard is not consistent about + // Use a decimal value to display the sub ID and not hex. Open 3D Engine is not consistent about // how sub IDs are displayed, so it's important to double check what format a sub ID is in before using it elsewhere. m_ui->productAssetIdValueLabel->setText(assetId.ToString(AZ::Data::AssetId::SubIdDisplayType::Decimal).c_str()); diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp index dfb97a4e9d..4d7711acad 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp @@ -76,7 +76,7 @@ namespace AssetProcessor AzFramework::StringFunc::AssetDatabasePath::Join(scanFolder.m_scanFolder.c_str(), fullPath.c_str(), fullPath, true, false); - // It's common for Lumberyard game projects and scan folders to be in a subfolder + // It's common for Open 3D Engine game projects and scan folders to be in a subfolder // of the engine install. To improve readability of the source files, strip out // that portion of the path if it overlaps. if (!m_assetRootSet) diff --git a/Code/Tools/AssetProcessor/native/ui/style/AssetProcessor.qrc b/Code/Tools/AssetProcessor/native/ui/style/AssetProcessor.qrc index ef8f688f8b..564d7a2132 100644 --- a/Code/Tools/AssetProcessor/native/ui/style/AssetProcessor.qrc +++ b/Code/Tools/AssetProcessor/native/ui/style/AssetProcessor.qrc @@ -16,6 +16,6 @@ AssetProcessor_arrow_down.svg AssetProcessor_arrow_up.svg AssetProcessor_refresh.png - lyassetprocessor.png + o3de_assetprocessor.png diff --git a/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.ico b/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.ico deleted file mode 100644 index b9c9e924ee..0000000000 --- a/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9965c02521822e92baad09dde15064ac0f326d861533725de283bac6e0ce3618 -size 108108 diff --git a/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.png b/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.png deleted file mode 100644 index 1f8ba21e9a..0000000000 --- a/Code/Tools/AssetProcessor/native/ui/style/lyassetprocessor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:68f33fe204a433f8c765d524c9b9e42963f5d16c3442f36df87185bcb4555111 -size 8686 diff --git a/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.ico b/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.ico new file mode 100644 index 0000000000..2980b6e386 --- /dev/null +++ b/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424c7e9a5bc4819e838e142ae87c987ce96ef40ff853d4a2610d7f068d635851 +size 107989 diff --git a/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.png b/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.png new file mode 100644 index 0000000000..50610c7ff4 --- /dev/null +++ b/Code/Tools/AssetProcessor/native/ui/style/o3de_assetprocessor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f16c891aaa1686a3735fe84c7a69c3cef24e68af7baa86bf2f54ab4d51b71e8 +size 8489 diff --git a/Code/Tools/AssetProcessor/native/unittests/AssetProcessingStateDataUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/AssetProcessingStateDataUnitTests.cpp index bbbea4f170..1ece24210a 100644 --- a/Code/Tools/AssetProcessor/native/unittests/AssetProcessingStateDataUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/AssetProcessingStateDataUnitTests.cpp @@ -148,7 +148,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon scanFolders.clear(); //add a scanfolder - scanFolder = ScanFolderDatabaseEntry("c:/lumberyard/dev", "dev", "rootportkey", ""); + scanFolder = ScanFolderDatabaseEntry("c:/O3DE/dev", "dev", "rootportkey", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(scanFolder)); if (scanFolder.m_scanFolderID == AzToolsFramework::AssetDatabase::InvalidEntryId) { @@ -158,7 +158,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon //add the same folder again, should not add another because it already exists, so we should get the same id // not only that, but the path should update. - ScanFolderDatabaseEntry dupeScanFolder = ScanFolderDatabaseEntry("c:/lumberyard/dev2", "dev", "rootportkey", ""); + ScanFolderDatabaseEntry dupeScanFolder = ScanFolderDatabaseEntry("c:/O3DE/dev2", "dev", "rootportkey", ""); dupeScanFolder.m_scanFolderID = AzToolsFramework::AssetDatabase::InvalidEntryId; UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(dupeScanFolder)); if (!(dupeScanFolder == scanFolder)) @@ -174,7 +174,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon scanFolders.clear(); UNIT_TEST_EXPECT_TRUE(stateData->GetScanFolders(scanFolders)); UNIT_TEST_EXPECT_TRUE(scanFolders.size() == 1); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/dev2")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev2")); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, scanFolder.m_scanFolderID)); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainPortableKey(scanFolders, scanFolder.m_portableKey.c_str())); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainPortableKey(scanFolders, "rootportkey")); @@ -200,7 +200,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon } //add another folder - ScanFolderDatabaseEntry gameScanFolderEntry("c:/lumberyard/game", "game", "gameportkey", ""); + ScanFolderDatabaseEntry gameScanFolderEntry("c:/O3DE/game", "game", "gameportkey", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(gameScanFolderEntry)); if (gameScanFolderEntry.m_scanFolderID == AzToolsFramework::AssetDatabase::InvalidEntryId || gameScanFolderEntry.m_scanFolderID == scanFolder.m_scanFolderID) @@ -213,8 +213,8 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon scanFolders.clear(); UNIT_TEST_EXPECT_TRUE(stateData->GetScanFolders(scanFolders)); UNIT_TEST_EXPECT_TRUE(scanFolders.size() == 2); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/dev2")); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/game")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev2")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/game")); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, scanFolder.m_scanFolderID)); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, gameScanFolderEntry.m_scanFolderID)); @@ -226,11 +226,11 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon scanFolders.clear(); UNIT_TEST_EXPECT_TRUE(stateData->GetScanFolders(scanFolders)); UNIT_TEST_EXPECT_TRUE(scanFolders.size() == 1); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/dev2")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev2")); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, scanFolder.m_scanFolderID)); //add another folder again - gameScanFolderEntry = ScanFolderDatabaseEntry("c:/lumberyard/game", "game", "gameportkey2", ""); + gameScanFolderEntry = ScanFolderDatabaseEntry("c:/O3DE/game", "game", "gameportkey2", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(gameScanFolderEntry)); if (gameScanFolderEntry.m_scanFolderID == AzToolsFramework::AssetDatabase::InvalidEntryId || gameScanFolderEntry.m_scanFolderID == scanFolder.m_scanFolderID) @@ -243,8 +243,8 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon scanFolders.clear(); UNIT_TEST_EXPECT_TRUE(stateData->GetScanFolders(scanFolders)); UNIT_TEST_EXPECT_TRUE(scanFolders.size() == 2); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/dev2")); - UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/lumberyard/game")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev2")); + UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanPath(scanFolders, "c:/O3DE/game")); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, scanFolder.m_scanFolderID)); UNIT_TEST_EXPECT_TRUE(ScanFoldersContainScanFolderID(scanFolders, gameScanFolderEntry.m_scanFolderID)); @@ -258,7 +258,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon /////////////////////////////////////////////////////////// //setup for sources tests //for the rest of the test lets add the original scan folder - scanFolder = ScanFolderDatabaseEntry("c:/lumberyard/dev", "dev", "devkey2", ""); + scanFolder = ScanFolderDatabaseEntry("c:/O3DE/dev", "dev", "devkey2", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(scanFolder)); /////////////////////////////////////////////////////////// @@ -370,7 +370,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon UNIT_TEST_EXPECT_TRUE(SourcesContainSourceGuid(sources, source.m_sourceGuid)); //add the same source again, but change the scan folder. This should NOT add a new source - even if we don't know what the sourceID is: - ScanFolderDatabaseEntry scanfolder2 = ScanFolderDatabaseEntry("c:/lumberyard/dev2", "dev2", "devkey3", ""); + ScanFolderDatabaseEntry scanfolder2 = ScanFolderDatabaseEntry("c:/O3DE/dev2", "dev2", "devkey3", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(scanfolder2)); SourceDatabaseEntry dupeSource2(source); @@ -554,7 +554,7 @@ void AssetProcessingStateDataUnitTest::DataTest(AssetProcessor::AssetDatabaseCon //////////////////////////////////////////////////////////////// //Setup for jobs tests by having a scan folder and some sources //Add a scan folder - scanFolder = ScanFolderDatabaseEntry("c:/lumberyard/dev", "dev", "devkey3", ""); + scanFolder = ScanFolderDatabaseEntry("c:/O3DE/dev", "dev", "devkey3", ""); UNIT_TEST_EXPECT_TRUE(stateData->SetScanFolder(scanFolder)); //Add some sources diff --git a/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.cpp b/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.cpp index dc0786d918..10000298c7 100644 --- a/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.cpp @@ -115,9 +115,6 @@ ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun() #endif AssetProcessor::MessageInfoBus::Handler::BusConnect(); - QString bootstrapPath = devRoot.filePath("bootstrap.cfg"); - m_qtFileWatcher.addPath(bootstrapPath); - // we have to monitor both the cache folder and the database file and restart AP if either of them gets deleted // It is important to note that we are monitoring the parent folder and not the actual cache folder itself since // we want to handle the use case on Mac OS if the user moves the cache folder to the trash. @@ -135,33 +132,6 @@ ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun() QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::fileChanged, this, &GUIApplicationManager::FileChanged); QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::directoryChanged, this, &GUIApplicationManager::DirectoryChanged); - // Register a notifier for when the project_path property changes within the SettingsRegistry - if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) - { - // Needs to be updated to project_path. - auto OnProjectPathChanged = [this, cachedProjectPath = projectPath](AZStd::string_view path, AZ::SettingsRegistryInterface::Type) - { - constexpr auto projectPathKey = - AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) - + "/project_path"; - if (projectPathKey == path) - { - AZ::SettingsRegistryInterface::FixedValueString newProjectPath; - if (auto registry = AZ::SettingsRegistry::Get(); registry && registry->Get(newProjectPath, path)) - { - // we only have to quit if the project path has changed, not if just the bootstrap has changed. - if (cachedProjectPath.compare(newProjectPath.c_str()) != 0) - { - AZ_TracePrintf(AssetProcessor::ConsoleChannel, "bootstrap.cfg Project Path changed from %s to %s. Quitting\n", - cachedProjectPath.toUtf8().constData(), newProjectPath.c_str()); - QMetaObject::invokeMethod(this, "QuitRequested", Qt::QueuedConnection); - } - } - } - }; - m_bootstrapGameFolderChangedHandler = settingsRegistry->RegisterNotifier(AZStd::move(OnProjectPathChanged)); - } - return ApplicationManager::BeforeRunStatus::Status_Success; } @@ -306,7 +276,7 @@ bool GUIApplicationManager::Run() m_trayIcon = new QSystemTrayIcon(m_mainWindow); m_trayIcon->setContextMenu(trayIconMenu); m_trayIcon->setToolTip(QObject::tr("Asset Processor")); - m_trayIcon->setIcon(QIcon(":/lyassetprocessor.png")); + m_trayIcon->setIcon(QIcon(":/o3de_assetprocessor.png")); m_trayIcon->show(); QObject::connect(m_trayIcon, &QSystemTrayIcon::activated, m_mainWindow, [&, wrapper](QSystemTrayIcon::ActivationReason reason) { @@ -328,8 +298,8 @@ bool GUIApplicationManager::Run() if (startHidden) { m_trayIcon->showMessage( - QCoreApplication::translate("Tray Icon", "Lumberyard Asset Processor has started"), - QCoreApplication::translate("Tray Icon", "The Lumberyard Asset Processor monitors raw project assets and converts those assets into runtime-ready data."), + QCoreApplication::translate("Tray Icon", "Open 3D Engine Asset Processor has started"), + QCoreApplication::translate("Tray Icon", "The Open 3D Engine Asset Processor monitors raw project assets and converts those assets into runtime-ready data."), QSystemTrayIcon::Information, 3000); } } @@ -651,29 +621,10 @@ void GUIApplicationManager::DirectoryChanged([[maybe_unused]] QString path) void GUIApplicationManager::FileChanged(QString path) { QDir devRoot = ApplicationManager::GetSystemRoot(); - QString bootstrapPath = devRoot.filePath("bootstrap.cfg"); QDir projectCacheRoot; AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot); QString assetDbPath = projectCacheRoot.filePath("assetdb.sqlite"); - if (QString::compare(AssetUtilities::NormalizeFilePath(path), bootstrapPath, Qt::CaseInsensitive) == 0) - { - AssetUtilities::UpdateBranchToken(); - - if (m_connectionManager) - { - m_connectionManager->UpdateAllowedListFromBootStrap(); - } - - // Re-merge the Bootstrap.cfg into the SettingsRegistry - AZStd::vector scratchBuffer; - AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); - AZ_Assert(settingsRegistry, "Unable to retrieve global SettingsRegistry, it should be available now"); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*settingsRegistry); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*settingsRegistry, *m_frameworkApp.GetAzCommandLine(), false); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*settingsRegistry); - } - else if (QString::compare(AssetUtilities::NormalizeFilePath(path), assetDbPath, Qt::CaseInsensitive) == 0) + if (QString::compare(AssetUtilities::NormalizeFilePath(path), assetDbPath, Qt::CaseInsensitive) == 0) { if (!QFile::exists(assetDbPath)) { @@ -868,7 +819,7 @@ void GUIApplicationManager::ShowTrayIconErrorMessage(QString msg) { m_timeWhenLastWarningWasShown = currentTime; m_trayIcon->showMessage( - QCoreApplication::translate("Tray Icon", "Lumberyard Asset Processor"), + QCoreApplication::translate("Tray Icon", "Open 3D Engine Asset Processor"), QCoreApplication::translate("Tray Icon", msg.toUtf8().data()), QSystemTrayIcon::Critical, 3000); } @@ -880,7 +831,7 @@ void GUIApplicationManager::ShowTrayIconMessage(QString msg) if (m_trayIcon && m_mainWindow && !m_mainWindow->isVisible()) { m_trayIcon->showMessage( - QCoreApplication::translate("Tray Icon", "Lumberyard Asset Processor"), + QCoreApplication::translate("Tray Icon", "Open 3D Engine Asset Processor"), QCoreApplication::translate("Tray Icon", msg.toUtf8().data()), QSystemTrayIcon::Information, 3000); } diff --git a/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.h b/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.h index e824350cef..1947e26ae0 100644 --- a/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.h +++ b/Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.h @@ -112,7 +112,6 @@ private: QPointer m_trayIcon; QPointer m_mainWindow; - AZ::SettingsRegistryInterface::NotifyEventHandler m_bootstrapGameFolderChangedHandler; AZStd::chrono::system_clock::time_point m_timeWhenLastWarningWasShown; }; diff --git a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp index c62078f7ab..b615e8854a 100644 --- a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp @@ -181,13 +181,29 @@ namespace AssetUtilsInternal if (AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(settingsRegistry, AssetProcessorUserSettingsRootKey, apSettingsStream, apDumperSettings)) { + constexpr const char* AssetProcessorTmpSetreg = "asset_processor.setreg.tmp"; + // Write to a temporary file first before renaming it to the final file location + // This is needed to reduce the potential of a race condition which occurs when other applications attempt to load settings registry + // files from the project's user Registry folder while the AssetProcessor is writing the file out the asset_processor.setreg + // at the same time + QString tempDirValue; + AssetUtilities::CreateTempWorkspace(tempDirValue); + QDir tempDir(tempDirValue); + AZ::IO::FixedMaxPath tmpSetregPath = tempDir.absoluteFilePath(QString(AssetProcessorTmpSetreg)).toUtf8().data(); constexpr auto modeFlags = AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH; - if (AZ::IO::SystemFile apSetregFile; apSetregFile.Open(setregPath.c_str(), modeFlags)) + if (AZ::IO::SystemFile apSetregFile; apSetregFile.Open(tmpSetregPath.c_str(), modeFlags)) { size_t bytesWritten = apSetregFile.Write(apSettingsJson.data(), apSettingsJson.size()); - return bytesWritten == apSettingsJson.size(); + // Close the file so that it can be renamed. + apSetregFile.Close(); + if (bytesWritten == apSettingsJson.size()) + { + // Create the directory to contain the moved setreg file + AZ::IO::SystemFile::CreateDir(AZ::IO::FixedMaxPath(setregPath.ParentPath()).c_str()); + return AZ::IO::SystemFile::Rename(tmpSetregPath.c_str(), setregPath.c_str(), true); + } } else { diff --git a/Code/Tools/CrashHandler/Shared/CrashHandler.h b/Code/Tools/CrashHandler/Shared/CrashHandler.h index 86cf31917a..df5185283b 100644 --- a/Code/Tools/CrashHandler/Shared/CrashHandler.h +++ b/Code/Tools/CrashHandler/Shared/CrashHandler.h @@ -21,7 +21,7 @@ namespace CrashHandler { static const char* defaultCrashFolder = "CrashDB/"; - static const char* lumberyardProductName = "lumberyard"; + static const char* O3DEProductName = "Open 3D Engine"; using CrashHandlerAnnotations = std::map; using CrashHandlerArguments = std::vector; @@ -48,7 +48,7 @@ namespace CrashHandler virtual std::string DetermineAppPath() const; - virtual const char* GetProductName() const { return lumberyardProductName; } + virtual const char* GetProductName() const { return O3DEProductName; } virtual bool CreateCrashHandlerDB(const std::string& reportPath) const; diff --git a/Code/Tools/CrashHandler/Tools/UI/submit_report.ui b/Code/Tools/CrashHandler/Tools/UI/submit_report.ui index ae98d536a1..872adac709 100644 --- a/Code/Tools/CrashHandler/Tools/UI/submit_report.ui +++ b/Code/Tools/CrashHandler/Tools/UI/submit_report.ui @@ -80,7 +80,7 @@ - Lumberyard has encountered a fatal error. We're sorry for the inconvenience. + Open 3D Engine has encountered a fatal error. We're sorry for the inconvenience. true @@ -96,7 +96,7 @@ - A Lumberyard Editor crash debugging file has been created at: + An Open 3D Engine Editor crash debugging file has been created at: true @@ -134,7 +134,7 @@ - If you are willing to submit this file to Amazon it will help us improve the Lumberyard experience. We will treat this report as confidential. + If you are willing to submit this file to Amazon it will help us improve the Open 3D Engine experience. We will treat this report as confidential. true diff --git a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp index 9fb85fc585..8162c1093b 100644 --- a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp +++ b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp @@ -32,11 +32,11 @@ #include "UI/ui_submit_report.h" -namespace Lumberyard +namespace O3de { void InstallCrashUploader(int& argc, char* argv[]) { - Lumberyard::CrashUploader::SetCrashUploader(std::make_shared(argc, argv)); + O3de::CrashUploader::SetCrashUploader(std::make_shared(argc, argv)); } QString GetReportString(const std::wstring& reportPath) { diff --git a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.h b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.h index ca7081b0e1..fce321ceb8 100644 --- a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.h +++ b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.h @@ -16,7 +16,7 @@ #include -namespace Lumberyard +namespace O3de { class ToolsCrashUploader : public CrashUploader { diff --git a/Code/Tools/CrashHandler/Tools/Uploader/platforms/win/main.cpp b/Code/Tools/CrashHandler/Tools/Uploader/platforms/win/main.cpp index 54748cddde..0899eeca51 100644 --- a/Code/Tools/CrashHandler/Tools/Uploader/platforms/win/main.cpp +++ b/Code/Tools/CrashHandler/Tools/Uploader/platforms/win/main.cpp @@ -22,10 +22,10 @@ namespace { int HandlerMain(int argc, char* argv[]) { - Lumberyard::InstallCrashUploader(argc, argv); + O3de::InstallCrashUploader(argc, argv); LOG(ERROR) << "Initializing windows crash uploader"; - int resultCode = crashpad::HandlerMain(argc, argv, Lumberyard::CrashUploader::GetCrashUploader()->GetUserStreamSources()); + int resultCode = crashpad::HandlerMain(argc, argv, O3de::CrashUploader::GetCrashUploader()->GetUserStreamSources()); return resultCode; } diff --git a/Code/Tools/CrashHandler/Uploader/include/Uploader/BufferedDataStream.h b/Code/Tools/CrashHandler/Uploader/include/Uploader/BufferedDataStream.h index de7493ec33..6eb25c1857 100644 --- a/Code/Tools/CrashHandler/Uploader/include/Uploader/BufferedDataStream.h +++ b/Code/Tools/CrashHandler/Uploader/include/Uploader/BufferedDataStream.h @@ -16,7 +16,7 @@ #include #include -namespace Lumberyard +namespace O3de { class BufferedDataStream : public crashpad::MinidumpUserExtensionStreamDataSource { diff --git a/Code/Tools/CrashHandler/Uploader/include/Uploader/CrashUploader.h b/Code/Tools/CrashHandler/Uploader/include/Uploader/CrashUploader.h index 7ce677a8f8..dee0c03e67 100644 --- a/Code/Tools/CrashHandler/Uploader/include/Uploader/CrashUploader.h +++ b/Code/Tools/CrashHandler/Uploader/include/Uploader/CrashUploader.h @@ -28,7 +28,7 @@ #include #include -namespace Lumberyard +namespace O3de { bool CheckConfirmation(const crashpad::CrashReportDatabase::Report& report); void InstallCrashUploader(int& argc, char* argv[]); diff --git a/Code/Tools/CrashHandler/Uploader/include/Uploader/FileStreamDataSource.h b/Code/Tools/CrashHandler/Uploader/include/Uploader/FileStreamDataSource.h index 0fec400c7a..0193b185ff 100644 --- a/Code/Tools/CrashHandler/Uploader/include/Uploader/FileStreamDataSource.h +++ b/Code/Tools/CrashHandler/Uploader/include/Uploader/FileStreamDataSource.h @@ -16,7 +16,7 @@ #include #include "base/files/file_path.h" -namespace Lumberyard +namespace O3de { class FileStreamDataSource : public crashpad::UserStreamDataSource { diff --git a/Code/Tools/CrashHandler/Uploader/src/BufferedDataStream.cpp b/Code/Tools/CrashHandler/Uploader/src/BufferedDataStream.cpp index 28dea132c0..d744a193d4 100644 --- a/Code/Tools/CrashHandler/Uploader/src/BufferedDataStream.cpp +++ b/Code/Tools/CrashHandler/Uploader/src/BufferedDataStream.cpp @@ -12,7 +12,7 @@ #include -namespace Lumberyard +namespace O3de { BufferedDataStream::BufferedDataStream(uint32_t stream_type, const void* data, size_t data_size) : crashpad::MinidumpUserExtensionStreamDataSource(stream_type) diff --git a/Code/Tools/CrashHandler/Uploader/src/CrashUploader.cpp b/Code/Tools/CrashHandler/Uploader/src/CrashUploader.cpp index 6ad2e8ab14..037b3aee5b 100644 --- a/Code/Tools/CrashHandler/Uploader/src/CrashUploader.cpp +++ b/Code/Tools/CrashHandler/Uploader/src/CrashUploader.cpp @@ -25,7 +25,7 @@ #include -namespace Lumberyard +namespace O3de { using namespace crashpad; diff --git a/Code/Tools/CrashHandler/Uploader/src/FileStreamDataSource.cpp b/Code/Tools/CrashHandler/Uploader/src/FileStreamDataSource.cpp index 6a9520c84b..57b1fc59f2 100644 --- a/Code/Tools/CrashHandler/Uploader/src/FileStreamDataSource.cpp +++ b/Code/Tools/CrashHandler/Uploader/src/FileStreamDataSource.cpp @@ -15,7 +15,7 @@ #include -namespace Lumberyard +namespace O3de { FileStreamDataSource::FileStreamDataSource(const base::FilePath& filePath) : m_filePath{ filePath } diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp index a8ac0f7699..e0cbd8d733 100644 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp +++ b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp @@ -44,7 +44,7 @@ namespace }; static AZStd::atomic_long numberOfOpenSockets = {0}; - const int MAX_DATA_SIZE = 1024 * 1024; // Only allow 1 MB of data to come through. Lumberyard Game Engine has the same size constraint + const int MAX_DATA_SIZE = 1024 * 1024; // Only allow 1 MB of data to come through. Open 3D Engine has the same size constraint const size_t BLOCKSIZE = 4 * 1024; const size_t MAX_ERROR_MESSAGE_SIZE = 1024; const size_t MAX_HOSTNAME_BUFFER_SIZE = 1024; diff --git a/Code/Tools/DeltaCataloger/CMakeLists.txt b/Code/Tools/DeltaCataloger/CMakeLists.txt index c66f44ec66..b250df3ecb 100644 --- a/Code/Tools/DeltaCataloger/CMakeLists.txt +++ b/Code/Tools/DeltaCataloger/CMakeLists.txt @@ -13,6 +13,20 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +if(PAL_HOST_PLATFORM_NAME_LOWERCASE STREQUAL "windows") +ly_add_target( + NAME DeltaCataloger EXECUTABLE + NAMESPACE AZ + FILES_CMAKE + deltacataloger_files.cmake + deltacataloger_win_files.cmake + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AzFramework + AZ::AzToolsFramework +) +else() ly_add_target( NAME DeltaCataloger EXECUTABLE NAMESPACE AZ @@ -24,6 +38,7 @@ ly_add_target( AZ::AzFramework AZ::AzToolsFramework ) +endif() if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) diff --git a/Code/Tools/DeltaCataloger/deltacataloger_win_files.cmake b/Code/Tools/DeltaCataloger/deltacataloger_win_files.cmake new file mode 100644 index 0000000000..44152c82a8 --- /dev/null +++ b/Code/Tools/DeltaCataloger/deltacataloger_win_files.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(FILES + source/DeltaCataloger.rc +) diff --git a/Code/Tools/DeltaCataloger/source/DeltaCataloger.ico b/Code/Tools/DeltaCataloger/source/DeltaCataloger.ico new file mode 100644 index 0000000000..f6a69c0059 --- /dev/null +++ b/Code/Tools/DeltaCataloger/source/DeltaCataloger.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02a102aad5a014f2dc8cfcfb3f502ccf45207e2f8aca946b84e910488e4027c5 +size 103189 diff --git a/Code/Tools/DeltaCataloger/source/DeltaCataloger.rc b/Code/Tools/DeltaCataloger/source/DeltaCataloger.rc new file mode 100644 index 0000000000..5f939051d2 --- /dev/null +++ b/Code/Tools/DeltaCataloger/source/DeltaCataloger.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "DeltaCataloger.ico" diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc.h b/Code/Tools/HLSLCrossCompiler/include/hlslcc.h index 14f96c9988..efa43d8f4f 100644 --- a/Code/Tools/HLSLCrossCompiler/include/hlslcc.h +++ b/Code/Tools/HLSLCrossCompiler/include/hlslcc.h @@ -503,7 +503,7 @@ typedef enum _FRAMEBUFFER_FETCH_TYPE // NOTE: HLSLCC flags are specified by command line when executing this cross compiler. // If these flags change, the command line switch '-flags=XXX' must change as well. -// Lumberyard composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' +// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' /*HLSL constant buffers are treated as default-block unform arrays by default. This is done to support versions of GLSL which lack ARB_uniform_buffer_object functionality. diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h index 23458d4933..b7444121bc 100644 --- a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h +++ b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h @@ -445,7 +445,7 @@ typedef struct // NOTE: HLSLCC flags are specified by command line when executing this cross compiler. // If these flags change, the command line switch '-flags=XXX' must change as well. -// Lumberyard composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' +// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' /*HLSL constant buffers are treated as default-block unform arrays by default. This is done to support versions of GLSL which lack ARB_uniform_buffer_object functionality. diff --git a/Code/Tools/News/NewsBuilder/Qt/NewsBuilder.cpp b/Code/Tools/News/NewsBuilder/Qt/NewsBuilder.cpp index e505b52256..074099a4e6 100644 --- a/Code/Tools/News/NewsBuilder/Qt/NewsBuilder.cpp +++ b/Code/Tools/News/NewsBuilder/Qt/NewsBuilder.cpp @@ -165,7 +165,7 @@ namespace News QCustomMessageBox msgBox( QCustomMessageBox::Critical, tr("Publish resources"), - tr("You are about to overwrite the current Lumberyard Welcome Message. Are you sure you want to publish?"), + tr("You are about to overwrite the current Open 3D Engine Welcome Message. Are you sure you want to publish?"), this); msgBox.AddButton("Yes", Yes); msgBox.AddButton("No", No); diff --git a/Code/Tools/News/NewsShared/Qt/ArticleErrorView.ui b/Code/Tools/News/NewsShared/Qt/ArticleErrorView.ui index 8d5e914486..c94c636720 100644 --- a/Code/Tools/News/NewsShared/Qt/ArticleErrorView.ui +++ b/Code/Tools/News/NewsShared/Qt/ArticleErrorView.ui @@ -168,7 +168,7 @@ a { text-decoration: underline; color: red } - We couldn’t connect to the network or access our news database. To see the latest Lumberyard news, blogs, tutorials, and more, please visit the <a href="http://aws.amazon.com/lumberyard/">Lumberyard website</a>. + We couldn’t connect to the network or access our news database. To see the latest Open 3D Engine news, blogs, tutorials, and more, please visit the <a href="http://aws.amazon.com/lumberyard/">Lumberyard website</a>. Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/Code/Tools/RC/ResourceCompiler/CMakeLists.txt b/Code/Tools/RC/ResourceCompiler/CMakeLists.txt index c0cbca5a41..5b56071a62 100644 --- a/Code/Tools/RC/ResourceCompiler/CMakeLists.txt +++ b/Code/Tools/RC/ResourceCompiler/CMakeLists.txt @@ -23,7 +23,6 @@ ly_add_target( Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake INCLUDE_DIRECTORIES PUBLIC - PCH . .. BUILD_DEPENDENCIES diff --git a/Code/Tools/RC/ResourceCompiler/ResourceCompiler.cpp b/Code/Tools/RC/ResourceCompiler/ResourceCompiler.cpp index 42b123cfdd..54224c661c 100644 --- a/Code/Tools/RC/ResourceCompiler/ResourceCompiler.cpp +++ b/Code/Tools/RC/ResourceCompiler/ResourceCompiler.cpp @@ -1284,10 +1284,6 @@ void ResourceCompiler::LogMultiLine(const char* szText) *pLine++ = *p++; } - while (*p) - { - ; - } } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Tools/RC/ResourceCompiler/ResourceCompiler.rc b/Code/Tools/RC/ResourceCompiler/ResourceCompiler.rc index 7fab104d9b..b2f6af7583 100644 --- a/Code/Tools/RC/ResourceCompiler/ResourceCompiler.rc +++ b/Code/Tools/RC/ResourceCompiler/ResourceCompiler.rc @@ -73,7 +73,7 @@ BEGIN VALUE "FileVersion", "1.1.8.6" VALUE "InternalName", "ResourceCompiler" VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "LegalTrademarks", "Lumberyard" + VALUE "LegalTrademarks", "Open 3D Engine" VALUE "OriginalFilename", "rc.exe" VALUE "ProductName", "Resource Compiler" VALUE "ProductVersion", "1.1.8.6" diff --git a/Code/Tools/RC/ResourceCompiler/main.cpp b/Code/Tools/RC/ResourceCompiler/main.cpp index 1289452e53..02dbd406d8 100644 --- a/Code/Tools/RC/ResourceCompiler/main.cpp +++ b/Code/Tools/RC/ResourceCompiler/main.cpp @@ -408,7 +408,7 @@ int rcmain(int argc, char** argv, [[maybe_unused]] char** envp) Config mainConfig; mainConfig.SetConfigKeyRegistry(&rc); - QSettings settings("HKEY_CURRENT_USER\\Software\\Amazon\\Lumberyard\\Settings", QSettings::NativeFormat); + QSettings settings("HKEY_CURRENT_USER\\Software\\Amazon\\O3DE\\Settings", QSettings::NativeFormat); bool enableSourceControl = settings.value("RC_EnableSourceControl", true).toBool(); mainConfig.SetKeyValue(eCP_PriorityCmdline, "nosourcecontrol", enableSourceControl ? "0" : "1"); diff --git a/Code/Tools/RC/ResourceCompilerPC/CMakeLists.txt b/Code/Tools/RC/ResourceCompilerPC/CMakeLists.txt index 5fd28f7e7e..bf582ee26c 100644 --- a/Code/Tools/RC/ResourceCompilerPC/CMakeLists.txt +++ b/Code/Tools/RC/ResourceCompilerPC/CMakeLists.txt @@ -23,7 +23,6 @@ ly_add_target( INCLUDE_DIRECTORIES PUBLIC . - PCH COMPILE_DEFINITIONS PRIVATE RESOURCE_COMPILER diff --git a/Code/Tools/RC/ResourceCompilerScene/Common/MaterialExporter.cpp b/Code/Tools/RC/ResourceCompilerScene/Common/MaterialExporter.cpp index 4a1ee4c5c1..32e13de700 100644 --- a/Code/Tools/RC/ResourceCompilerScene/Common/MaterialExporter.cpp +++ b/Code/Tools/RC/ResourceCompilerScene/Common/MaterialExporter.cpp @@ -306,7 +306,7 @@ Change FBX Setting's \"Update Materials\" to true or modify the associated mater if (index == GFxFramework::MaterialExport::g_materialNotFound) { - AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Unable to find material named %s in mtl file while building FBX to Lumberyard material index table.", nodeName.c_str()); + AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Unable to find material named %s in mtl file while building FBX to Open 3D Engine material index table.", nodeName.c_str()); result += SceneEvents::ProcessingResult::Failure; } table.push_back(index); diff --git a/Code/Tools/RC/ResourceCompilerXML/CMakeLists.txt b/Code/Tools/RC/ResourceCompilerXML/CMakeLists.txt index 3a83c3c20a..77ba46bc7c 100644 --- a/Code/Tools/RC/ResourceCompilerXML/CMakeLists.txt +++ b/Code/Tools/RC/ResourceCompilerXML/CMakeLists.txt @@ -22,7 +22,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE . - PCH BUILD_DEPENDENCIES PRIVATE 3rdParty::Qt::Core diff --git a/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt b/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt index f4d0a18fe2..ac8af3fdaa 100644 --- a/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt +++ b/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt @@ -15,6 +15,8 @@ if (NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) + ly_add_target( NAME FbxSDKWrapper STATIC NAMESPACE AZ diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/FbxMaterialImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/FbxMaterialImporter.cpp index 3ae5828df4..199f476ec0 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/FbxMaterialImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/FbxMaterialImporter.cpp @@ -138,7 +138,7 @@ namespace AZ AZ_TracePrintf(Utilities::WarningWindow, "Opacity has been changed from 0 to full. Some DCC tools ignore the opacity and " "write 0 to indicate opacity is not used. This causes meshes to turn invisible, which is often not the intention so " "the opacity has been set to full automatically. If the intention was for a fully transparent mesh, please update " - "the opacity in Lumberyards material editor."); + "the opacity in Open 3D Engine's material editor."); } material->SetOpacity(opacity); diff --git a/Code/Tools/SceneAPI/SceneData/Groups/MeshGroup.cpp b/Code/Tools/SceneAPI/SceneData/Groups/MeshGroup.cpp index d51aadb2f2..6ba39e6a65 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/MeshGroup.cpp +++ b/Code/Tools/SceneAPI/SceneData/Groups/MeshGroup.cpp @@ -98,9 +98,9 @@ namespace AZ ->Attribute("AutoExpand", true) ->Attribute(Edit::Attributes::NameLabelOverride, "") ->DataElement(AZ_CRC("ManifestName", 0x5215b349), &MeshGroup::m_name, "Name mesh", - "Name the mesh as you want it to appear in the Lumberyard Asset Browser.") + "Name the mesh as you want it to appear in the Open 3D Engine Asset Browser.") ->Attribute("FilterType", DataTypes::IMeshGroup::TYPEINFO_Uuid()) - ->DataElement(Edit::UIHandlers::Default, &MeshGroup::m_nodeSelectionList, "Select meshes", "Select 1 or more meshes to add to this asset in the Lumberyard Asset Browser.") + ->DataElement(Edit::UIHandlers::Default, &MeshGroup::m_nodeSelectionList, "Select meshes", "Select 1 or more meshes to add to this asset in the Open 3D Engine Asset Browser.") ->Attribute("FilterName", "meshes") ->Attribute("FilterType", DataTypes::IMeshData::TYPEINFO_Uuid()) ->DataElement(Edit::UIHandlers::Default, &MeshGroup::m_rules, "", "Add or remove rules to fine-tune the export process.") diff --git a/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.cpp b/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.cpp index 142682ca76..bed8397714 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.cpp +++ b/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.cpp @@ -98,7 +98,7 @@ namespace AZ ->Attribute("AutoExpand", true) ->Attribute(Edit::Attributes::NameLabelOverride, "") ->DataElement(AZ_CRC("ManifestName", 0x5215b349), &SkeletonGroup::m_name, "Name skeleton", - "Name the skeleton as you want it to appear in the Lumberyard Asset Browser.") + "Name the skeleton as you want it to appear in the Open 3D Engine Asset Browser.") ->Attribute("FilterType", DataTypes::ISkeletonGroup::TYPEINFO_Uuid()) ->DataElement("NodeListSelection", &SkeletonGroup::m_selectedRootBone, "Select root bone", "Select the root bone of the skeleton.") ->Attribute("ClassTypeIdFilter", AZ::SceneData::GraphData::RootBoneData::TYPEINFO_Uuid()) diff --git a/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.cpp b/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.cpp index 7b196e19cb..6b16ab14b4 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.cpp +++ b/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.cpp @@ -103,9 +103,9 @@ namespace AZ ->Attribute("AutoExpand", true) ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") ->DataElement(AZ_CRC("ManifestName", 0x5215b349), &SkinGroup::m_name, "Name skin", - "Name the skin as you want it to appear in the Lumberyard Asset Browser.") + "Name the skin as you want it to appear in the Open 3D Engine Asset Browser.") ->Attribute("FilterType", DataTypes::ISkinGroup::TYPEINFO_Uuid()) - ->DataElement(AZ_CRC("ManifestName", 0x5215b349), &SkinGroup::m_nodeSelectionList, "Select skins", "Select 1 or more skins to add to this asset in the Lumberyard Asset Browser.") + ->DataElement(AZ_CRC("ManifestName", 0x5215b349), &SkinGroup::m_nodeSelectionList, "Select skins", "Select 1 or more skins to add to this asset in the Open 3D Engine Asset Browser.") ->Attribute("FilterName", "skins") ->Attribute("FilterVirtualType", Behaviors::SkinGroup::s_skinVirtualType) ->DataElement(Edit::UIHandlers::Default, &SkinGroup::m_rules, "", "Add or remove rules to fine-tune the export process.") diff --git a/Code/Tools/SceneAPI/SceneData/Rules/BlendShapeRule.cpp b/Code/Tools/SceneAPI/SceneData/Rules/BlendShapeRule.cpp index b7f0353f5a..3563375e40 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/BlendShapeRule.cpp +++ b/Code/Tools/SceneAPI/SceneData/Rules/BlendShapeRule.cpp @@ -55,7 +55,7 @@ namespace AZ EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { - editContext->Class("Blend shapes", "Select mesh targets to configure blend shapes at a later time using Lumberyard.") + editContext->Class("Blend shapes", "Select mesh targets to configure blend shapes at a later time using Open 3D Engine.") ->ClassElement(Edit::ClassElements::EditorData, "") ->Attribute("AutoExpand", true) ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") diff --git a/Code/Tools/SceneAPI/SceneData/Rules/MaterialRule.cpp b/Code/Tools/SceneAPI/SceneData/Rules/MaterialRule.cpp index 00538019a2..e9efa7e136 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/MaterialRule.cpp +++ b/Code/Tools/SceneAPI/SceneData/Rules/MaterialRule.cpp @@ -59,7 +59,7 @@ namespace AZ ->ClassElement(Edit::ClassElements::EditorData, "") ->Attribute("AutoExpand", true) ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") - ->DataElement(Edit::UIHandlers::Default, &MaterialRule::m_updateMaterials, "Update materials", "Checking this box will accept changes made in the source file into the Lumberyard asset.") + ->DataElement(Edit::UIHandlers::Default, &MaterialRule::m_updateMaterials, "Update materials", "Checking this box will accept changes made in the source file into the Open 3D Engine asset.") ->DataElement(Edit::UIHandlers::Default, &MaterialRule::m_removeMaterials, "Remove unused materials","Detects and removes material files from the game project that are not present in the source file."); } } diff --git a/Code/Tools/ShaderCacheGen/ShaderCacheGen/ShaderCacheGen.cpp b/Code/Tools/ShaderCacheGen/ShaderCacheGen/ShaderCacheGen.cpp index 2988886d5b..4dbf6a9f90 100644 --- a/Code/Tools/ShaderCacheGen/ShaderCacheGen/ShaderCacheGen.cpp +++ b/Code/Tools/ShaderCacheGen/ShaderCacheGen/ShaderCacheGen.cpp @@ -101,8 +101,9 @@ bool DisplayYesNoMessageBox(const char* title, const char* message) return MessageBox(0, message, title, MB_YESNO) == IDYES; #elif defined(AZ_PLATFORM_MAC) return MessageBox(title, message, CFSTR("Yes"), CFSTR("No")) == kCFUserNotificationDefaultResponse; -#endif +#else return false; +#endif } void DisplayErrorMessageBox(const char* message) @@ -129,10 +130,10 @@ void ClearPlatformCVars(ISystem* pISystem) pISystem->GetIConsole()->ExecuteString("r_ShadersOrbis = 0"); } -bool IsLumberyardRunning() +bool IsO3DERunning() { bool isRunning = false; - const char* mutexName = "LumberyardApplication"; + const char* mutexName = "O3DEApplication"; #if defined(AZ_PLATFORM_WINDOWS) HANDLE mutex = CreateMutex(NULL, TRUE, mutexName); isRunning = GetLastError() == ERROR_ALREADY_EXISTS; @@ -222,17 +223,17 @@ int main_wrapped(int argc, char* argv[]) s_displayMessageBox = false; } - if (IsLumberyardRunning()) + if (IsO3DERunning()) { if (CryStringUtils::stristr(commandLine, "-devmode") == 0) { - DisplayErrorMessageBox("There is already a Lumberyard application running. Cannot start another one!"); + DisplayErrorMessageBox("There is already a Open 3D Engine application running. Cannot start another one!"); return errorCode; } if (s_displayMessageBox) { - if (!DisplayYesNoMessageBox("Too many apps", "There is already a Lumberyard application running\nDo you want to start another one?")) + if (!DisplayYesNoMessageBox("Too many apps", "There is already a Open 3D Engine application running\nDo you want to start another one?")) { return errorCode; } diff --git a/Code/Tools/Standalone/Source/Editor/hex_lua.ico b/Code/Tools/Standalone/Source/Editor/hex_lua.ico index 5bd0dee97f..04682d48bb 100644 --- a/Code/Tools/Standalone/Source/Editor/hex_lua.ico +++ b/Code/Tools/Standalone/Source/Editor/hex_lua.ico @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b291f16009fb4e8611eec975c418d718ff86a77e43fba4a6f025c2e17475fb7 -size 2238 +oid sha256:da0769acdcfeeb65d2824b287edbb2f65daebe7909c1b551c520db1a3b7fa236 +size 108040 diff --git a/Code/Tools/Standalone/Source/StandaloneToolsApplication.cpp b/Code/Tools/Standalone/Source/StandaloneToolsApplication.cpp index 4b181cfb16..d1daac40c3 100644 --- a/Code/Tools/Standalone/Source/StandaloneToolsApplication.cpp +++ b/Code/Tools/Standalone/Source/StandaloneToolsApplication.cpp @@ -97,7 +97,7 @@ namespace StandaloneTools { const int k_processIntervalInSecs = 2; const bool doSDKInitShutdown = true; - EBUS_EVENT(Telemetry::TelemetryEventsBus, Initialize, "LumberyardIDE", k_processIntervalInSecs, doSDKInitShutdown); + EBUS_EVENT(Telemetry::TelemetryEventsBus, Initialize, "O3DE_IDE", k_processIntervalInSecs, doSDKInitShutdown); bool launched = LaunchDiscoveryService(); diff --git a/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp b/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp index 0a78c43473..9012554144 100644 --- a/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp +++ b/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp @@ -31,7 +31,7 @@ namespace AWSCore static AwsApiJobConfigHolder s_configHolder{}; return s_configHolder.GetConfig(nullptr, [](AwsApiJobConfig& config) { - config.userAgent = "/Lumberyard_AwsApiJob"; + config.userAgent = "/O3DE_AwsApiJob"; config.requestTimeoutMs = 30000; config.connectTimeoutMs = 30000; } diff --git a/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp b/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp index ad8b0d61f1..4f94c91dcd 100644 --- a/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp +++ b/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp @@ -130,7 +130,7 @@ TEST_F(AWSCoreSystemComponentTest, GetDefaultJobContext_Call_JobContextIsNotNull TEST_F(AWSCoreSystemComponentTest, GetDefaultConfig_Call_GetConfigWithExpectedValue) { auto actualDefaultConfig = m_coreSystemsComponent->GetDefaultConfig(); - EXPECT_TRUE(actualDefaultConfig->userAgent == "/Lumberyard_AwsApiJob"); + EXPECT_TRUE(actualDefaultConfig->userAgent == "/O3DE_AwsApiJob"); EXPECT_TRUE(actualDefaultConfig->requestTimeoutMs == 30000); EXPECT_TRUE(actualDefaultConfig->connectTimeoutMs == 30000); diff --git a/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp b/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp index fa0f6db9aa..8742872091 100644 --- a/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp +++ b/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp @@ -27,7 +27,7 @@ namespace AWSMetrics AZStd::string IdentityProvider::GetEngineVersion() { static constexpr const char* EngineConfigFilePath = "@root@/engine.json"; - static constexpr const char* EngineVersionJsonKey = "LumberyardVersion"; + static constexpr const char* EngineVersionJsonKey = "O3DEVersion"; AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetDirectInstance(); if (!fileIO) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.h index f26c114af6..e6ac1e3977 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.h @@ -14,7 +14,7 @@ namespace ImageProcessingAtom { - // note: lumberyard is right hand Z up coordinate + // note: O3DE is right hand Z up coordinate // please don't change the order of the enum since we are using it to match the face id defined in AMD's CubemapGen // and they are using left hand Y up coordinate enum CubemapFace diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h index d3b0596fce..b16ae49860 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h @@ -49,7 +49,7 @@ namespace ImageProcessingAtom bool IsExtensionSupported(const char* extension); IImageObject* LoadImageFromFile(const AZStd::string& filename); - // These functions are for loading legacy lumberyard dds files + // These functions are for loading legacy O3DE dds files IImageObject* LoadImageFromFileLegacy(const AZStd::string& filename); IImageObject* LoadImageFromFileStreamLegacy(AZ::IO::SystemFileStream& fileLoadStream); IImageObject* LoadAttachedImageFromDdsFileLegacy(const AZStd::string& filename, IImageObjectPtr originImage); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h index d60c42b7fe..f280d4df48 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h @@ -144,7 +144,7 @@ namespace ImageProcessingAtom AZ::u32 reserved; }; - // Dds header for lumberyard dds format. + // Dds header for O3DE dds format. // It has same size as standard dds header but uses several reserved slots for customized information struct DDS_HEADER_LEGACY { diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index cbe80ffa83..7d82ca5869 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -30,8 +30,6 @@ if(NOT PAL_TRAIT_BUILD_ATOM_ASSET_SHADER_SUPPORTED) INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore @@ -56,8 +54,6 @@ ly_add_target( Source Source/Editor ${pal_source_dir} - PUBLIC - Include COMPILE_DEFINITIONS PRIVATE NOT_USE_CRY_MEMORY_MANAGER @@ -95,8 +91,6 @@ ly_add_target( PRIVATE Source Source/Editor - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE 3rdParty::mcpp diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index f4825bca5b..099e9062cf 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -115,7 +115,7 @@ namespace AZ { // GFX TODO - investigate window creation being part of the GameApplication. - m_nativeWindow = AZStd::make_unique("LumberyardLauncher", AzFramework::WindowGeometry(0, 0, 1920, 1080)); + m_nativeWindow = AZStd::make_unique("O3DELauncher", AzFramework::WindowGeometry(0, 0, 1920, 1080)); AZ_Assert(m_nativeWindow, "Failed to create the game window\n"); m_nativeWindow->Activate(); @@ -378,6 +378,23 @@ namespace AZ { m_simulateTime += deltaTime; m_deltaTime = deltaTime; + + // Temp: When running in the launcher without the legacy renderer + // we need to call RenderTick on the viewport context each frame. + if (m_viewportContext) + { + AZ::ApplicationTypeQuery appType; + ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType); + if (appType.IsGame()) + { + m_viewportContext->RenderTick(); + } + } + } + + int BootstrapSystemComponent::GetTickOrder() + { + return TICK_LAST; } void BootstrapSystemComponent::OnWindowClosed() diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h index 06a3917e13..f655272350 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h @@ -85,6 +85,7 @@ namespace AZ // TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + int GetTickOrder() override; // AzFramework::AssetCatalogEventBus::Handler overrides ... void OnCatalogLoaded(const char* catalogFile) override; diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass index 236957523b..60de5e10b9 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass @@ -32,8 +32,8 @@ } }, { - "Name": "SpotLightShadowmap", - "ShaderInputName": "m_spotLightShadowmaps", + "Name": "ProjectedShadowmap", + "ShaderInputName": "m_projectedShadowmaps", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { @@ -41,8 +41,8 @@ } }, { - "Name": "ExponentialShadowmapSpot", - "ShaderInputName": "m_spotLightExponentialShadowmap", + "Name": "ExponentialShadowmapProjected", + "ShaderInputName": "m_projectedExponentialShadowmap", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass index 7b8d8a7482..79a42b11f7 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass @@ -49,12 +49,12 @@ ] }, { - "Name": "SpotLightShadowmapsPass", - "TemplateName": "SpotLightShadowmapsTemplate", + "Name": "ProjectedShadowmapsPass", + "TemplateName": "ProjectedShadowmapsTemplate", "PassData": { "$type": "RasterPassData", "DrawListTag": "shadow", - "PipelineViewTag": "SpotLightView" + "PipelineViewTag": "ProjectedShadowView" }, "Connections": [ { @@ -84,17 +84,17 @@ ] }, { - "Name": "EsmShadowmapsPassSpot", + "Name": "EsmShadowmapsPassProjected", "TemplateName": "EsmShadowmapsTemplate", "PassData": { "$type": "EsmShadowmapsPassData", - "LightType": "spot" + "LightType": "projected" }, "Connections": [ { "LocalSlot": "DepthShadowmaps", "AttachmentRef": { - "Pass": "SpotLightShadowmapsPass", + "Pass": "ProjectedShadowmapsPass", "Attachment": "Shadowmap" } } @@ -243,16 +243,16 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { - "Pass": "SpotLightShadowmapsPass", + "Pass": "ProjectedShadowmapsPass", "Attachment": "Shadowmap" } }, { - "LocalSlot": "ExponentialShadowmapSpot", + "LocalSlot": "ExponentialShadowmapProjected", "AttachmentRef": { - "Pass": "EsmShadowmapsPassSpot", + "Pass": "EsmShadowmapsPassProjected", "Attachment": "EsmShadowmaps" } }, diff --git a/Gems/Atom/Feature/Common/Assets/Passes/Forward.pass b/Gems/Atom/Feature/Common/Assets/Passes/Forward.pass index ccb567e75f..66cf330fc5 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/Forward.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/Forward.pass @@ -33,8 +33,8 @@ } }, { - "Name": "SpotLightShadowmap", - "ShaderInputName": "m_spotLightShadowmaps", + "Name": "ProjectedShadowmap", + "ShaderInputName": "m_projectedShadowmaps", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { @@ -42,8 +42,8 @@ } }, { - "Name": "ExponentialShadowmapSpot", - "ShaderInputName": "m_spotLightExponentialShadowmap", + "Name": "ExponentialShadowmapProjected", + "ShaderInputName": "m_projectedExponentialShadowmap", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ForwardCheckerboard.pass b/Gems/Atom/Feature/Common/Assets/Passes/ForwardCheckerboard.pass index 45c6da5fe8..13fffd9e08 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ForwardCheckerboard.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ForwardCheckerboard.pass @@ -32,8 +32,8 @@ } }, { - "Name": "SpotLightShadowmap", - "ShaderInputName": "m_spotLightShadowmaps", + "Name": "ProjectedShadowmap", + "ShaderInputName": "m_projectedShadowmaps", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { @@ -41,8 +41,8 @@ } }, { - "Name": "ExponentialShadowmapSpot", - "ShaderInputName": "m_spotLightExponentialShadowmap", + "Name": "ExponentialShadowmapProjected", + "ShaderInputName": "m_projectedExponentialShadowmap", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ForwardMSAA.pass b/Gems/Atom/Feature/Common/Assets/Passes/ForwardMSAA.pass index b3525bd8de..b5d5f9f92c 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ForwardMSAA.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ForwardMSAA.pass @@ -33,8 +33,8 @@ } }, { - "Name": "SpotLightShadowmap", - "ShaderInputName": "m_spotLightShadowmaps", + "Name": "ProjectedShadowmap", + "ShaderInputName": "m_projectedShadowmaps", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { @@ -42,8 +42,8 @@ } }, { - "Name": "ExponentialShadowmapSpot", - "ShaderInputName": "m_spotLightExponentialShadowmap", + "Name": "ExponentialShadowmapProjected", + "ShaderInputName": "m_projectedExponentialShadowmap", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass index 4a6d9b4d25..38a616313b 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass @@ -155,17 +155,17 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { "Pass": "ShadowPass", - "Attachment": "SpotLightShadowmap" + "Attachment": "ProjectedShadowmap" } }, { - "LocalSlot": "SpotLightESM", + "LocalSlot": "ProjectedESM", "AttachmentRef": { "Pass": "ShadowPass", - "Attachment": "SpotLightESM" + "Attachment": "ProjectedESM" } }, { @@ -224,17 +224,17 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { "Pass": "ShadowPass", - "Attachment": "SpotLightShadowmap" + "Attachment": "ProjectedShadowmap" } }, { - "LocalSlot": "SpotLightESM", + "LocalSlot": "ProjectedESM", "AttachmentRef": { "Pass": "ShadowPass", - "Attachment": "SpotLightESM" + "Attachment": "ProjectedESM" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass index 9877d736a8..8131bbdf5d 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass @@ -17,11 +17,11 @@ "SlotType": "Input" }, { - "Name": "SpotLightShadowmap", + "Name": "ProjectedShadowmap", "SlotType": "Input" }, { - "Name": "SpotLightESM", + "Name": "ProjectedESM", "SlotType": "Input" }, { @@ -82,17 +82,17 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { "Pass": "Parent", - "Attachment": "SpotLightShadowmap" + "Attachment": "ProjectedShadowmap" } }, { - "LocalSlot": "ExponentialShadowmapSpot", + "LocalSlot": "ExponentialShadowmapProjected", "AttachmentRef": { "Pass": "Parent", - "Attachment": "SpotLightESM" + "Attachment": "ProjectedESM" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index ac39ddc2f8..3cedd78210 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -217,8 +217,8 @@ "Path": "Passes/EnvironmentCubeMapPipeline.pass" }, { - "Name": "SpotLightShadowmapsTemplate", - "Path": "Passes/SpotLightShadowmaps.pass" + "Name": "ProjectedShadowmapsTemplate", + "Path": "Passes/ProjectedShadowmaps.pass" }, { "Name": "LightCullingRemapTemplate", diff --git a/Gems/Atom/Feature/Common/Assets/Passes/SpotLightShadowmaps.pass b/Gems/Atom/Feature/Common/Assets/Passes/ProjectedShadowmaps.pass similarity index 91% rename from Gems/Atom/Feature/Common/Assets/Passes/SpotLightShadowmaps.pass rename to Gems/Atom/Feature/Common/Assets/Passes/ProjectedShadowmaps.pass index aa4c957965..1bfbea527e 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/SpotLightShadowmaps.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ProjectedShadowmaps.pass @@ -4,8 +4,8 @@ "ClassName": "PassAsset", "ClassData": { "PassTemplate": { - "Name": "SpotLightShadowmapsTemplate", - "PassClass": "SpotLightShadowmapsPass", + "Name": "ProjectedShadowmapsTemplate", + "PassClass": "ProjectedShadowmapsPass", "Slots": [ { "Name": "Shadowmap", diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ShadowParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/ShadowParent.pass index af9e4b15f5..436a1577b6 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ShadowParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ShadowParent.pass @@ -22,11 +22,11 @@ "SlotType": "Output" }, { - "Name": "SpotLightShadowmap", + "Name": "ProjectedShadowmap", "SlotType": "Output" }, { - "Name": "SpotLightESM", + "Name": "ProjectedESM", "SlotType": "Output" }, // SwapChain here is only used to reference the frame height and format @@ -51,16 +51,16 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { - "Pass": "SpotLightShadowmapsPass", + "Pass": "ProjectedShadowmapsPass", "Attachment": "Shadowmap" } }, { - "LocalSlot": "SpotLightESM", + "LocalSlot": "ProjectedESM", "AttachmentRef": { - "Pass": "EsmShadowmapsPassSpot", + "Pass": "EsmShadowmapsPassProjected", "Attachment": "EsmShadowmaps" } } @@ -85,12 +85,12 @@ ] }, { - "Name": "SpotLightShadowmapsPass", - "TemplateName": "SpotLightShadowmapsTemplate", + "Name": "ProjectedShadowmapsPass", + "TemplateName": "ProjectedShadowmapsTemplate", "PassData": { "$type": "RasterPassData", "DrawListTag": "shadow", - "PipelineViewTag": "SpotLightView" + "PipelineViewTag": "ProjectedShadowView" }, "Connections": [ { @@ -120,17 +120,17 @@ ] }, { - "Name": "EsmShadowmapsPassSpot", + "Name": "EsmShadowmapsPassProjected", "TemplateName": "EsmShadowmapsTemplate", "PassData": { "$type": "EsmShadowmapsPassData", - "LightType": "spot" + "LightType": "projected" }, "Connections": [ { "LocalSlot": "DepthShadowmaps", "AttachmentRef": { - "Pass": "SpotLightShadowmapsPass", + "Pass": "ProjectedShadowmapsPass", "Attachment": "Shadowmap" } } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass index 5033a44ea6..415aa2fec0 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass @@ -38,8 +38,8 @@ } }, { - "Name": "SpotLightShadowmap", - "ShaderInputName": "m_spotLightShadowmaps", + "Name": "ProjectedShadowmap", + "ShaderInputName": "m_projectedShadowmaps", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { @@ -47,8 +47,8 @@ } }, { - "Name": "ExponentialShadowmapSpot", - "ShaderInputName": "m_spotLightExponentialShadowmap", + "Name": "ExponentialShadowmapProjected", + "ShaderInputName": "m_projectedExponentialShadowmap", "SlotType": "Input", "ScopeAttachmentUsage": "Shader", "ImageViewDesc": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass index c2c60b7689..32517484f3 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass @@ -17,11 +17,11 @@ "SlotType": "Input" }, { - "Name": "SpotLightShadowmap", + "Name": "ProjectedShadowmap", "SlotType": "Input" }, { - "Name": "SpotLightESM", + "Name": "ProjectedESM", "SlotType": "Input" }, { @@ -64,17 +64,17 @@ } }, { - "LocalSlot": "SpotLightShadowmap", + "LocalSlot": "ProjectedShadowmap", "AttachmentRef": { "Pass": "Parent", - "Attachment": "SpotLightShadowmap" + "Attachment": "ProjectedShadowmap" } }, { - "LocalSlot": "ExponentialShadowmapSpot", + "LocalSlot": "ExponentialShadowmapProjected", "AttachmentRef": { "Pass": "Parent", - "Attachment": "SpotLightESM" + "Attachment": "ProjectedESM" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli index fd78ddc6bd..c47ee2fc8c 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli @@ -18,8 +18,8 @@ #define TILE_DIM_X 16 #define TILE_DIM_Y 16 -// Point, spot, disk, capsule, quad lights, decals -#define NUM_LIGHT_TYPES 6 +// Simple point, simple spot, point(sphere), spot (disk), capsule, quad lights, decals +#define NUM_LIGHT_TYPES 7 uint GetLightListIndex(uint3 groupID, uint gridWidth, int offset) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/MorphTargets/MorphTargetCompression.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/MorphTargets/MorphTargetCompression.azsli index d71074c6cc..3e6e501656 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/MorphTargets/MorphTargetCompression.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/MorphTargets/MorphTargetCompression.azsli @@ -30,6 +30,14 @@ float3 DecodeTBNDelta(uint3 encodedTBN) return float3(encodedTBN) * f - 2.0f; } +float4 DecodeColorDelta(uint4 encodedColor) +{ + // Color deltas are in a range of -1.0 to 1.0 + // 8 bits per channel, 4 channels + float f = 2.0f / 255.0f; + return float4(encodedColor) * f - 1.0f; +} + int3 EncodeFloatsToInts(float3 f, float integerEncoding) { return int3(f * integerEncoding); @@ -39,3 +47,13 @@ float3 DecodeIntsToFloats(int3 i, float inverseIntegerEncoding) { return float3(i) * inverseIntegerEncoding; } + +int4 EncodeFloatsToInts(float4 f, float integerEncoding) +{ + return int4(f * integerEncoding); +} + +float4 DecodeIntsToFloats(int4 i, float inverseIntegerEncoding) +{ + return float4(i) * inverseIntegerEncoding; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassSrg.azsli index 7639eb3d08..14cff21739 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassSrg.azsli @@ -19,8 +19,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass // [GFX TODO][ATOM-2012] adapt to multiple shadowmaps Texture2DArray m_directionalLightShadowmap; Texture2DArray m_directionalLightExponentialShadowmap; - Texture2DArray m_spotLightShadowmaps; - Texture2DArray m_spotLightExponentialShadowmap; + Texture2DArray m_projectedShadowmaps; + Texture2DArray m_projectedExponentialShadowmap; Texture2D m_brdfMap; Sampler LinearSampler diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli index 79c05fbe8b..6b3a9cfada 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli @@ -13,6 +13,12 @@ #pragma once #include +#include + +enum DiskLightFlag +{ + UseConeAngle = 1, +}; void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingData lightingData) { @@ -22,33 +28,42 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat float3 posToLightDir = normalize(posToLight); - // Adjust direction if light emits both direction and is pointing away. - float facing = sign(dot(posToLightDir, -light.m_direction)); - float3 lightDirection = light.m_direction; - if (facing * light.m_bothDirectionsFactor > 0.0 ) - { - lightDirection = -lightDirection; - } - // Reduce the brightness based on how much the disk is facing this pixel. - float angleFalloff = dot(posToLightDir, -lightDirection); + float angleFalloff = dot(posToLightDir, -light.m_direction); // Only calculate shading if light is in range if (falloff < 1.0f && angleFalloff > 0.0f) { + bool useConeAngle = light.m_flags & DiskLightFlag::UseConeAngle; + float3 dirToConeTip; + float dotWithDirection; + + if (useConeAngle) + { + float3 coneTipPosition = light.m_position + light.m_bulbPositionOffset * -light.m_direction; + dirToConeTip = normalize(coneTipPosition - surface.position); + dotWithDirection = dot(dirToConeTip, -normalize(light.m_direction)); + + // If outside the outer cone angle return. + if (dotWithDirection < light.m_cosOuterConeAngle) + { + return; + } + } + // Smoothly adjusts the light intensity so it reaches 0 at light.m_attenuationRadius distance float radiusAttenuation = 1.0 - (falloff * falloff); radiusAttenuation = radiusAttenuation * radiusAttenuation; // Find the distance to the closest point on the disk - float distanceToPlane = dot(posToLight, -lightDirection); + float distanceToPlane = dot(posToLight, -light.m_direction); float distanceToPlane2 = distanceToPlane * distanceToPlane; float pointOnPlaneToLightDistance = sqrt(distanceToLight2 - distanceToPlane2); // pythagorean theorem float pointOnPlaneToDiskDistance = max(pointOnPlaneToLightDistance - light.m_diskRadius, 0.0f); float distanceToDisk2 = pointOnPlaneToDiskDistance * pointOnPlaneToDiskDistance + distanceToPlane2; // Update the light direction based on the edges of the disk as visible from this point instead of the center. - float3 pointOnPlane = -lightDirection * distanceToPlane; + float3 pointOnPlane = -light.m_direction * distanceToPlane; float3 pointOnPlaneToLightDir = normalize(posToLight - pointOnPlane); float3 nearSideDir = normalize(pointOnPlane + pointOnPlaneToLightDir * (pointOnPlaneToLightDistance - light.m_diskRadius)); float3 farSideDir = normalize(pointOnPlane + pointOnPlaneToLightDir * (pointOnPlaneToLightDistance + light.m_diskRadius)); @@ -63,17 +78,52 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // 0 radius disks are unaffected. lightIntensity /= ((light.m_diskRadius / distanceToPlane) + 1.0); + // shadow + float litRatio = 1.0; + + // How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available + float backShadowRatio = 0.0; + if (o_enableShadows) + { + litRatio = ProjectedShadow::GetVisibility( + light.m_shadowIndex, + light.m_position, + surface.position, + -dirToConeTip, + surface.normal); + + // Use backShadowRatio to carry thickness from shadow map for thick mode + backShadowRatio = 1.0 - litRatio; + if (o_transmission_mode == TransmissionMode::ThickObject) + { + backShadowRatio = ProjectedShadow::GetThickness( + light.m_shadowIndex, + surface.position); + } + } + + if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra + { + // Normalize into 0.0 - 1.0 space. + float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); + + // Apply smoothstep + penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); + + lightIntensity *= penumbraMask; + } + // Diffuse contribution - lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir); + lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio; // Tranmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, 0.0); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, 0.0) * litRatio; // Adjust the light direction for specular based on disk size - // Calculate the reflection off the normal from the view lightDirection + // Calculate the reflection off the normal from the view direction float3 reflectionDir = reflect(-lightingData.dirToCamera, surface.normal); - float reflectionDotLight = dot(reflectionDir, -lightDirection); + float reflectionDotLight = dot(reflectionDir, -light.m_direction); // Let 'Intersection' denote the point where the reflection ray intersects the diskLight plane // As such, posToIntersection denotes the vector from pos to the intersection of the reflection ray and the disk plane: @@ -90,21 +140,21 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // then treat that as the reflection plane intersection. float3 posToFarOffPoint = reflectionDir * distanceToPlane * 10000.0; float3 lightToFarOffPoint = posToFarOffPoint - posToLight; - float3 intersectionToFarOffPoint = dot(lightToFarOffPoint, lightDirection) * lightDirection; + float3 intersectionToFarOffPoint = dot(lightToFarOffPoint, light.m_direction) * light.m_direction; posToIntersection = posToFarOffPoint - intersectionToFarOffPoint; } // Calculate a vector from the reflection vector to the light float3 intersectionToLight = posToLight - posToIntersection; - // Adjust the lightDirection to light based on the bulb size + // Adjust the direction to light based on the bulb size posToLight -= intersectionToLight * saturate(light.m_diskRadius / length(intersectionToLight)); // Adjust the intensity of the light based on the bulb size to conserve energy float diskIntensityNormalization = GetIntensityAdjustedByRadiusAndRoughness(surface.roughnessA, light.m_diskRadius, distanceToLight2); // Specular contribution - lightingData.specularLighting += diskIntensityNormalization * GetSpecularLighting(surface, lightingData, lightIntensity, normalize(posToLight)); + lightingData.specularLighting += diskIntensityNormalization * GetSpecularLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; } } @@ -147,7 +197,7 @@ void ValidateDiskLight(ViewSrg::DiskLight light, Surface surface, inout Lighting { float2 randomPoint = GetHammersleyPoint(i, sampleCount); float3 samplePoint = SampleDisk(randomPoint, light); - AddSampleContribution(surface, lightingData, samplePoint, light.m_direction, light.m_bothDirectionsFactor, diffuseAcc, specularAcc, translucentAcc); + AddSampleContribution(surface, lightingData, samplePoint, light.m_direction, 0.0, diffuseAcc, specularAcc, translucentAcc); } lightingData.diffuseLighting += (diffuseAcc / float(sampleCount)) * light.m_rgbIntensityCandelas; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Lights.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Lights.azsli index 37594cf553..2a921f7859 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Lights.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Lights.azsli @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include void ApplyDirectLighting(Surface surface, inout LightingData lightingData) { @@ -28,11 +29,12 @@ void ApplyDirectLighting(Surface surface, inout LightingData lightingData) } if (o_enablePunctualLights) { - ApplyPointLights(surface, lightingData); - ApplySpotLights(surface, lightingData); + ApplySimplePointLights(surface, lightingData); + ApplySimpleSpotLights(surface, lightingData); } if (o_enableAreaLights) { + ApplyPointLights(surface, lightingData); ApplyDiskLights(surface, lightingData); ApplyCapsuleLights(surface, lightingData); ApplyQuadLights(surface, lightingData); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimplePointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimplePointLight.azsli new file mode 100644 index 0000000000..9353095cdd --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimplePointLight.azsli @@ -0,0 +1,55 @@ +/* +* 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 + +void ApplySimplePointLight(ViewSrg::SimplePointLight light, Surface surface, inout LightingData lightingData) +{ + float3 posToLight = light.m_position - surface.position; + float d2 = dot(posToLight, posToLight); // light distance squared + float falloff = d2 * light.m_invAttenuationRadiusSquared; + + // Only calculate shading if light is in range + if (falloff < 1.0f) + { + // Smoothly adjusts the light intensity so it reaches 0 at light.m_attenuationRadius distance + float radiusAttenuation = 1.0 - (falloff * falloff); + radiusAttenuation = radiusAttenuation * radiusAttenuation; + + // Standard quadratic falloff + d2 = max(0.001 * 0.001, d2); // clamp the light to at least 1mm away to avoid extreme values. + float3 lightIntensity = (light.m_rgbIntensityCandelas / d2) * radiusAttenuation; + float3 posToLightDir = normalize(posToLight); + + // Diffuse contribution + lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir); + + // Specular contribution + lightingData.specularLighting += GetSpecularLighting(surface, lightingData, lightIntensity, posToLightDir); + } +} + +void ApplySimplePointLights(Surface surface, inout LightingData lightingData) +{ + lightingData.tileIterator.LoadAdvance(); + + while( !lightingData.tileIterator.IsDone() ) + { + uint currLightIndex = lightingData.tileIterator.GetValue(); + lightingData.tileIterator.LoadAdvance(); + + ViewSrg::SimplePointLight light = ViewSrg::m_simplePointLights[currLightIndex]; + ApplySimplePointLight(light, surface, lightingData); + } +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimpleSpotLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimpleSpotLight.azsli new file mode 100644 index 0000000000..5fee8e60ff --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SimpleSpotLight.azsli @@ -0,0 +1,76 @@ +/* +* 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 + +void ApplySimpleSpotLight(ViewSrg::SimpleSpotLight light, Surface surface, inout LightingData lightingData) +{ + float3 posToLight = light.m_position - surface.position; + + float3 dirToLight = normalize(posToLight); + float dotWithDirection = dot(dirToLight, -normalize(light.m_direction)); + + // If outside the outer cone angle return. + if (dotWithDirection < light.m_cosOuterConeAngle) + { + return; + } + + float d2 = dot(posToLight, posToLight); // light distance squared + float falloff = d2 * light.m_invAttenuationRadiusSquared; + + // Only calculate shading if light is in range + if (falloff < 1.0f) + { + // Smoothly adjusts the light intensity so it reaches 0 at light.m_attenuationRadius distance + float radiusAttenuation = 1.0 - (falloff * falloff); + radiusAttenuation = radiusAttenuation * radiusAttenuation; + + // Standard quadratic falloff + d2 = max(0.001 * 0.001, d2); // clamp the light to at least 1mm away to avoid extreme values. + float3 lightIntensity = (light.m_rgbIntensityCandelas / d2) * radiusAttenuation; + float3 posToLightDir = normalize(posToLight); + + if (dotWithDirection < light.m_cosInnerConeAngle) // in penumbra + { + // Normalize into 0.0 - 1.0 space. + float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); + + // Apply smoothstep + penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); + + lightIntensity *= penumbraMask; + } + + // Diffuse contribution + lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir); + + // Specular contribution + lightingData.specularLighting += GetSpecularLighting(surface, lightingData, lightIntensity, posToLightDir); + } +} + +void ApplySimpleSpotLights(Surface surface, inout LightingData lightingData) +{ + lightingData.tileIterator.LoadAdvance(); + + while( !lightingData.tileIterator.IsDone() ) + { + uint currLightIndex = lightingData.tileIterator.GetValue(); + lightingData.tileIterator.LoadAdvance(); + + ViewSrg::SimpleSpotLight light = ViewSrg::m_simpleSpotLights[currLightIndex]; + ApplySimpleSpotLight(light, surface, lightingData); + } +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SpotLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SpotLight.azsli deleted file mode 100644 index c6ea016938..0000000000 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/SpotLight.azsli +++ /dev/null @@ -1,152 +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 - -void ApplySpotLight(ViewSrg::SpotLight spotLight, Surface surface, inout LightingData lightingData, uint lightIndex) -{ - float3 posToLight = spotLight.m_position - surface.position; - float distanceToLight2 = dot(posToLight, posToLight); // light distance squared - float falloff = distanceToLight2 * spotLight.m_invAttenuationRadiusSquared; - - float3 spotConeTipPosition = spotLight.m_position + spotLight.m_bulbPositionOffset * -spotLight.m_direction; - float3 dirToConeTip = normalize(spotConeTipPosition - surface.position); - float dotWithDirection = dot(dirToConeTip, -normalize(spotLight.m_direction)); - - float3 posToLightDir = normalize(posToLight); - - // Reduce the brightness based on how much the disk is facing this pixel. - float angleFalloff = dot(posToLightDir, -spotLight.m_direction); - - if (falloff < 1.0f && dotWithDirection >= spotLight.m_outerConeAngle && angleFalloff > 0.0) // Only calculate shading if light is in range and in cone. - { - // Smoothly adjusts the light intensity so it reaches 0 at light.m_attenuationRadius distance - float radiusAttenuation = 1.0 - (falloff * falloff); - radiusAttenuation = radiusAttenuation * radiusAttenuation; - - // Find the distance to the closest point on the disk - float distanceToPlane = dot(posToLight,-spotLight.m_direction); - float distanceToPlane2 = distanceToPlane * distanceToPlane; - float pointOnPlaneToLightDistance = sqrt(distanceToLight2 - distanceToPlane2); // pythagorean theorem - float pointOnPlaneToDiskDistance = max(pointOnPlaneToLightDistance - spotLight.m_bulbRadius, 0.0f); - float distanceToDisk2 = pointOnPlaneToDiskDistance * pointOnPlaneToDiskDistance + distanceToPlane2; - - // Update the light direction based on the edges of the disk as visible from this point instead of the center. - float3 pointOnPlane = -spotLight.m_direction * distanceToPlane; - float3 pointOnPlaneToLightDir = normalize(posToLight - pointOnPlane); - float3 nearSideDir = normalize(pointOnPlane + pointOnPlaneToLightDir * (pointOnPlaneToLightDistance - spotLight.m_bulbRadius)); - float3 farSideDir = normalize(pointOnPlane + pointOnPlaneToLightDir * (pointOnPlaneToLightDistance + spotLight.m_bulbRadius)); - posToLightDir = normalize((nearSideDir + farSideDir) * 0.5); - - // Standard quadratic falloff - distanceToDisk2 = max(0.001 * 0.001, distanceToDisk2); // clamp the light to at least 1mm away to avoid extreme values. - float3 lightIntensity = (spotLight.m_rgbIntensityCandelas / distanceToDisk2) * radiusAttenuation * angleFalloff; - - // Adjust brightness based on the disk size relative to its distance. - // The larger the disk is relative to the surface point, the dimmer it becomes. - // 0 radius disks are unaffected. - lightIntensity /= ((spotLight.m_bulbRadius / distanceToPlane) + 1.0); - - // shadow - float litRatio = 1.; - - // How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available - float backShadowRatio = 0.; - if (o_enableShadows) - { - litRatio = SpotLightShadow::GetVisibility( - lightIndex, - surface.position, - -dirToConeTip, - surface.normal); - - // Use backShadowRatio to carry thickness from shadow map for thick mode - backShadowRatio = 1.0 - litRatio; - if (o_transmission_mode == TransmissionMode::ThickObject) - { - backShadowRatio = SpotLightShadow::GetThickness( - lightIndex, - surface.position); - } - } - - float3 dirToLight = normalize(posToLight); - - if (dotWithDirection < spotLight.m_innerConeAngle) // in penumbra - { - // Normalize into 0.0 - 1.0 space. - float penumbraMask = (dotWithDirection - spotLight.m_outerConeAngle) / (spotLight.m_innerConeAngle - spotLight.m_outerConeAngle); - - // Bias the curve towards the inner or outer cone angle - penumbraMask = saturate((spotLight.m_penumbraBias * penumbraMask + penumbraMask) / (spotLight.m_penumbraBias * penumbraMask + 1.0)); - - // Apply smoothstep - penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); - - lightIntensity *= penumbraMask; - } - - lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, dirToLight) * litRatio; - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, dirToLight, backShadowRatio); - - // Calculate the reflection off the normal from the view lightDirection - float3 reflectionDir = reflect(-lightingData.dirToCamera, surface.normal); - float reflectionDotLight = dot(reflectionDir, -spotLight.m_direction); - - // Let 'Intersection' denote the point where the reflection ray intersects the diskLight plane - // As such, posToIntersection denotes the vector from pos to the intersection of the reflection ray and the disk plane: - float3 posToIntersection; - - if (reflectionDotLight >= 0.0001) - { - // Reflection going towards the light - posToIntersection = reflectionDir * distanceToPlane / reflectionDotLight; - } - else - { - // Reflection going away from the light. Choose a point far off and project it on the plane, - // then treat that as the reflection plane intersection. - float3 posToFarOffPoint = reflectionDir * distanceToPlane * 10000.0; - float3 lightToFarOffPoint = posToFarOffPoint - posToLight; - float3 intersectionToFarOffPoint = dot(lightToFarOffPoint, spotLight.m_direction) * spotLight.m_direction; - posToIntersection = posToFarOffPoint - intersectionToFarOffPoint; - } - - // Calculate a vector from the reflection vector to the light - float3 intersectionToLight = posToLight - posToIntersection; - - // Adjust the direction to light based on the bulb size - posToLight -= intersectionToLight * saturate(spotLight.m_bulbRadius / length(intersectionToLight)); - - // Adjust the intensity of the light based on the bulb size to conserve energy - float diskIntensityNormalization = GetIntensityAdjustedByRadiusAndRoughness(surface.roughnessA, spotLight.m_bulbRadius, distanceToLight2); - - lightingData.specularLighting += diskIntensityNormalization * GetSpecularLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; - } -} - -void ApplySpotLights(Surface surface, inout LightingData lightingData) -{ - lightingData.tileIterator.LoadAdvance(); - - while( !lightingData.tileIterator.IsDone() ) - { - uint currLightIndex = lightingData.tileIterator.GetValue(); - lightingData.tileIterator.LoadAdvance(); - - ViewSrg::SpotLight light = ViewSrg::m_spotLights[currLightIndex]; - ApplySpotLight(light, surface, lightingData, currLightIndex); - } -} 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 7639eb3d08..14cff21739 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 @@ -19,8 +19,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass // [GFX TODO][ATOM-2012] adapt to multiple shadowmaps Texture2DArray m_directionalLightShadowmap; Texture2DArray m_directionalLightExponentialShadowmap; - Texture2DArray m_spotLightShadowmaps; - Texture2DArray m_spotLightExponentialShadowmap; + Texture2DArray m_projectedShadowmaps; + Texture2DArray m_projectedExponentialShadowmap; Texture2D m_brdfMap; Sampler LinearSampler diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index 1bbebcc06d..893df85e3e 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -16,11 +16,11 @@ #include "JitterTablePcf.azsli" #include "Shadow.azsli" #include "ShadowmapAtlasLib.azsli" +#include "BicubicPcfFilters.azsli" // Before including this azsli file, a PassSrg must be defined with the following members: // Texture2DArray m_directionalLightShadowmap; // Texture2DArray m_directionalLightExponentialShadowmap; -// Texture2DArray m_spotLightShadowmaps; // Sampler LinearSampler; // This matchs ShadowFilterMethod in ShadowConstants.h @@ -102,6 +102,9 @@ class DirectionalLightShadow // This outputs visibility ratio (from 0.0 to 1.0) for ESM+PCF. float GetVisibilityFromLightEsmPcf(); + float SamplePcfBicubic(); + float SamplePcfBicubic(float3 shadowCoord, uint indexOfCascade); + uint m_lightIndex; float3 m_shadowCoords[ViewSrg::MaxCascadeCount]; float m_slopeBias[ViewSrg::MaxCascadeCount]; @@ -281,6 +284,11 @@ float DirectionalLightShadow::GetVisibilityFromLightPcf() { return GetVisibilityFromLightNoFilter(); } + + if (ViewSrg::m_directionalLightShadows[m_lightIndex].m_pcfFilterMethod == PcfFilterMethod_Bicubic) + { + return SamplePcfBicubic(); + } const float3 lightDirection = normalize(SceneSrg::m_directionalLights[m_lightIndex].m_direction); @@ -404,6 +412,57 @@ float DirectionalLightShadow::GetVisibilityFromLightEsmPcf() return 1.; } +float DirectionalLightShadow::SamplePcfBicubic() +{ + static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds. + static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. + + const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; + const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; + for (uint indexOfCascade = 0; indexOfCascade < cascadeCount; ++indexOfCascade) + { + const float3 shadowCoord = m_shadowCoords[indexOfCascade]; + + if (shadowCoord.x >= 0. && shadowCoord.x * size < size - PixelMargin && + shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin && + shadowCoord.z < 1. - DepthMargin) + { + return SamplePcfBicubic(shadowCoord, indexOfCascade); + } + } + m_debugInfo.m_cascadeIndex = cascadeCount; + return 1.; +} + +float DirectionalLightShadow::SamplePcfBicubic(float3 shadowCoord, uint indexOfCascade) +{ + const uint filteringSampleCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_filteringSampleCount; + const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; + const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; + Texture2DArray shadowmap = PassSrg::m_directionalLightShadowmap; + + SampleShadowMapBicubicParameters param; + param.shadowMap = shadowmap; + param.shadowPos = float3(shadowCoord.xy, indexOfCascade); + param.shadowMapSize = size; + param.invShadowMapSize = rcp(size); + param.comparisonValue = shadowCoord.z; + param.samplerState = SceneSrg::m_hwPcfSampler; + + if (filteringSampleCount <= 4) + { + return SampleShadowMapBicubic_4Tap(param); + } + else if (filteringSampleCount <= 9) + { + return SampleShadowMapBicubic_9Tap(param); + } + else + { + return SampleShadowMapBicubic_16Tap(param); + } +} + float DirectionalLightShadow::GetVisibility( uint lightIndex, float3 shadowCoords[ViewSrg::MaxCascadeCount], diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/SpotLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli similarity index 73% rename from Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/SpotLightShadow.azsli rename to Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 2e5f18d864..e4cb87802a 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/SpotLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -20,23 +20,24 @@ #include "JitterTablePcf.azsli" #include "Shadow.azsli" -// SpotLightShadow calculates lit/shadowed for a spot light. -class SpotLightShadow +// ProjectedShadow calculates shadowed area projected from a light. +class ProjectedShadow { ////////// // public method - //! This calculates visibility of the surface from the spot light. - //! @param lightIndex spot light index + //! This calculates visibility of the surface from a light source. + //! @param viewPosition position of the shadow casting view //! @param worldPosition surface position in the world coordinate. //! @return 1.0 if lit, 0.0 if shadowed. static float GetVisibility( - uint lightIndex, + uint shadowId, + float3 viewPosition, float3 worldPosition, float3 lightDirection, float3 normalVector); - static float GetThickness(uint lightIndex, float3 worldPosition); + static float GetThickness(uint shadowIndex, float3 worldPosition); ////////// // private methods @@ -56,9 +57,9 @@ class SpotLightShadow uint jitterIndex); void SetShadowPosition(); float3 GetAtlasPosition(float2 texturePosition); - static float UnprojectDepth(uint lightIndex, float depthBufferValue); + static float UnprojectDepth(uint shadowIndex, float depthBufferValue); - uint m_lightIndex; + float3 m_viewPosition; uint m_shadowIndex; float3 m_worldPosition; float3 m_lightDirection; @@ -66,28 +67,31 @@ class SpotLightShadow float3 m_shadowPosition; }; -float SpotLightShadow::GetVisibility( - uint lightIndex, +float ProjectedShadow::GetVisibility( + uint shadowIndex, + float3 viewPosition, float3 worldPosition, float3 lightDirection, float3 normalVector) { - SpotLightShadow shadow; - shadow.m_lightIndex = lightIndex; - shadow.m_shadowIndex = ViewSrg::m_spotLights[lightIndex].m_shadowIndex; + // If no shadow, early return. + if (shadowIndex == 0xFFFF) + { + return 1.0; + } + + ProjectedShadow shadow; + shadow.m_viewPosition = viewPosition; + shadow.m_shadowIndex = shadowIndex; shadow.m_worldPosition = worldPosition; shadow.m_lightDirection = lightDirection; shadow.m_normalVector = normalVector; shadow.SetShadowPosition(); - // If no shadow, early return. - if (shadow.m_shadowIndex < 0) - { - return 1.0; - } - float visibility = 1.; - switch (ViewSrg::m_spotLightShadows[shadow.m_shadowIndex].m_shadowFilterMethod) + // Filter method is stored in top 16 bits. + uint filterMethod = ViewSrg::m_projectedShadows[shadow.m_shadowIndex].m_shadowFilterMethod & 0x0000FFFF; + switch (filterMethod) { case ViewSrg::ShadowFilterMethodNone: visibility = shadow.GetVisibilityNoFilter(); @@ -106,9 +110,9 @@ float SpotLightShadow::GetVisibility( return saturate(visibility); } -float SpotLightShadow::UnprojectDepth(uint lightIndex, float depthBufferValue) +float ProjectedShadow::UnprojectDepth(uint shadowIndex, float depthBufferValue) { - // Unproject the perspective matrix that was built in SpotLightFeatureProcessor.cpp + // Unproject the perspective matrix that was built in ProjectedShadowFeatureProcessor.cpp // (Right-hand with non-reversed depth) // Should look something like the following: // [... ... ... ...][x] @@ -117,33 +121,40 @@ float SpotLightShadow::UnprojectDepth(uint lightIndex, float depthBufferValue) // [... ... -1 ...][1] // unprojectConstants contains the A and B values - const float2 unprojectConstants = ViewSrg::m_spotLightShadows[lightIndex].m_unprojectConstants; + const float2 unprojectConstants = ViewSrg::m_projectedShadows[shadowIndex].m_unprojectConstants; return -unprojectConstants.y / (depthBufferValue + unprojectConstants.x); } -float SpotLightShadow::GetThickness(uint lightIndex, float3 worldPosition) +float ProjectedShadow::GetThickness(uint shadowIndex, float3 worldPosition) { - SpotLightShadow shadow; - shadow.m_lightIndex = lightIndex; + // If no shadow, early return. + if (shadowIndex == 0xFFFF) + { + return 0.0; + } + + ProjectedShadow shadow; shadow.m_worldPosition = worldPosition; - shadow.m_shadowIndex = ViewSrg::m_spotLights[lightIndex].m_shadowIndex; + shadow.m_shadowIndex = shadowIndex; shadow.SetShadowPosition(); return shadow.GetThickness(); } -float SpotLightShadow::GetVisibilityNoFilter() +float ProjectedShadow::GetVisibilityNoFilter() { return IsShadowed(m_shadowPosition) ? 0. : 1.; } -float SpotLightShadow::GetVisibilityPcf() +float ProjectedShadow::GetVisibilityPcf() { - if (ViewSrg::m_spotLightShadows[m_shadowIndex].m_pcfFilterMethod == PcfFilterMethod_Bicubic) + // PCF filter method is stored in bottom 16 bits. + const uint pcfFilterMethod = ViewSrg::m_projectedShadows[m_shadowIndex].m_shadowFilterMethod >> 16; + if (pcfFilterMethod == PcfFilterMethod_Bicubic) { return SamplePcfBicubic(); } - const uint predictionCount = ViewSrg::m_spotLightShadows[m_shadowIndex].m_predictionSampleCount; + const uint predictionCount = ViewSrg::m_projectedShadows[m_shadowIndex].m_predictionSampleCount; if (predictionCount <= 1) { @@ -187,7 +198,7 @@ float SpotLightShadow::GetVisibilityPcf() // we calculate the more precious lit ratio in the area. const uint filteringCount = max( predictionCount, - ViewSrg::m_spotLightShadows[m_shadowIndex].m_filteringSampleCount); + ViewSrg::m_projectedShadows[m_shadowIndex].m_filteringSampleCount); for (; jitterIndex < filteringCount; ++jitterIndex) { @@ -204,26 +215,26 @@ float SpotLightShadow::GetVisibilityPcf() return (filteringCount - shadowedCount) * 1. / filteringCount; } -float SpotLightShadow::GetVisibilityEsm() +float ProjectedShadow::GetVisibilityEsm() { static const float PixelMargin = 1.5; // avoiding artifact on the edge of shadowmap. - const uint size = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapSize; + const uint size = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; if (size <= 1) { return 1.; // There is no shadowmap for this light. } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_spotLightExponentialShadowmap; + const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) { const float3 coefficients = float3( - ViewSrg::m_esmsSpot[m_shadowIndex].m_n_f_n, - ViewSrg::m_esmsSpot[m_shadowIndex].m_n_f, - ViewSrg::m_esmsSpot[m_shadowIndex].m_f); + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_n_f_n, + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_n_f, + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_f); if (coefficients.x == 0.) { return 1.; @@ -243,26 +254,26 @@ float SpotLightShadow::GetVisibilityEsm() return 1.; } -float SpotLightShadow::GetVisibilityEsmPcf() +float ProjectedShadow::GetVisibilityEsmPcf() { static const float PixelMargin = 1.5; // avoiding artifact on the edge of shadowmap; - const uint size = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapSize; + const uint size = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; if (size <= 1) { return 1.; // There is no shadowmap for this light. } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_spotLightExponentialShadowmap; + const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) { const float3 coefficients = float3( - ViewSrg::m_esmsSpot[m_shadowIndex].m_n_f_n, - ViewSrg::m_esmsSpot[m_shadowIndex].m_n_f, - ViewSrg::m_esmsSpot[m_shadowIndex].m_f); + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_n_f_n, + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_n_f, + ViewSrg::m_projectedFilterParams[m_shadowIndex].m_f); if (coefficients.x == 0.) { return 1.; @@ -292,18 +303,18 @@ float SpotLightShadow::GetVisibilityEsmPcf() return 1.; } -float SpotLightShadow::GetThickness() +float ProjectedShadow::GetThickness() { static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. - const uint size = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapSize; + const uint size = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; if (size <= 1) { return 0.; } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray shadowmap = PassSrg::m_spotLightShadowmaps; + const Texture2DArray shadowmap = PassSrg::m_projectedShadowmaps; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) @@ -320,17 +331,17 @@ float SpotLightShadow::GetThickness() return 0.; } -float SpotLightShadow::SamplePcfBicubic() +float ProjectedShadow::SamplePcfBicubic() { - const uint filteringSampleCount = ViewSrg::m_spotLightShadows[m_shadowIndex].m_filteringSampleCount; + const uint filteringSampleCount = ViewSrg::m_projectedShadows[m_shadowIndex].m_filteringSampleCount; const float3 atlasPosition = GetAtlasPosition(m_shadowPosition.xy); SampleShadowMapBicubicParameters param; - param.shadowMap = PassSrg::m_spotLightShadowmaps; + param.shadowMap = PassSrg::m_projectedShadowmaps; param.shadowPos = float3(atlasPosition.xy * ViewSrg::m_invShadowmapAtlasSize, atlasPosition.z); param.shadowMapSize = ViewSrg::m_shadowmapAtlasSize; param.invShadowMapSize = ViewSrg::m_invShadowmapAtlasSize; - param.comparisonValue = m_shadowPosition.z; + param.comparisonValue = m_shadowPosition.z - ViewSrg::m_projectedShadows[m_shadowIndex].m_bias; param.samplerState = SceneSrg::m_hwPcfSampler; if (filteringSampleCount <= 4) @@ -347,20 +358,18 @@ float SpotLightShadow::SamplePcfBicubic() } } -bool SpotLightShadow::IsShadowed(float3 shadowPosition) +bool ProjectedShadow::IsShadowed(float3 shadowPosition) { static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. - ViewSrg::SpotLightShadow shadow = ViewSrg::m_spotLightShadows[m_shadowIndex]; - - const uint size = shadow.m_shadowmapSize; + const uint size = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; if (size <= 1) { return false; // There is no shadowmap for this light. } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray shadowmap = PassSrg::m_spotLightShadowmaps; + const Texture2DArray shadowmap = PassSrg::m_projectedShadowmaps; if (shadowPosition.x >= 0 && shadowPosition.x * size < size - PixelMargin && shadowPosition.y >= 0 && shadowPosition.y * size < size - PixelMargin) @@ -370,7 +379,8 @@ bool SpotLightShadow::IsShadowed(float3 shadowPosition) PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; const float depthDiff = depthInShadowmap - shadowPosition.z; - if (depthDiff < -shadow.m_bias) + float bias = ViewSrg::m_projectedShadows[m_shadowIndex].m_bias; + if (depthDiff < -bias) { return true; } @@ -379,23 +389,19 @@ bool SpotLightShadow::IsShadowed(float3 shadowPosition) return false; } -bool SpotLightShadow::IsShadowedWithJitter( +bool ProjectedShadow::IsShadowedWithJitter( float3 jitterUnitX, float3 jitterUnitY, float jitterDepthDiffBase, uint jitterIndex) -{ - ViewSrg::SpotLightShadow shadow = ViewSrg::m_spotLightShadows[m_shadowIndex]; +{ + ViewSrg::ProjectedShadow shadow = ViewSrg::m_projectedShadows[m_shadowIndex]; const float4x4 depthBiasMatrix = shadow.m_depthBiasMatrix; const float boundaryScale = shadow.m_boundaryScale; - ViewSrg::SpotLight spotLight = ViewSrg::m_spotLights[m_lightIndex]; - float3 shadowCasterPosition = spotLight.m_position; - - const float outerConeAngle = spotLight.m_outerConeAngle; const float2 jitterXY = g_jitterTablePcf[jitterIndex]; - const float dist = distance(m_worldPosition, shadowCasterPosition); + const float dist = distance(m_worldPosition, m_viewPosition); const float boundaryRadius = dist * tan(boundaryScale); // jitterWorldXY is the jittering diff vector from the lighted point on the surface // in the world space. It is remarked as "v_J" in the comment @@ -412,18 +418,18 @@ bool SpotLightShadow::IsShadowedWithJitter( return IsShadowed(jitteredShadowmapHomogeneous.xyz / jitteredShadowmapHomogeneous.w); } -void SpotLightShadow::SetShadowPosition() +void ProjectedShadow::SetShadowPosition() { - const float4x4 depthBiasMatrix = ViewSrg::m_spotLightShadows[m_shadowIndex].m_depthBiasMatrix; + const float4x4 depthBiasMatrix = ViewSrg::m_projectedShadows[m_shadowIndex].m_depthBiasMatrix; float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition, 1)); m_shadowPosition = shadowPositionHomogeneous.xyz / shadowPositionHomogeneous.w; } -float3 SpotLightShadow::GetAtlasPosition(float2 texturePosition) +float3 ProjectedShadow::GetAtlasPosition(float2 texturePosition) { - const uint2 originInSlice = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapOriginInSlice; - const uint shadowmapSize = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapSize; - const uint slice = ViewSrg::m_spotLightShadows[m_shadowIndex].m_shadowmapArraySlice; + const uint2 originInSlice = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapOriginInSlice; + const uint shadowmapSize = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; + const uint slice = ViewSrg::m_projectedShadows[m_shadowIndex].m_shadowmapArraySlice; const float2 coordInTexture = texturePosition * shadowmapSize + originInSlice; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli index 5c850dbfeb..5404cf8b69 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli @@ -36,7 +36,36 @@ partial ShaderResourceGroup ViewSrg float2 m_padding; // explicit padding }; - // Point lights + // Simple Point Lights + + struct SimplePointLight + { + float3 m_position; + float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. + float3 m_rgbIntensityCandelas; + float m_padding; // explicit padding. + }; + + StructuredBuffer m_simplePointLights; + uint m_simplePointLightCount; + + // Simple Spot Lights + + struct SimpleSpotLight + { + float3 m_position; + float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. + float3 m_direction; + float m_cosInnerConeAngle; // cosine of the outer cone angle + float3 m_rgbIntensityCandelas; + float m_cosOuterConeAngle; // cosine of the inner cone angle + }; + + StructuredBuffer m_simpleSpotLights; + uint m_simpleSpotLightCount; + + + // Point lights (sphere lights) struct PointLight { @@ -49,47 +78,22 @@ partial ShaderResourceGroup ViewSrg StructuredBuffer m_pointLights; uint m_pointLightCount; - // Spot Lights - - struct SpotLight - { - float3 m_position; - float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. + // Projected Shadows - float3 m_rgbIntensityCandelas; - float m_innerConeAngle; // cosine of the angle from the direction axis at which this light starts to fall off. - - float3 m_direction; // the direction of the spot light - float m_outerConeAngle; // cosine of the angle from the direction axis at which this light no longer has an effect. - - float m_penumbraBias; // bias of the falloff curve between inner and outer cone angles. - - int m_shadowIndex; // index for SpotLightShadow. - - float m_bulbRadius; // Radius disk representing the spot light bulb - float m_bulbPositionOffset; // Amount of offset from the disk of the spot light to the tip of the cone. - }; - - StructuredBuffer m_spotLights; - uint m_spotLightCount; - - struct SpotLightShadow + struct ProjectedShadow { float4x4 m_depthBiasMatrix; uint m_shadowmapArraySlice; // array slice who has shadowmap in the atlas. - uint2 m_shadowmapOriginInSlice; // shadowmap origin in the slice of the atlas. - uint m_shadowmapSize; // width and height of shadowmap - uint m_shadowFilterMethod; + uint m_shadowFilterMethod; // Includes overall filter method in top 16 bits and pcf method in bottom 16 bits. float m_boundaryScale; uint m_predictionSampleCount; uint m_filteringSampleCount; float2 m_unprojectConstants; float m_bias; - uint m_pcfFilterMethod; // Matches with PcfFilterMethod in ShadowConstants.h }; - StructuredBuffer m_spotLightShadows; - StructuredBuffer m_esmsSpot; + StructuredBuffer m_projectedShadows; + StructuredBuffer m_projectedFilterParams; float m_shadowmapAtlasSize; // image size of shadowmap atlas. width and height has the same value. float m_invShadowmapAtlasSize; // reciprocal of the atlas size @@ -113,6 +117,8 @@ partial ShaderResourceGroup ViewSrg uint m_debugFlags; uint m_shadowFilterMethod; float m_far_minus_near; + uint m_pcfFilterMethod; // Matches with PcfFilterMethod in ShadowConstants.h + uint m_padding[3]; }; enum ShadowFilterMethod @@ -135,10 +141,14 @@ partial ShaderResourceGroup ViewSrg { float3 m_position; float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. - float3 m_direction; - float m_bothDirectionsFactor; // 0.0f for one direction, -1.0f for both. float3 m_rgbIntensityCandelas; float m_diskRadius; + float3 m_direction; + uint m_flags; + float m_cosInnerConeAngle; + float m_cosOuterConeAngle; + float m_bulbPositionOffset; + uint m_shadowIndex; }; StructuredBuffer m_diskLights; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrg.azsli index 40bbc965e2..2025e3b81b 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrg.azsli @@ -42,33 +42,19 @@ partial ShaderResourceGroup RayTracingSceneSrg StructuredBuffer m_pointLights; uint m_pointLightCount; - // spot Lights - // [GFX TODO][ATOM-4049] separate SRG for lights and shadows. - struct SpotLight - { - float3 m_position; - float m_invAttenuationRadiusSquared; // radius at which this light no longer has an effect, 1 / radius^2. - float3 m_rgbIntensityCandelas; - float m_innerConeAngle; // cosine of the angle from the direction axis at which this light starts to fall off. - float3 m_direction; // the direction of the spot light - float m_outerConeAngle; // cosine of the angle from the direction axis at which this light no longer has an effect. - float m_penumbraBias; // bias of the falloff curve between inner and outer cone angles. - int m_shadowIndex; // index for SpotLightShadow. - float2 m_padding; - }; - - StructuredBuffer m_spotLights; - uint m_spotLightCount; - - // disk Lights + // disk Lights struct DiskLight { float3 m_position; - float m_invAttenuationRadiusSquared; // radius at which this light no longer has an effect, 1 / radius^2. - float3 m_direction; - float m_bothDirectionsFactor; // 0.0f for one direction, -1.0f for both. + float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. float3 m_rgbIntensityCandelas; - float m_diskRadius; + float m_diskRadius; + float3 m_direction; + uint m_flags; + float m_cosInnerConeAngle; + float m_cosOuterConeAngle; + float m_bulbPositionOffset; + uint m_shadowIndex; }; StructuredBuffer m_diskLights; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.azsl index b3156b8bf6..640491234f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.azsl @@ -24,12 +24,35 @@ enum QuadLightFlag // Copied from QuadLight.azsli. See https://jira.agscollab.co UseFastApproximation = 0x02, // 1 << 1, // Use a fast approximation instead of linearly transformed cosines. }; +enum DiskLightFlag +{ + UseConeAngle = 1, +}; + ShaderResourceGroup PassSrg : SRG_PerPass { // Figure out how to remove duplicate struct definitions. // These are also defined in View.srg // https://jira.agscollab.com/browse/ATOM-3731 + struct SimplePointLight + { + float3 m_position; + float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. + float3 m_rgbIntensityCandelas; + float m_padding; // explicit padding. + }; + + struct SimpleSpotLight + { + float3 m_position; + float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. + float3 m_direction; + float m_cosInnerConeAngle; // cosine of the outer cone angle + float3 m_rgbIntensityCandelas; + float m_cosOuterConeAngle; // cosine of the inner cone angle + }; + struct PointLight { float3 m_position; @@ -38,35 +61,20 @@ ShaderResourceGroup PassSrg : SRG_PerPass float m_bulbRadius; }; - struct SpotLight - { - float3 m_position; - float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. - - float3 m_rgbIntensityCandelas; - float m_innerConeAngle; // cosine of the angle from the direction axis at which this light starts to fall off. - - float3 m_direction; // the direction of the spot light - float m_outerConeAngle; // cosine of the angle from the direction axis at which this light no longer has an effect. - - float m_penumbraBias; // bias of the falloff curve between inner and outer cone angles. - - int m_shadowIndex; // index for SpotLightShadow. - - float m_bulbRadius; // Radius disk representing the spot light bulb - float m_bulbPositionOffset; // Amount of offset from the disk of the spot light to the tip of the cone. - }; - struct DiskLight { float3 m_position; float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2. - float3 m_direction; - float m_bothDirectionsFactor; // 0.0f for one direction, -1.0f for both. float3 m_rgbIntensityCandelas; float m_diskRadius; + float3 m_direction; + uint m_flags; + float m_cosInnerConeAngle; + float m_cosOuterConeAngle; + float m_bulbPositionOffset; + uint m_shadowIndex; }; - + struct CapsuleLight { float3 m_startPoint; // One of the end points of the capsule @@ -103,13 +111,15 @@ ShaderResourceGroup PassSrg : SRG_PerPass LightCullingConstants m_constantData; // Source light data + StructuredBuffer m_simplePointLights; + StructuredBuffer m_simpleSpotLights; StructuredBuffer m_pointLights; - StructuredBuffer m_spotLights; StructuredBuffer m_diskLights; StructuredBuffer m_capsuleLights; StructuredBuffer m_quadLights; + uint m_simplePointLightCount; + uint m_simpleSpotLightCount; uint m_pointLightCount; - uint m_spotLightCount; uint m_diskLightCount; uint m_capsuleLightCount; uint m_quadLightCount; @@ -306,13 +316,19 @@ void CopySharedLightsToMainMemory(uint lightCount, uint groupIndex, uint3 groupI } // Return the minz and maxz of this light in view space -float2 ComputePointLightMinMaxZ(PassSrg::PointLight light, float3 lightPosition) -{ - float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared); +float2 ComputePointLightMinMaxZ(float lightRadius, float3 lightPosition) +{ float2 minmax = lightPosition.z + lightRadius * float2(-1,1) * RH_COORD_SYSTEM_REVERSE; return minmax; } +float2 ComputeSimpleSpotLightMinMax(PassSrg::SimpleSpotLight light, float3 lightPosition) +{ + float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared); + float2 minmax = lightPosition.z + lightRadius * float2(-1, 1) * RH_COORD_SYSTEM_REVERSE; + return minmax; +} + // Return the minz and maxz of this quad light in view space // Quad light must be double sided float2 ComputeQuadLightMinMaxZ_DoubleSided(PassSrg::QuadLight light, float3 lightPosition) @@ -330,16 +346,9 @@ float2 ComputeQuadLightMinMaxZ_SingleSided(PassSrg::QuadLight light, float3 ligh return ComputeQuadLightMinMaxZ_DoubleSided(light, lightPosition); } -float2 ComputeSpotLightMinMax(PassSrg::SpotLight light, float3 lightPosition) -{ - float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared) + light.m_bulbPositionOffset; - float2 minmax = lightPosition.z + lightRadius * float2(-1, 1) * RH_COORD_SYSTEM_REVERSE; - return minmax; -} - float2 ComputeDiskLightMinMax(PassSrg::DiskLight light, float3 lightPosition) { - float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared); + float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared) + light.m_bulbPositionOffset; float2 minmax = lightPosition.z + lightRadius * float2(-1, 1) * RH_COORD_SYSTEM_REVERSE; return minmax; } @@ -375,44 +384,58 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center } } -void CullPointLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents, float2 tile_center_uv) +void CullPointLight(uint lightIndex, float3 lightPosition, float invLightRadius, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) +{ + lightPosition = WorldToView_Point(lightPosition); + bool potentiallyIntersects = TestSphereVsAabbInvSqrt(lightPosition, invLightRadius, aabb_center, aabb_extents); + if (potentiallyIntersects) + { + // Implement and profile fine-grained light culling testing + // https://jira.agscollab.com/browse/ATOM-3732 + + uint inside = 0; + float2 minmax = ComputePointLightMinMaxZ(rsqrt(invLightRadius), lightPosition); + if (IsObjectInsideTile(tileLightData, minmax, inside)) + { + MarkLightAsVisibleInSharedMemory(lightIndex, inside); + } + } +} + +void CullSimplePointLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) +{ + for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_simplePointLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y) + { + PassSrg::SimplePointLight light = PassSrg::m_simplePointLights[lightIndex]; + CullPointLight(lightIndex, light.m_position, light.m_invAttenuationRadiusSquared, tileLightData, aabb_center, aabb_extents); + } +} + +void CullPointLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) { for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_pointLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y) { PassSrg::PointLight light = PassSrg::m_pointLights[lightIndex]; - float3 lightPosition = WorldToView_Point(light.m_position); - bool potentiallyIntersects = TestSphereVsAabbInvSqrt(lightPosition, light.m_invAttenuationRadiusSquared, aabb_center, aabb_extents); - if (potentiallyIntersects) - { - // Implement and profile fine-grained light culling testing - // https://jira.agscollab.com/browse/ATOM-3732 - - uint inside = 0; - float2 minmax = ComputePointLightMinMaxZ(light, lightPosition); - if (IsObjectInsideTile(tileLightData, minmax, inside)) - { - MarkLightAsVisibleInSharedMemory(lightIndex, inside); - } - } + CullPointLight(lightIndex, light.m_position, light.m_invAttenuationRadiusSquared, tileLightData, aabb_center, aabb_extents); } } -void CullSpotLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) +void CullSimpleSpotLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) { - for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_spotLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y) + for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_simpleSpotLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y) { - PassSrg::SpotLight light = PassSrg::m_spotLights[lightIndex]; - float3 lightPosition = WorldToView_Point(light.m_position - light.m_bulbPositionOffset * light.m_direction); + PassSrg::SimpleSpotLight light = PassSrg::m_simpleSpotLights[lightIndex]; + float3 lightPosition = WorldToView_Point(light.m_position); float3 lightDirection = WorldToView_Vector(light.m_direction); - bool potentiallyIntersects = TestSphereVsCone(aabb_center, length(aabb_extents), lightPosition, lightDirection, light.m_outerConeAngle, rsqrt(light.m_invAttenuationRadiusSquared) + light.m_bulbPositionOffset); + bool potentiallyIntersects = TestSphereVsCone(aabb_center, length(aabb_extents), lightPosition, lightDirection, light.m_cosOuterConeAngle, rsqrt(light.m_invAttenuationRadiusSquared)); if (potentiallyIntersects) { // Implement and profile fine-grained light culling testing // https://jira.agscollab.com/browse/ATOM-3732 uint inside = 0; - float2 minmax = ComputeSpotLightMinMax(light, lightPosition); + float2 minmax = ComputeSimpleSpotLightMinMax(light, lightPosition); if (IsObjectInsideTile(tileLightData, minmax, inside)) { MarkLightAsVisibleInSharedMemory(lightIndex, inside); @@ -421,29 +444,36 @@ void CullSpotLights(uint groupIndex, TileLightData tileLightData, float3 aabb_ce } } - void CullDiskLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents) { - for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_diskLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y) { PassSrg::DiskLight light = PassSrg::m_diskLights[lightIndex]; - float3 lightPosition = WorldToView_Point(light.m_position); + float3 lightPosition = WorldToView_Point(light.m_position - light.m_bulbPositionOffset * light.m_direction); float lightRadius = rsqrt(light.m_invAttenuationRadiusSquared) + light.m_diskRadius; float lightRadiusSqr = lightRadius * lightRadius; float aabbRadius = length(aabb_extents); - bool potentiallyIntersects = TestSphereVsAabb(lightPosition, lightRadiusSqr, aabb_center, aabb_extents); + float3 lightDirection = WorldToView_Vector(light.m_direction); - if (potentiallyIntersects && light.m_bothDirectionsFactor == 0) - { - // Only one side is visible, check that we are above the hemisphere - float3 lightDirection = WorldToView_Vector(light.m_direction); - float3 toAABBCenter = aabb_center - lightPosition; - float distanceToLightPlane = dot(lightDirection, toAABBCenter); + bool potentiallyIntersects; + if (light.m_flags & DiskLightFlag::UseConeAngle > 0) + { + potentiallyIntersects = TestSphereVsCone(aabb_center, length(aabb_extents), lightPosition, lightDirection, light.m_cosOuterConeAngle, rsqrt(light.m_invAttenuationRadiusSquared) + light.m_bulbPositionOffset); + } + else + { + potentiallyIntersects = TestSphereVsAabb(lightPosition, lightRadiusSqr, aabb_center, aabb_extents); + + if (potentiallyIntersects) + { + // Only one side is visible, check that we are above the hemisphere + float3 toAABBCenter = aabb_center - lightPosition; + float distanceToLightPlane = dot(lightDirection, toAABBCenter); - potentiallyIntersects = distanceToLightPlane >= -aabbRadius; - } - + potentiallyIntersects = distanceToLightPlane >= -aabbRadius; + } + } + if (potentiallyIntersects) { // Implement and profile fine-grained light culling testing @@ -454,7 +484,7 @@ void CullDiskLights(uint groupIndex, TileLightData tileLightData, float3 aabb_ce if (IsObjectInsideTile(tileLightData, minmax, inside)) { MarkLightAsVisibleInSharedMemory(lightIndex, inside); - } + } } } } @@ -603,11 +633,6 @@ uint WriteCullingDataToMainMemory(uint lightCount, uint groupIndex, uint3 groupI // Point light index << 16 | bitmask contains which bits the light is present in // ... // End of Group -// Spot light index << 16 | bitmask contains which bits the light is present in -// Spot light index << 16 | bitmask contains which bits the light is present in -// Spot light index << 16 | bitmask contains which bits the light is present in -// ... -// End of Group // Disk light index << 16 | bitmask contains which bits the light is present in // Disk light index << 16 | bitmask contains which bits the light is present in // Disk light index << 16 | bitmask contains which bits the light is present in @@ -643,14 +668,19 @@ void MainCS( ClearSharedLightCountWithDoubleBarrier(groupIndex); - CullPointLights(groupIndex, tileLightData, aabb_center, aabb_extents, tileCenterUv); + CullSimplePointLights(groupIndex, tileLightData, aabb_center, aabb_extents); lightCount = WriteCullingDataToMainMemory(lightCount, groupIndex, groupID ); ClearSharedLightCountWithDoubleBarrier(groupIndex); - CullSpotLights(groupIndex, tileLightData, aabb_center, aabb_extents); + CullSimpleSpotLights(groupIndex, tileLightData, aabb_center, aabb_extents); lightCount = WriteCullingDataToMainMemory(lightCount, groupIndex, groupID ); + + ClearSharedLightCountWithDoubleBarrier(groupIndex); + CullPointLights(groupIndex, tileLightData, aabb_center, aabb_extents); + lightCount = WriteCullingDataToMainMemory(lightCount, groupIndex, groupID ); + ClearSharedLightCountWithDoubleBarrier(groupIndex); CullDiskLights(groupIndex, tileLightData, aabb_center, aabb_extents); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.azsl index 68d4238c1a..3f83940189 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.azsl @@ -21,6 +21,9 @@ rootconstant uint s_targetPositionOffset; rootconstant uint s_targetNormalOffset; rootconstant uint s_targetTangentOffset; rootconstant uint s_targetBitangentOffset; +rootconstant uint s_targetColorOffset; + +option bool o_hasColorDeltas = false; void WriteDeltaToAccumulationBuffer(float3 delta, uint offset, uint morphedVertexIndex) { @@ -71,7 +74,6 @@ void MainCS(uint3 thread_id: SV_DispatchThreadID) compressedTangentDelta.x = (delta.m_compressedNormalDeltaZTangentDelta >> 16) & 0x000000FF; compressedTangentDelta.y = (delta.m_compressedNormalDeltaZTangentDelta >> 8) & 0x000000FF; compressedTangentDelta.z = delta.m_compressedNormalDeltaZTangentDelta & 0x000000FF; - // Now that we have the compressed normals and tangents, unpack them and write them to the accumulation buffer float3 normalDelta = DecodeTBNDelta(compressedNormalDelta) * s_weight; @@ -89,5 +91,18 @@ void MainCS(uint3 thread_id: SV_DispatchThreadID) // Now that we have the compressed bitangents, unpack them and write them to the accumulation buffer float3 bitangentDelta = DecodeTBNDelta(compressedBitangentDelta) * s_weight; WriteDeltaToAccumulationBuffer(bitangentDelta, s_targetBitangentOffset, morphedVertexIndex); + + if (o_hasColorDeltas) + { + uint4 compressedColorDelta; + // Colors are in the least significant 24 bits (8 bits per channel) + compressedColorDelta.r = (delta.m_compressedColorDeltaRGBA >> 24) & 0x000000FF; + compressedColorDelta.g = (delta.m_compressedColorDeltaRGBA >> 16) & 0x000000FF; + compressedColorDelta.b = (delta.m_compressedColorDeltaRGBA >> 8) & 0x000000FF; + compressedColorDelta.a = delta.m_compressedColorDeltaRGBA & 0x000000FF; + + float4 colorDelta = DecodeColorDelta(compressedColorDelta) * s_weight; + WriteDeltaToAccumulationBuffer(colorDelta, s_targetColorOffset, morphedVertexIndex); + } } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli index 6baa0ed474..7ec5b43368 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli @@ -33,8 +33,10 @@ struct MorphTargetDelta uint m_compressedNormalDeltaZTangentDelta; // 8 bit padding plus 8 bits per component for bitangent deltas uint m_compressedPadBitangentDeltaXYZ; + // 8 bits per component for color delta + uint m_compressedColorDeltaRGBA; // Extra padding so the struct is 16 byte aligned for structured buffers - uint3 m_pad; + uint2 m_pad; }; // Input to the morph target compute shader diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.azsl index 496c215a00..cae3011688 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.azsl @@ -17,7 +17,9 @@ option enum class SkinningMethod { LinearSkinning, DualQuaternion } o_skinningMethod = SkinningMethod::LinearSkinning; option bool o_applyMorphTargets = false; +option bool o_applyColorMorphTargets = false; +// Apply a morph target delta with three components void ApplyMorphTargetDelta(uint streamOffset, uint vertexIndex, inout float3 modifiedValue) { // Get the start of the current delta @@ -39,6 +41,32 @@ void ApplyMorphTargetDelta(uint streamOffset, uint vertexIndex, inout float3 mod modifiedValue += decodedFloats; } +// Apply a morph target delta with four components + +void ApplyMorphTargetDelta(uint streamOffset, uint vertexIndex, inout float4 modifiedValue) +{ + // Get the start of the current delta + uint offset = streamOffset + vertexIndex * 4; + + // Read in the encoded deltas + uint4 encodedInts; + encodedInts.x = asint(PassSrg::m_skinnedMeshOutputStream[offset]); + encodedInts.y = asint(PassSrg::m_skinnedMeshOutputStream[offset + 1]); + encodedInts.z = asint(PassSrg::m_skinnedMeshOutputStream[offset + 2]); + encodedInts.w = asint(PassSrg::m_skinnedMeshOutputStream[offset + 3]); + + // Since we're done reading, re-set the accumulation to 0 for the next frame + PassSrg::m_skinnedMeshOutputStream[offset] = asfloat(0); + PassSrg::m_skinnedMeshOutputStream[offset + 1] = asfloat(0); + PassSrg::m_skinnedMeshOutputStream[offset + 2] = asfloat(0); + PassSrg::m_skinnedMeshOutputStream[offset + 3] = asfloat(0); + + // Now decode and apply the delta + float4 decodedFloats = DecodeIntsToFloats(encodedInts, InstanceSrg::m_morphTargetDeltaInverseIntegerEncoding); + modifiedValue += decodedFloats; +} + + //! Utility function for vertex shaders to transform vertex tangent, bitangent, and normal vectors into world space based on MikkT conventions. //! Structured like ConstructTBN from TangentSpace.azsli, but uses a float3x3 for the localToWorld matrix. //! It does not flip the bitangent using the w component of the tangent, and instead assumes that the input bitangent is already oriented correctly. @@ -168,6 +196,16 @@ void MainCS(uint3 thread_id: SV_DispatchThreadID) ApplyMorphTargetDelta(InstanceSrg::m_morphTargetTangentDeltaOffset, i, tangent.xyz); ApplyMorphTargetDelta(InstanceSrg::m_morphTargetBitangentDeltaOffset, i, bitangent); } + + if (o_applyColorMorphTargets) + { + float4 color = InstanceSrg::m_sourceColors[i]; + ApplyMorphTargetDelta(InstanceSrg::m_morphTargetColorDeltaOffset, i, color); + PassSrg::m_skinnedMeshOutputStream[InstanceSrg::m_targetColors + i * 4] = color.r; + PassSrg::m_skinnedMeshOutputStream[InstanceSrg::m_targetColors + i * 4 + 1] = color.g; + PassSrg::m_skinnedMeshOutputStream[InstanceSrg::m_targetColors + i * 4 + 2] = color.b; + PassSrg::m_skinnedMeshOutputStream[InstanceSrg::m_targetColors + i * 4 + 3] = color.a; + } switch(o_skinningMethod) { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli index 824325f58e..5a9e44bade 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli @@ -31,21 +31,39 @@ ShaderResourceGroup InstanceSrg : SRG_PerDraw Buffer m_sourceBiTangents; // BITANGENT 0 ByteAddressBuffer m_sourceBlendIndices; // BLENDINDICES 0 Buffer m_sourceBlendWeights; // BLENDWEIGHTS 0 + + // Optional color input, if colors are being morphed by morph targets + Buffer m_sourceColors; // COLOR 0 // Per-instance input StructuredBuffer m_boneTransformsLinear; StructuredBuffer m_boneTransformsDualQuaternion; // Per-instance morph target input + // Offsets to the locations in the accumulation buffer that hold + // the sum of all deltas for vertex 0. Each thread can further offset into the buffer + // using the thread id to find the delta for the vertex the thread is working on. uint m_morphTargetPositionDeltaOffset; uint m_morphTargetNormalDeltaOffset; uint m_morphTargetTangentDeltaOffset; uint m_morphTargetBitangentDeltaOffset; + uint m_morphTargetColorDeltaOffset; + + // Morph target deltas are stored as signed integers in order to make use of + // InterlockedAdd to accumulate them. They are multiplied by the integer + // encoding when encoding from float->int, and must be multiplied + // by the inverse when decoding from int->float float m_morphTargetDeltaInverseIntegerEncoding; // Per-instance output + // Offsets to the locations in the output stream with the skinning result + // for vertex 0. Each thread can further offset into the buffer using + // the thread id to find the output location for the vertex the thread is working on. uint m_targetPositions; uint m_targetNormals; uint m_targetTangents; uint m_targetBiTangents; + + // Optional color output, if colors are being morphed by morph targets + uint m_targetColors; } diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index 91bb1999c2..1b8c0e0987 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -191,7 +191,7 @@ set(FILES Passes/SMAAConvertToPerceptualColor.pass Passes/SMAAEdgeDetection.pass Passes/SMAANeighborhoodBlending.pass - Passes/SpotLightShadowmaps.pass + Passes/ProjectedShadowmaps.pass Passes/SsaoCompute.pass Passes/SsaoHalfRes.pass Passes/SsaoParent.pass @@ -249,7 +249,6 @@ set(FILES ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli - ShaderLib/Atom/Features/PBR/Lights/SpotLight.azsli ShaderLib/Atom/Features/PBR/Microfacet/Brdf.azsli ShaderLib/Atom/Features/PBR/Microfacet/Fresnel.azsli ShaderLib/Atom/Features/PBR/Microfacet/Ggx.azsli @@ -274,7 +273,7 @@ set(FILES ShaderLib/Atom/Features/Shadow/JitterTablePcf.azsli ShaderLib/Atom/Features/Shadow/Shadow.azsli ShaderLib/Atom/Features/Shadow/ShadowmapAtlasLib.azsli - ShaderLib/Atom/Features/Shadow/SpotLightShadow.azsli + ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli ShaderResourceGroups/SceneSrg.azsli ShaderResourceGroups/SceneSrgAll.azsli ShaderResourceGroups/SceneTimeSrg.azsli diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 199463c7b4..93da352c6e 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -31,7 +31,6 @@ ly_add_target( Include Source 3rdParty/ACES - ../External/ImGui COMPILE_DEFINITIONS PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/CoreLightsConstants.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/CoreLightsConstants.h index 534edf1399..cddb2d56dc 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/CoreLightsConstants.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/CoreLightsConstants.h @@ -18,7 +18,7 @@ namespace AZ { namespace Render { - static constexpr float MaxSpotLightConeAngleDegree = 360.f; - static constexpr float MaxSpotLightConeAngleDegreeWithShadow = 170.f; + static constexpr float MaxDiskLightConeAngleDegree = 180.0f; + static constexpr float MaxDiskLightConeAngleDegreeWithShadow = 170.f; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h index 28528c0274..0d6811dedf 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h @@ -169,6 +169,9 @@ namespace AZ //! @param width Boundary width. The shadow is gradually changed the degree of shadowed. //! If width == 0, softening edge is disabled. Units are in meters. virtual void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) = 0; + + //! Sets the shadowmap Pcf method. + virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index 44db942baa..50c0aa2455 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -14,6 +14,7 @@ #include #include +#include namespace AZ { @@ -24,19 +25,29 @@ namespace AZ { struct DiskLightData { + enum Flags + { + UseConeAngle = 0b1, + }; + AZStd::array m_position = { { 0.0f, 0.0f, 0.0f } }; float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations. - AZStd::array m_direction = { { 0.0f, 0.0f, 0.0f } }; - float m_bothDirectionsFactor = 0.0f; // 0.0f if single direction, -1.0f if both directions. + AZStd::array m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } }; float m_diskRadius = 0.0f; // Radius of disk light in meters. - void SetLightEmitsBothDirections(bool isBothDirections) - { - m_bothDirectionsFactor = isBothDirections ? -1.0f : 0.0f; - } + AZStd::array m_direction = { { 1.0f, 0.0f, 0.0f } }; + uint32_t m_flags = 0; // See Flags enum above. + + float m_cosInnerConeAngle = 0.0f; // cosine of inner cone angle + float m_cosOuterConeAngle = 0.0f; // cosine of outer cone angle + float m_bulbPositionOffset = 0.0f; // Distance from the light disk surface to the tip of the cone of the light. m_bulbRadius * tanf(pi/2 - m_outerConeAngle). + uint16_t m_shadowIndex = -1; // index for ProjectedShadowData. A value of 0xFFFF indicates an illegal index. + uint16_t m_padding; // Explicit padding. }; + static constexpr size_t size = sizeof(DiskLightData); + //! DiskLightFeatureProcessorInterface provides an interface to acquire, release, and update a disk light. This is necessary for code outside of //! the Atom features gem to communicate with the DiskLightFeatureProcessor. class DiskLightFeatureProcessorInterface @@ -55,21 +66,46 @@ namespace AZ //! Creates a new LightHandle by copying data from an existing LightHandle. virtual LightHandle CloneLight(LightHandle handle) = 0; + // Generic Disk Light Settings + //! Sets the intensity in RGB candela for a given LightHandle. virtual void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) = 0; //! Sets the position for a given LightHandle. virtual void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) = 0; //! Sets the direction for a given LightHandle. virtual void SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) = 0; - //! Sets if the disk light emits light in both directions for a given LightHandle. - virtual void SetLightEmitsBothDirections(LightHandle handle, bool lightEmitsBothDirections) = 0; //! Sets the radius in meters at which the provided LightHandle will no longer have an effect. virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0; //! Sets the disk radius for the provided LightHandle. virtual void SetDiskRadius(LightHandle handle, float radius) = 0; + // Cone Angle Settings + + //! Sets whether the disk should constrain its light to a cone. (use SetInnerConeAngle and SetOuterConeAngle to set cone angle parameters) + virtual void SetConstrainToConeLight(LightHandle handle, bool useCone) = 0; + //! Sets the inner and outer cone angles in radians. + virtual void SetConeAngles(LightHandle handle, float innerRadians, float outerRadians) = 0; + + // Shadow Settings + + //! Sets if shadows are enabled + virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0; + //! Sets the shadowmap size (width and height) of the light. + virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0; + //! Specifies filter method of shadows. + virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0; + //! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on the boundary. 0 disables softening. + virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0; + //! Sets sample count to predict boundary of shadow (up to 16). It will be clamped to be less than or equal to the filtering sample count. + virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0; + //! Sets sample count for filtering of shadow boundary (up to 64) + virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; + //! Sets the shadowmap Pcf (percentage closer filtering) method. + virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; + //! Sets all of the the disk data for the provided LightHandle. virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0; + }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h index a2702b262f..bd324ac1d7 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h @@ -41,7 +41,7 @@ namespace AZ Count }; - enum class PcfMethod : uint32_t + enum class PcfMethod : uint16_t { BoundarySearch = 0, // Performs a variable number of taps, first to determine if we are on a shadow boundary, then the remaining taps are to find the occlusion amount Bicubic, // Uses a fixed size Pcf kernel with kernel weights set to approximate bicubic filtering diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimplePointLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimplePointLightFeatureProcessorInterface.h new file mode 100644 index 0000000000..c2a286d15d --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimplePointLightFeatureProcessorInterface.h @@ -0,0 +1,49 @@ +/* +* 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 +{ + class Vector3; + + namespace Render + { + //! SimplePointLightFeatureProcessorInterface provides an interface to acquire, release, and update a point light. + class SimplePointLightFeatureProcessorInterface + : public RPI::FeatureProcessor + { + public: + AZ_RTTI(AZ::Render::SimplePointLightFeatureProcessorInterface, "{B6FABD69-ED5B-4D6C-8695-27CB95D13CE4}", AZ::RPI::FeatureProcessor); + + using LightHandle = RHI::Handle; + static constexpr PhotometricUnit PhotometricUnitType = PhotometricUnit::Candela; + + //! Creates a new point light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no longer needed. + virtual LightHandle AcquireLight() = 0; + //! Releases a LightHandle which removes the point light. + virtual bool ReleaseLight(LightHandle& handle) = 0; + //! Creates a new LightHandle by copying data from an existing LightHandle. + virtual LightHandle CloneLight(LightHandle handle) = 0; + + //! Sets the intensity in RGB candela for a given LightHandle. + virtual void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) = 0; + //! Sets the position for a given LightHandle. + virtual void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) = 0; + //! Sets the radius in meters at which the provided LightHandle will no longer have an effect. + virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimpleSpotLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimpleSpotLightFeatureProcessorInterface.h new file mode 100644 index 0000000000..78ad25cc2c --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SimpleSpotLightFeatureProcessorInterface.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 + +#include +#include + +namespace AZ +{ + class Vector3; + + namespace Render + { + //! SimpleSpotLightFeatureProcessorInterface provides an interface to acquire, release, and update a simple spot light. + class SimpleSpotLightFeatureProcessorInterface + : public RPI::FeatureProcessor + { + public: + AZ_RTTI(AZ::Render::SimpleSpotLightFeatureProcessorInterface, "{1DE04BF2-DD8F-437C-9B6D-4BDAC4BE2BAC}", AZ::RPI::FeatureProcessor); + + using LightHandle = RHI::Handle; + static constexpr PhotometricUnit PhotometricUnitType = PhotometricUnit::Candela; + + //! Creates a new spot light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no longer needed. + virtual LightHandle AcquireLight() = 0; + //! Releases a LightHandle which removes the spot light. + virtual bool ReleaseLight(LightHandle& handle) = 0; + //! Creates a new LightHandle by copying data from an existing LightHandle. + virtual LightHandle CloneLight(LightHandle handle) = 0; + + //! Sets the intensity in RGB candela for a given LightHandle. + virtual void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) = 0; + //! Sets the position for a given LightHandle. + virtual void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) = 0; + //! Sets the direction for a given LightHandle. + virtual void SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) = 0; + //! Sets the radius in meters at which the provided LightHandle will no longer have an effect. + virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0; + //! Sets the inner and outer cone angles in radians. + virtual void SetConeAngles(LightHandle handle, float innerRadians, float outerRadians) = 0; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h deleted file mode 100644 index a237bca627..0000000000 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h +++ /dev/null @@ -1,110 +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 -#include - -namespace AZ -{ - class Color; - class Vector3; - - namespace Render - { - struct SpotLightData - { - AZStd::array m_position = { { 0.0f, 0.0f, 0.0f } }; - float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations. - - AZStd::array m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } }; - float m_innerConeAngle; // cosine of the angle from the direction axis at which this light starts to fall off. - - AZStd::array m_direction = { { 1.0f, 0.0f, 0.0f } }; - float m_outerConeAngle; // cosine of the angle from the direction axis at which this light no longer has an effect. - - float m_penumbraBias = 0.0f; // controls biasing the falloff curve between inner and outer cone angles. - - int32_t m_shadowIndex = -1; // index for SpotLightShadowData. - // a minus value indicates an illegal index. - - float m_bulbRadius = 0.0f; // Size of the disk in meters representing the spot light bulb. - - float m_bulbPostionOffset = 0.0f; // Distance from the light disk surface to the tip of the cone of the light. m_bulbRadius * tanf(pi/2 - m_outerConeAngle). - }; - - //! SpotLightFeatureProcessorInterface provides an interface to acquire, release, and update a spot light. This is necessary for code outside of - //! the Atom features gem to communicate with the SpotLightFeatureProcessor. - class SpotLightFeatureProcessorInterface - : public RPI::FeatureProcessor - { - public: - AZ_RTTI(AZ::Render::SpotLightFeatureProcessorInterface, "{9424429B-C5E9-4CF2-9512-7911778E2836}", AZ::RPI::FeatureProcessor); - - using LightHandle = RHI::Handle; - - //! Creates a new spot light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no longer needed. - virtual LightHandle AcquireLight() = 0; - //! Releases a LightHandle which removes the spot light. - virtual bool ReleaseLight(LightHandle& handle) = 0; - //! Creates a new LightHandle by copying data from an existing LightHandle. - virtual LightHandle CloneLight(LightHandle handle) = 0; - - //! Sets the intensity in RGB candela for a given LightHandle. - virtual void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) = 0; - //! Sets the position of the spot light. - virtual void SetPosition(LightHandle handle, const Vector3& lightPosition) = 0; - //! Sets the direction of the spot light. direction should be normalized. - virtual void SetDirection(LightHandle handle, const Vector3& direction) = 0; - //! Sets the bulb radius of the spot light in meters. - virtual void SetBulbRadius(LightHandle handle, float bulbRadius) = 0; - //! Sets the inner and outer cone angles in degrees. - virtual void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) = 0; - //! Sets a -1 to +1 value that adjusts the bias of the interpolation of light intensity from the inner cone to the outer. - virtual void SetPenumbraBias(LightHandle handle, float penumbraBias) = 0; - //! Sets the radius in meters at which the provided LightHandle will no longer have an effect. - virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0; - //! Sets the shadowmap size (width and height) of the light. - virtual void SetShadowmapSize(LightHandle handle, ShadowmapSize shadowmapSize) = 0; - //! Sets the shadowmap Pcf method. - virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; - - //! This specifies filter method of shadows. - //! @param handle the light handle. - //! @param method filter method. - virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0; - - //! This specifies the width of boundary between shadowed area and lit area. - //! @param handle the light handle. - //! @param width Boundary width. The degree of shadowed gradually changes on the boundary. - //! If width == 0, softening edge is disabled. Units are in degrees. - virtual void SetShadowBoundaryWidthAngle(LightHandle handle, float boundaryWidthDegree) = 0; - - //! This sets sample count to predict boundary of shadow. - //! @param handle the light handle. - //! @param count Sample Count for prediction of whether the pixel is on the boundary (up to 16) - //! The value should be less than or equal to m_filteringSampleCount. - virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0; - - //! This sets sample count for filtering of shadow boundary. - //! @param handle the light handle. - //! @param count Sample Count for filtering (up to 64) - virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; - - //! Sets all of the the spot light data for the provided LightHandle. - virtual void SetSpotLightData(LightHandle handle, const SpotLightData& data) = 0; - }; - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/MorphTargets/MorphTargetInputBuffers.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/MorphTargets/MorphTargetInputBuffers.h index 8e5d91198f..56ecd7de4d 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/MorphTargets/MorphTargetInputBuffers.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/MorphTargets/MorphTargetInputBuffers.h @@ -63,6 +63,7 @@ namespace AZ float m_maxDelta; uint32_t m_vertexCount; uint32_t m_positionOffset; + bool m_hasColorDeltas; }; namespace MorphTargetConstants @@ -82,6 +83,7 @@ namespace AZ uint32_t m_accumulatedNormalDeltaOffsetInBytes; uint32_t m_accumulatedTangentDeltaOffsetInBytes; uint32_t m_accumulatedBitangentDeltaOffsetInBytes; + uint32_t m_accumulatedColorDeltaOffsetInBytes; }; }// Render diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl index cbb9dc945c..420fe518f2 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl @@ -148,7 +148,7 @@ // } // // As you can see, this macro pattern allows us to add a member to Box or Cylinder by adding a single line to BoxParams.inl or CylinderParams.inl -// Because of the number of classes an boiler plate code involved in creating Lumberyard Component, this macro system allows us to change one line +// Because of the number of classes an boiler plate code involved in creating Open 3D Engine Component, this macro system allows us to change one line // in one file instead of changing over a dozens of lines in half a dozen files. // // ___________________________________________________________________________________________________________________________________________________ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h new file mode 100644 index 0000000000..97a7228386 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h @@ -0,0 +1,72 @@ +/* +* 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 +#include + +namespace AZ::Render +{ + //! This feature processor handles projected shadows for various lights. + class ProjectedShadowFeatureProcessorInterface + : public RPI::FeatureProcessor + { + public: + + AZ_RTTI(AZ::Render::ProjectedShadowFeatureProcessorInterface, "{C5651D73-3448-4D76-91C0-0E636A197F63}", AZ::RPI::FeatureProcessor); + + using ShadowId = RHI::Handle; + static constexpr float MaxProjectedShadowRadians = AZ::DegToRad(150.0f); + + //! Used in SetShadowProperties() to set several related shadow properties in one function call. + struct ProjectedShadowDescriptor + { + Transform m_transform = Transform::CreateIdentity(); + float m_nearPlaneDistance = 0.01f; + float m_farPlaneDistance = 10000.0f; + float m_aspectRatio = 1.0f; + float m_fieldOfViewYRadians = DegToRad(90.0f); + }; + + //! Creates a new projected shadow and returns a handle that can be used to reference it later. + virtual ShadowId AcquireShadow() = 0; + //! Releases a projected shadow given its ID. + virtual void ReleaseShadow(ShadowId id) = 0; + //! Sets the world space transform of where the shadow is cast from + virtual void SetShadowTransform(ShadowId id, Transform transform) = 0; + //! Sets the near and far plane distances for the shadow. + virtual void SetNearFarPlanes(ShadowId id, float nearPlaneDistance, float farPlaneDistance) = 0; + //! Sets the aspect ratio for the shadow. + virtual void SetAspectRatio(ShadowId id, float aspectRatio) = 0; + //! Sets the field of view for the shadow in radians in the Y direction. + virtual void SetFieldOfViewY(ShadowId id, float fieldOfView) = 0; + //! Sets the maximum resolution of the shadow map + virtual void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) = 0; + //! Sets the shadowmap Pcf method. + virtual void SetPcfMethod(ShadowId id, PcfMethod method) = 0; + //! Sets the shadow filter method + virtual void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) = 0; + //! Sets the width of boundary between shadowed area and lit area. + virtual void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) = 0; + //! Sets the sample count to predict the boundary of the shadow. Max 16, should be less than filtering sample count. + virtual void SetPredictionSampleCount(ShadowId id, uint16_t count) = 0; + //! Sets the sample count for filtering of the shadow boundary, max 64. + virtual void SetFilteringSampleCount(ShadowId id, uint16_t count) = 0; + //! Sets all of the shadow properites in one call + virtual void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) = 0; + //! Gets the current shadow properties. Useful for updating several properties at once in SetShadowProperties() without having to set every property. + virtual const ProjectedShadowDescriptor& GetShadowProperties(ShadowId id) = 0; + }; +} diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h index 6970e92da6..54ac19e87e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h @@ -57,7 +57,7 @@ namespace AZ struct SkinnedSubMeshSharedViews { RPI::BufferAssetView m_indexBufferView; - AZStd::array < RPI::BufferAssetView, static_cast(SkinnedMeshStaticVertexStreams::NumVertexStreams)> m_staticStreamViews; + AZStd::array (SkinnedMeshStaticVertexStreams::NumVertexStreams)> m_staticStreamViews; }; @@ -85,7 +85,7 @@ namespace AZ uint32_t GetVertexCount() const; //! Set the index buffer asset - void SetIndexBuffer(const Data::Asset bufferAsset); + void SetIndexBufferAsset(const Data::Asset bufferAsset); //! Create the index buffer. SetIndexCount must be called first as CreateIndexBuffer depends on that to know the number of indices to create. //! @param data The indices to be used for the index buffer. The index buffer is used by the target skinned model, but is not modified during skinning so it is shared between all instances of the same skinned mesh. @@ -126,19 +126,31 @@ namespace AZ //! Get the MorphTargetInputBuffers for all the morph targets that can be applied to an instance of this skinned mesh const AZStd::vector>& GetMorphTargetInputBuffers() const; - //! Sets the input for an input vertex stream from an existing buffer asset. + //! Sets the input vertex stream from an existing buffer asset. void SetSkinningInputBufferAsset(const Data::Asset bufferAsset, SkinnedMeshInputVertexStreams inputStream); + //! Sets the static vertex stream from an existing buffer asset. + void SetStaticBufferAsset(const Data::Asset bufferAsset, SkinnedMeshStaticVertexStreams staticStream); + //! Returns the BufferAsset of an input vertex stream. const Data::Asset& GetSkinningInputBufferAsset(SkinnedMeshInputVertexStreams stream) const; //! Calls RPI::Buffer::WaitForUpload for each buffer in the lod. void WaitForUpload(); + //! Returns true if this lod has a morphed color stream + bool HasDynamicColors() const; + + //! Sets the model lod asset for the underlying lod + void SetModelLodAsset(const Data::Asset& modelLodAsset); + private: void CreateSharedSubMeshBufferViews(); + //! The lod asset from the underlying mesh + Data::Asset m_modelLodAsset; + //! One BufferAsset for each input vertex stream AZStd::array, static_cast(SkinnedMeshInputVertexStreams::NumVertexStreams)> m_inputBufferAssets; //! One buffer for each input vertex stream @@ -172,6 +184,11 @@ namespace AZ uint32_t m_indexCount = 0; //! Total number of vertices for the entire lod uint32_t m_vertexCount = 0; + + //! Bool for keeping track of whether or not this lod has morphed colors + bool m_hasDynamicColors = false; + //! Bool for keeping track of whether or not this lod has a static color stream + bool m_hasStaticColors = false; }; //! Container for all the buffers and views needed for per-source model input to both the skinning shader and subsequent mesh shaders diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshShaderOptions.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshShaderOptions.h index e57f25c2c0..ba95d3464f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshShaderOptions.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshShaderOptions.h @@ -28,6 +28,7 @@ namespace AZ { SkinningMethod m_skinningMethod = SkinningMethod::LinearSkinning; bool m_applyMorphTargets = false; + bool m_applyColorMorphTargets = false; }; } } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshVertexStreams.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshVertexStreams.h index b2087c999f..bcd20733b2 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshVertexStreams.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshVertexStreams.h @@ -33,6 +33,8 @@ namespace AZ BiTangent, BlendIndices, BlendWeights, + // Optional + Color, NumVertexStreams }; @@ -43,6 +45,8 @@ namespace AZ Normal, Tangent, BiTangent, + // Optional + Color, NumVertexStreams }; @@ -51,6 +55,8 @@ namespace AZ enum class SkinnedMeshStaticVertexStreams : uint8_t { UV_0, + // Optional + Color, NumVertexStreams }; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h new file mode 100644 index 0000000000..3e9e58d29e --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h @@ -0,0 +1,166 @@ +/* +* 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 AZ::Render +{ + //! MultiSparseVector works similarly to SparseVector, but supports multiple underlying vectors + //! templated to several different types. A separate underlying vector is created for each template + //! type and elements are reserved and released in all vectors simultaneously. Each type can be + //! retrieved individually by index with GetElement(index) where the first Type is + //! ArrayIndex 0, the next Type is ArrayIndex 1 etc. + //! See SparseVector.h for more details. + + template + class MultiSparseVector + { + public: + + MultiSparseVector(); + + //! Reserves elements in the underlying vectors and returns the index to those elements. + size_t Reserve(); + + //! Releases elements with the given index so they can be reused. + void Release(size_t index); + + //! Clears all the data from the underlying vectors and resets the size to 0 + void Clear(); + + //! Returns the size of the underlying vectors. This is not the same as the number of + //! valid elements in the vectors since there can be empty slots. + size_t GetSize() const; + + //! Returns a reference to the element at a given index in the ArrayIndex vector. + template + auto& GetElement(size_t index); + + //! Returns a pointer to the raw data for the ArrayIndex vector. + template + auto* GetRawData() const; + + private: + + static constexpr size_t NoFreeSlot = -1; + static constexpr size_t InitialReservedCount = 128; + + using Fn = void(&)(AZStd::vector& ...); + + // Variadic convenience functions + + template + static void ClearFunction(Args&... args) + { + (args.clear(), ...); + } + + template + static void EmplaceBackFunction(Args&... args) + { + (args.emplace_back(), ...); + } + + template + static void ReserveCapacityFunction(Args&... args) + { + (args.reserve(InitialReservedCount), ...); + } + + template + static void InitializeElement(size_t index, T& container) + { + container.at(index) = {}; + } + + template + static void DeleteElement(size_t index, T& container) + { + AZStd::destroy_at(&container.at(index)); + } + + size_t m_nextFreeSlot = NoFreeSlot; + AZStd::tuple...> m_data; + }; + + template + MultiSparseVector::MultiSparseVector() + { + static_assert(sizeof(AZStd::tuple_element_t<0, AZStd::tuple>) >= sizeof(size_t), + "Data stored in the first element of MultiSparseVector must be at least as large as a size_t."); + + // Reserve some initial capacity in the vectors based on InitialReservedCount. + AZStd::apply(static_cast(ReserveCapacityFunction), m_data); + } + + template + inline size_t MultiSparseVector::Reserve() + { + size_t slotToReturn = -1; + if (m_nextFreeSlot != NoFreeSlot) + { + // If there's a free slot, then use that space and update the linked list of free slots. + slotToReturn = m_nextFreeSlot; + m_nextFreeSlot = reinterpret_cast(GetElement<0>(m_nextFreeSlot)); + AZStd::apply([&](auto&... args){ (InitializeElement(slotToReturn, args), ...); }, m_data); + } + else + { + // If there's no free slot, append on the end. + slotToReturn = GetSize(); + AZStd::apply(static_cast(EmplaceBackFunction), m_data); + } + return slotToReturn; + } + + template + inline void MultiSparseVector::Release(size_t index) + { + AZ_Assert(index < GetSize(), "MultiSparseVector::Release() index out of bounds."); + if (index < GetSize()) + { + // Explicitly destruct the released elements and update the linked list of free slots. + AZStd::apply([&](auto&... args){ (DeleteElement(index, args), ...); }, m_data); + reinterpret_cast(GetElement<0>(index)) = m_nextFreeSlot; + m_nextFreeSlot = index; + } + } + + template + void MultiSparseVector::Clear() + { + AZStd::apply(static_cast(ClearFunction), m_data); + m_nextFreeSlot = NoFreeSlot; + } + + template + size_t MultiSparseVector::GetSize() const + { + return AZStd::get<0>(m_data).size(); + } + + template + template + auto& MultiSparseVector::GetElement(size_t index) + { + return AZStd::get(m_data).at(index); + } + + template + template + auto* MultiSparseVector::GetRawData() const + { + return AZStd::get(m_data).data(); + } +} diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h new file mode 100644 index 0000000000..a11f4de466 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h @@ -0,0 +1,126 @@ +/* +* 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 AZ::Render +{ + //! SparseVector stores elements in a vector under the hood, but allows for empty slots in the + //! vector. This means that elements can be added or removed without affecting the location of + //! other elements. When a new element is reserved in the SparseVector, it will use a free slot + //! if available. Otherwise, it will push the data onto the end of the vector. + //! + //! This class works by storing a linked list of elements in the empty slot, as well as an index + //! to the first empty slot. Since the linked list uses size_t for its type, this class must be + //! templated to a class that is at least sizeof(size_t). + + template + class SparseVector + { + public: + + SparseVector(); + + //! Reserves an element in the underlying vector and returns the index to that element. + size_t Reserve(); + + //! Releases an element with the given index so it can be reused. + void Release(size_t index); + + //! Clears all the data from the underlying vector and resets the size to 0 + void Clear(); + + //! Returns the size of the underlying vector. This is not the same as the number of + //! valid elements in the vector since there can be empty slots. + size_t GetSize() const; + + //! Returns a reference to the element at a given index + T& GetElement(size_t index); + + //! Returns a pointer to the raw data vector. + const T* GetRawData() const; + + private: + + static constexpr size_t NoFreeSlot = -1; + static constexpr size_t InitialReservedCount = 128; + + size_t m_nextFreeSlot = NoFreeSlot; + AZStd::vector m_data; + }; + + template + SparseVector::SparseVector() + { + static_assert(sizeof(T) >= sizeof(size_t), "Data stored in SparseVector must be at least as large as a size_t."); + m_data.reserve(InitialReservedCount); + } + + template + inline size_t SparseVector::Reserve() + { + size_t slotToReturn = -1; + if (m_nextFreeSlot != NoFreeSlot) + { + // If there's a free slot, then use that space and update the linked list of free slots. + slotToReturn = m_nextFreeSlot; + m_nextFreeSlot = reinterpret_cast(m_data.at(m_nextFreeSlot)); + m_data.at(slotToReturn) = T(); + } + else + { + // If there's no free slot, append on the end. + slotToReturn = m_data.size(); + m_data.emplace_back(); + } + return slotToReturn; + } + + template + inline void SparseVector::Release(size_t index) + { + if (index < m_data.size()) + { + // Explicitly destruct the released element and update the linked list of free slots. + m_data.at(index).~T(); + reinterpret_cast(m_data.at(index)) = m_nextFreeSlot; + m_nextFreeSlot = index; + } + } + + template + void SparseVector::Clear() + { + m_data.clear(); + m_nextFreeSlot = NoFreeSlot; + } + + template + size_t SparseVector::GetSize() const + { + return m_data.size(); + } + + template + T& SparseVector::GetElement(size_t index) + { + return m_data.at(index); + } + + template + const T* SparseVector::GetRawData() const + { + return m_data.data(); + } +} diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index e2b5beac1f..5f7057c9be 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -70,7 +70,7 @@ #include #include #include - +#include #include @@ -110,6 +110,7 @@ namespace AZ { AuxGeomFeatureProcessor::Reflect(context); TransformServiceFeatureProcessor::Reflect(context); + ProjectedShadowFeatureProcessor::Reflect(context); SkyBoxFeatureProcessor::Reflect(context); UseTextureFunctor::Reflect(context); PropertyVisibilityFunctor::Reflect(context); @@ -186,6 +187,7 @@ namespace AZ AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); + AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessor(); @@ -274,18 +276,19 @@ namespace AZ void CommonSystemComponent::Deactivate() { - AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); + AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); - AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); - AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); - AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); - AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CoreLightsSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CoreLightsSystemComponent.cpp index 017c314a06..7ef01cfbaf 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CoreLightsSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CoreLightsSystemComponent.cpp @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include #include @@ -33,8 +35,7 @@ #include #include #include -#include -#include +#include #include @@ -69,9 +70,10 @@ namespace AZ } PhotometricValue::Reflect(context); + SimplePointLightFeatureProcessor::Reflect(context); + SimpleSpotLightFeatureProcessor::Reflect(context); PointLightFeatureProcessor::Reflect(context); DirectionalLightFeatureProcessor::Reflect(context); - SpotLightFeatureProcessor::Reflect(context); DiskLightFeatureProcessor::Reflect(context); CapsuleLightFeatureProcessor::Reflect(context); QuadLightFeatureProcessor::Reflect(context); @@ -112,9 +114,10 @@ namespace AZ void CoreLightsSystemComponent::Activate() { + AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); + AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); - AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface(); @@ -126,7 +129,7 @@ namespace AZ passSystem->AddPassCreator(Name("DepthExponentiationPass"), &DepthExponentiationPass::Create); passSystem->AddPassCreator(Name("EsmShadowmapsPass"), &EsmShadowmapsPass::Create); passSystem->AddPassCreator(Name("ShadowmapPass"), &ShadowmapPass::Create); - passSystem->AddPassCreator(Name("SpotLightShadowmapsPass"), &SpotLightShadowmapsPass::Create); + passSystem->AddPassCreator(Name("ProjectedShadowmapsPass"), &ProjectedShadowmapsPass::Create); // Add the ShadowmapPassTemplate to the pass system. It will be cleaned up automatically when the pass system shuts down ShadowmapPass::CreatePassTemplate(); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 014178e220..f44a56233e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -609,6 +609,16 @@ namespace AZ m_shadowBufferNeedsUpdate = true; } + void DirectionalLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) + { + for (auto& it : m_shadowData) + { + it.second.GetData(handle.GetIndex()).m_pcfMethod = method; + } + m_shadowBufferNeedsUpdate = true; + } + + void DirectionalLightFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) { PrepareForChangingRenderPipelineAndCameraView(); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index 48a9b15dab..a276ea3f3e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -73,6 +73,7 @@ namespace AZ float padding2 = 0.0f; // Padding between float3s in shader, can be used for other data later. }; + // [GFX TODO][ATOM-15172] Look into compacting struct DirectionalLightShadowData struct DirectionalLightShadowData { AZStd::array m_depthBiasMatrices = @@ -103,8 +104,10 @@ namespace AZ uint32_t m_predictionSampleCount = 0; uint32_t m_filteringSampleCount = 0; uint32_t m_debugFlags = 0; - uint32_t m_shadowFilterMethod = 0; + uint32_t m_shadowFilterMethod = 0; float m_far_minus_near = 0; + PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; + uint32_t m_padding[3]; }; class DirectionalLightFeatureProcessor final @@ -218,6 +221,7 @@ namespace AZ void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) override; + void SetPcfMethod(LightHandle handle, PcfMethod method) override; const Data::Instance GetLightBuffer() const; uint32_t GetLightCount() const; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index 8bf2b6cefc..58bbed699a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -14,8 +14,9 @@ #include -#include #include +#include +#include #include @@ -56,6 +57,7 @@ namespace AZ desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout(); m_lightBufferHandler = GpuBufferHandler(desc); + m_shadowFeatureProcessor = GetParentScene()->GetFeatureProcessor(); } void DiskLightFeatureProcessor::Deactivate() @@ -83,6 +85,11 @@ namespace AZ { if (handle.IsValid()) { + ShadowId shadowId = ShadowId(m_diskLightData.GetData(handle.GetIndex()).m_shadowIndex); + if (shadowId.IsValid()) + { + m_shadowFeatureProcessor->ReleaseShadow(shadowId); + } m_diskLightData.RemoveIndex(handle.GetIndex()); m_deviceBufferNeedsUpdate = true; handle.Reset(); @@ -98,7 +105,21 @@ namespace AZ LightHandle handle = AcquireLight(); if (handle.IsValid()) { - m_diskLightData.GetData(handle.GetIndex()) = m_diskLightData.GetData(sourceLightHandle.GetIndex()); + // Get a reference to the new light + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + // Copy data from the source light on top of it. + light = m_diskLightData.GetData(sourceLightHandle.GetIndex()); + + ShadowId shadowId = ShadowId(light.m_shadowIndex); + if (shadowId.IsValid()) + { + // Since the source light has a valid shadow, a new shadow must be generated for the cloned light. + ProjectedShadowFeatureProcessorInterface::ProjectedShadowDescriptor originalDesc = m_shadowFeatureProcessor->GetShadowProperties(shadowId); + ShadowId cloneShadow = m_shadowFeatureProcessor->AcquireShadow(); + light.m_shadowIndex = cloneShadow.GetIndex(); + m_shadowFeatureProcessor->SetShadowProperties(cloneShadow, originalDesc); + } + m_deviceBufferNeedsUpdate = true; } return handle; @@ -148,6 +169,7 @@ namespace AZ lightPosition.StoreToFloat3(position.data()); m_deviceBufferNeedsUpdate = true; + UpdateShadow(handle); } void DiskLightFeatureProcessor::SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) @@ -158,14 +180,7 @@ namespace AZ lightDirection.StoreToFloat3(direction.data()); m_deviceBufferNeedsUpdate = true; - } - - void DiskLightFeatureProcessor::SetLightEmitsBothDirections(LightHandle handle, bool lightEmitsBothDirections) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetLightEmitsBothDirections()."); - - m_diskLightData.GetData(handle.GetIndex()).SetLightEmitsBothDirections(lightEmitsBothDirections); - m_deviceBufferNeedsUpdate = true; + UpdateShadow(handle); } void DiskLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius) @@ -173,16 +188,69 @@ namespace AZ AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetAttenuationRadius()."); attenuationRadius = AZStd::max(attenuationRadius, 0.001f); // prevent divide by zero. - m_diskLightData.GetData(handle.GetIndex()).m_invAttenuationRadiusSquared = 1.0f / (attenuationRadius * attenuationRadius); + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + light.m_invAttenuationRadiusSquared = 1.0f / (attenuationRadius * attenuationRadius); + m_deviceBufferNeedsUpdate = true; + + // Update the shadow near far planes if necessary + ShadowId shadowId = ShadowId(light.m_shadowIndex); + if (shadowId.IsValid()) + { + m_shadowFeatureProcessor->SetNearFarPlanes(ShadowId(light.m_shadowIndex), + light.m_bulbPositionOffset, attenuationRadius + light.m_bulbPositionOffset); + } } void DiskLightFeatureProcessor::SetDiskRadius(LightHandle handle, float radius) { AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetDiskRadius()."); - - m_diskLightData.GetData(handle.GetIndex()).m_diskRadius = radius; + + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + light.m_diskRadius = radius; + UpdateBulbPositionOffset(light); m_deviceBufferNeedsUpdate = true; + UpdateShadow(handle); + } + + void DiskLightFeatureProcessor::SetConstrainToConeLight(LightHandle handle, bool useCone) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetDiskRadius()."); + + uint32_t& flags = m_diskLightData.GetData(handle.GetIndex()).m_flags; + useCone ? flags |= DiskLightData::Flags::UseConeAngle : flags &= ~DiskLightData::Flags::UseConeAngle; + m_deviceBufferNeedsUpdate = true; + UpdateShadow(handle); + } + + void DiskLightFeatureProcessor::SetConeAngles(LightHandle handle, float innerRadians, float outerRadians) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetConeAngles()."); + + ValidateAndSetConeAngles(handle, innerRadians, outerRadians); + UpdateShadow(handle); + + m_deviceBufferNeedsUpdate = true; + } + + void DiskLightFeatureProcessor::ValidateAndSetConeAngles(LightHandle handle, float innerRadians, float outerRadians) + { + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + + // Assume if the cone angles are being set that the user wants to constrain to a cone angle + SetConstrainToConeLight(handle, true); + + ShadowId shadowId = ShadowId(light.m_shadowIndex); + float maxRadians = shadowId.IsNull() ? MaxConeRadians : MaxProjectedShadowRadians; + float minRadians = 0.001f; + + outerRadians = AZStd::clamp(outerRadians, minRadians, maxRadians); + innerRadians = AZStd::clamp(innerRadians, minRadians, outerRadians); + + light.m_cosInnerConeAngle = cosf(innerRadians); + light.m_cosOuterConeAngle = cosf(outerRadians); + + UpdateBulbPositionOffset(light); } void DiskLightFeatureProcessor::SetDiskData(LightHandle handle, const DiskLightData& data) @@ -191,6 +259,7 @@ namespace AZ m_diskLightData.GetData(handle.GetIndex()) = data; m_deviceBufferNeedsUpdate = true; + UpdateShadow(handle); } const Data::Instance DiskLightFeatureProcessor::GetLightBuffer()const @@ -203,5 +272,130 @@ namespace AZ return m_lightBufferHandler.GetElementCount(); } + void DiskLightFeatureProcessor::SetShadowsEnabled(LightHandle handle, bool enabled) + { + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + ShadowId shadowId = ShadowId(light.m_shadowIndex); + if (shadowId.IsValid() && enabled == false) + { + // Disable shadows + m_shadowFeatureProcessor->ReleaseShadow(shadowId); + shadowId.Reset(); + light.m_shadowIndex = shadowId.GetIndex(); + m_deviceBufferNeedsUpdate = true; + } + else if(shadowId.IsNull() && enabled == true) + { + // Enable shadows + light.m_shadowIndex = m_shadowFeatureProcessor->AcquireShadow().GetIndex(); + + // It's possible the cone angles aren't set, or are too wide for casting shadows. This makes sure they're set to reasonable limits. + // This function expects radians, so the cos stored in the actual data needs to be undone. + ValidateAndSetConeAngles(handle, acosf(light.m_cosInnerConeAngle), acosf(light.m_cosOuterConeAngle)); + + UpdateShadow(handle); + m_deviceBufferNeedsUpdate = true; + } + } + + template + void DiskLightFeatureProcessor::SetShadowSetting(LightHandle handle, Functor&& functor, ParamType&& param) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::SetShadowSetting()."); + + DiskLightData& light = m_diskLightData.GetData(handle.GetIndex()); + ShadowId shadowId = ShadowId(light.m_shadowIndex); + + AZ_Assert(shadowId.IsValid(), "Attempting to set a shadow property when shadows are not enabled."); + if (shadowId.IsValid()) + { + AZStd::invoke(AZStd::forward(functor), m_shadowFeatureProcessor, shadowId, AZStd::forward(param)); + } + } + + void DiskLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution, shadowmapSize); + } + + void DiskLightFeatureProcessor::SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowFilterMethod, method); + } + + void DiskLightFeatureProcessor::SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians); + } + + void DiskLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPredictionSampleCount, count); + } + + void DiskLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count); + } + + void DiskLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); + } + + void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle) + { + const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex()); + ShadowId shadowId = ShadowId(diskLight.m_shadowIndex); + if (shadowId.IsNull()) + { + // Early out if shadows are disabled. + return; + } + + ProjectedShadowFeatureProcessorInterface::ProjectedShadowDescriptor desc = m_shadowFeatureProcessor->GetShadowProperties(shadowId); + + Vector3 position = Vector3::CreateFromFloat3(diskLight.m_position.data()); + const Vector3 direction = Vector3::CreateFromFloat3(diskLight.m_direction.data()); + + constexpr float SmallAngle = 0.01f; + float halfFov = acosf(diskLight.m_cosOuterConeAngle); + desc.m_fieldOfViewYRadians = GetMax(halfFov * 2.0f, SmallAngle); + + // To handle bulb radius, set the position of the shadow caster behind the actual light depending on the radius of the bulb + // + // \ / + // \ / + // \_____/ <-- position of light itself (and forward plane of shadow casting view) + // . . + // . . + // * <-- position of shadow casting view + // + position += diskLight.m_bulbPositionOffset * -direction; + desc.m_transform = Transform::CreateLookAt(position, position + direction); + + desc.m_aspectRatio = 1.0f; + desc.m_nearPlaneDistance = diskLight.m_bulbPositionOffset; + + const float invRadiusSquared = diskLight.m_invAttenuationRadiusSquared; + if (invRadiusSquared <= 0.f) + { + AZ_Assert(false, "Attenuation radius have to be set before use the light."); + return; + } + const float attenuationRadius = sqrtf(1.f / invRadiusSquared); + desc.m_farPlaneDistance = attenuationRadius + diskLight.m_bulbPositionOffset; + + m_shadowFeatureProcessor->SetShadowProperties(shadowId, desc); + } + + void DiskLightFeatureProcessor::UpdateBulbPositionOffset(DiskLightData& light) + { + // If we have the outer cone angle in radians, the offset is (radius * tan(pi/2 - coneRadians)). However + // light stores the cosine of outerConeRadians, making the equation (radius * tan(pi/2 - acosf(cosConeRadians)). + // This simplifies to the equation below. + float cosConeRadians = light.m_cosOuterConeAngle; + light.m_bulbPositionOffset = light.m_diskRadius * cosConeRadians / sqrt(1 - cosConeRadians * cosConeRadians); + } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index e76f6af77d..446b008921 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace AZ { @@ -48,21 +49,46 @@ namespace AZ void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) override; void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) override; void SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) override; - void SetLightEmitsBothDirections(LightHandle handle, bool lightEmitsBothDirections) override; void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override; void SetDiskRadius(LightHandle handle, float radius) override; + void SetConstrainToConeLight(LightHandle handle, bool useCone) override; + void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) override; + void SetShadowsEnabled(LightHandle handle, bool enabled) override; + void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; + void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; + void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override; + void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; + void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; + void SetPcfMethod(LightHandle handle, PcfMethod method); + void SetDiskData(LightHandle handle, const DiskLightData& data) override; const Data::Instance GetLightBuffer()const; uint32_t GetLightCount()const; private: - DiskLightFeatureProcessor(const DiskLightFeatureProcessor&) = delete; static constexpr const char* FeatureProcessorName = "DiskLightFeatureProcessor"; + static constexpr float MaxConeRadians = AZ::DegToRad(90.0f); + static constexpr float MaxProjectedShadowRadians = ProjectedShadowFeatureProcessorInterface::MaxProjectedShadowRadians * 0.5f; + using ShadowId = ProjectedShadowFeatureProcessor::ShadowId; + + DiskLightFeatureProcessor(const DiskLightFeatureProcessor&) = delete; + + static void UpdateBulbPositionOffset(DiskLightData& light); + + void ValidateAndSetConeAngles(LightHandle handle, float innerRadians, float outerRadians); + void UpdateShadow(LightHandle handle); + + // Convenience function for forwarding requests to the ProjectedShadowFeatureProcessor + template + void SetShadowSetting(LightHandle handle, Functor&&, ParamType&& param); + + ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor; IndexedDataVector m_diskLightData; GpuBufferHandler m_lightBufferHandler; + bool m_deviceBufferNeedsUpdate = false; }; } // namespace Render diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp index 0d3ebb7704..e0b0841745 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp @@ -98,9 +98,9 @@ namespace AZ { exponentiationPass->SetShadowmapType(Shadow::ShadowmapType::Directional); } - else if (m_lightTypeName == Name("spot")) + else if (m_lightTypeName == Name("projected")) { - exponentiationPass->SetShadowmapType(Shadow::ShadowmapType::Spot); + exponentiationPass->SetShadowmapType(Shadow::ShadowmapType::Projected); } else { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h index dfb8a97b68..f9fc54f869 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h @@ -36,7 +36,8 @@ namespace AZ DataType& GetData(IndexType index); const DataType& GetData(IndexType index) const; size_t GetDataCount() const; - + + AZStd::vector& GetDataVector(); const AZStd::vector& GetDataVector() const; IndexType GetRawIndex(IndexType index) const; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl index dd714d7110..4d42c9e265 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl @@ -98,6 +98,12 @@ inline size_t IndexedDataVector::GetDataCount() const return m_data.size(); } +template +inline AZStd::vector& IndexedDataVector::GetDataVector() +{ + return m_data; +} + template inline const AZStd::vector& IndexedDataVector::GetDataVector() const { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp index cb091fdd8c..91b8836cc9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp @@ -28,8 +28,9 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -116,18 +117,20 @@ namespace AZ LightCullingPass::LightCullingPass(const RPI::PassDescriptor& descriptor) : RPI::ComputePass(descriptor) { - m_lightdata[eLightTypes_Point].m_lightCountIndex = Name("m_pointLightCount"); - m_lightdata[eLightTypes_Point].m_lightBufferIndex = Name("m_pointLights"); - m_lightdata[eLightTypes_Spot].m_lightCountIndex = Name("m_spotLightCount"); - m_lightdata[eLightTypes_Spot].m_lightBufferIndex = Name("m_spotLights"); - m_lightdata[eLightTypes_Disk].m_lightCountIndex = Name("m_diskLightCount"); - m_lightdata[eLightTypes_Disk].m_lightBufferIndex = Name("m_diskLights"); - m_lightdata[eLightTypes_Capsule].m_lightCountIndex = Name("m_capsuleLightCount"); - m_lightdata[eLightTypes_Capsule].m_lightBufferIndex = Name("m_capsuleLights"); - m_lightdata[eLightTypes_Quad].m_lightCountIndex = Name("m_quadLightCount"); - m_lightdata[eLightTypes_Quad].m_lightBufferIndex = Name("m_quadLights"); - m_lightdata[eLightTypes_Decal].m_lightCountIndex = Name("m_decalCount"); - m_lightdata[eLightTypes_Decal].m_lightBufferIndex = Name("m_decals"); + m_lightdata[eLightTypes_SimplePoint].m_lightCountIndex = Name("m_simplePointLightCount"); + m_lightdata[eLightTypes_SimplePoint].m_lightBufferIndex = Name("m_simplePointLights"); + m_lightdata[eLightTypes_SimpleSpot].m_lightCountIndex = Name("m_simpleSpotLightCount"); + m_lightdata[eLightTypes_SimpleSpot].m_lightBufferIndex = Name("m_simpleSpotLights"); + m_lightdata[eLightTypes_Point].m_lightCountIndex = Name("m_pointLightCount"); + m_lightdata[eLightTypes_Point].m_lightBufferIndex = Name("m_pointLights"); + m_lightdata[eLightTypes_Disk].m_lightCountIndex = Name("m_diskLightCount"); + m_lightdata[eLightTypes_Disk].m_lightBufferIndex = Name("m_diskLights"); + m_lightdata[eLightTypes_Capsule].m_lightCountIndex = Name("m_capsuleLightCount"); + m_lightdata[eLightTypes_Capsule].m_lightBufferIndex = Name("m_capsuleLights"); + m_lightdata[eLightTypes_Quad].m_lightCountIndex = Name("m_quadLightCount"); + m_lightdata[eLightTypes_Quad].m_lightBufferIndex = Name("m_quadLights"); + m_lightdata[eLightTypes_Decal].m_lightCountIndex = Name("m_decalCount"); + m_lightdata[eLightTypes_Decal].m_lightBufferIndex = Name("m_decals"); } void LightCullingPass::CompileResources(const RHI::FrameGraphCompileContext& context) @@ -274,14 +277,18 @@ namespace AZ void LightCullingPass::GetLightDataFromFeatureProcessor() { + const auto simplePointLightFP = m_pipeline->GetScene()->GetFeatureProcessor(); + m_lightdata[eLightTypes_SimplePoint].m_lightBuffer = simplePointLightFP->GetLightBuffer(); + m_lightdata[eLightTypes_SimplePoint].m_lightCount = simplePointLightFP->GetLightCount(); + + const auto simpleSpotLightFP = m_pipeline->GetScene()->GetFeatureProcessor(); + m_lightdata[eLightTypes_SimpleSpot].m_lightBuffer = simpleSpotLightFP->GetLightBuffer(); + m_lightdata[eLightTypes_SimpleSpot].m_lightCount = simpleSpotLightFP->GetLightCount(); + const auto pointLightFP = m_pipeline->GetScene()->GetFeatureProcessor(); m_lightdata[eLightTypes_Point].m_lightBuffer = pointLightFP->GetLightBuffer(); m_lightdata[eLightTypes_Point].m_lightCount = pointLightFP->GetLightCount(); - const auto spotLightFP = m_pipeline->GetScene()->GetFeatureProcessor(); - m_lightdata[eLightTypes_Spot].m_lightBuffer = spotLightFP->GetLightBuffer(); - m_lightdata[eLightTypes_Spot].m_lightCount = spotLightFP->GetLightCount(); - const auto diskLightFP = m_pipeline->GetScene()->GetFeatureProcessor(); m_lightdata[eLightTypes_Disk].m_lightBuffer = diskLightFP->GetLightBuffer(); m_lightdata[eLightTypes_Disk].m_lightCount = diskLightFP->GetLightCount(); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h index 7dd68e279b..a84c531c06 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h @@ -83,8 +83,9 @@ namespace AZ enum LightTypes { + eLightTypes_SimplePoint, + eLightTypes_SimpleSpot, eLightTypes_Point, - eLightTypes_Spot, eLightTypes_Disk, eLightTypes_Capsule, eLightTypes_Quad, diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp index 06e4b66253..eb3e87dcd1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.cpp similarity index 87% rename from Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.cpp rename to Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.cpp index 9c8613fb9c..d77419fe8f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.cpp @@ -14,19 +14,19 @@ #include #include #include -#include +#include #include namespace AZ { namespace Render { - RPI::Ptr SpotLightShadowmapsPass::Create(const RPI::PassDescriptor& descriptor) + RPI::Ptr ProjectedShadowmapsPass::Create(const RPI::PassDescriptor& descriptor) { - return aznew SpotLightShadowmapsPass(descriptor); + return aznew ProjectedShadowmapsPass(descriptor); } - SpotLightShadowmapsPass::SpotLightShadowmapsPass(const RPI::PassDescriptor& descriptor) + ProjectedShadowmapsPass::ProjectedShadowmapsPass(const RPI::PassDescriptor& descriptor) : Base(descriptor) { const RPI::RasterPassData* passData = RPI::PassUtils::GetPassData(descriptor); @@ -43,7 +43,7 @@ namespace AZ UpdateShadowmapSizes(shadowmapSizes); } - SpotLightShadowmapsPass::~SpotLightShadowmapsPass() + ProjectedShadowmapsPass::~ProjectedShadowmapsPass() { if (m_drawListTag.IsValid()) { @@ -52,12 +52,12 @@ namespace AZ } } - bool SpotLightShadowmapsPass::IsOfRenderPipeline(const RPI::RenderPipeline& renderPipeline) const + bool ProjectedShadowmapsPass::IsOfRenderPipeline(const RPI::RenderPipeline& renderPipeline) const { return &renderPipeline == m_pipeline; } - const RPI::PipelineViewTag& SpotLightShadowmapsPass::GetPipelineViewTagOfChild(size_t childIndex) + const RPI::PipelineViewTag& ProjectedShadowmapsPass::GetPipelineViewTagOfChild(size_t childIndex) { m_childrenPipelineViewTags.reserve(childIndex + 1); while (m_childrenPipelineViewTags.size() <= childIndex) @@ -69,7 +69,7 @@ namespace AZ return m_childrenPipelineViewTags[childIndex]; } - void SpotLightShadowmapsPass::UpdateShadowmapSizes(const AZStd::vector& sizes) + void ProjectedShadowmapsPass::UpdateShadowmapSizes(const AZStd::vector& sizes) { m_sizes = sizes; m_updateChildren = true; @@ -83,7 +83,7 @@ namespace AZ m_atlas.Finalize(); } - void SpotLightShadowmapsPass::UpdateChildren() + void ProjectedShadowmapsPass::UpdateChildren() { if (!m_updateChildren) { @@ -141,22 +141,22 @@ namespace AZ } } - ShadowmapSize SpotLightShadowmapsPass::GetShadowmapAtlasSize() const + ShadowmapSize ProjectedShadowmapsPass::GetShadowmapAtlasSize() const { return m_atlas.GetBaseShadowmapSize(); } - ShadowmapAtlas::Origin SpotLightShadowmapsPass::GetOriginInAtlas(uint16_t index) const + ShadowmapAtlas::Origin ProjectedShadowmapsPass::GetOriginInAtlas(uint16_t index) const { return m_atlas.GetOrigin(index); } - ShadowmapAtlas& SpotLightShadowmapsPass::GetShadowmapAtlas() + ShadowmapAtlas& ProjectedShadowmapsPass::GetShadowmapAtlas() { return m_atlas; } - void SpotLightShadowmapsPass::BuildAttachmentsInternal() + void ProjectedShadowmapsPass::BuildAttachmentsInternal() { UpdateChildren(); @@ -164,10 +164,10 @@ namespace AZ RPI::Ptr attachment = m_ownedAttachments.front(); if (!attachment) { - AZ_Assert(false, "[SpotLightShadowmapsPass %s] Cannot find shadowmap image attachment.", GetPathName().GetCStr()); + AZ_Assert(false, "[ProjectedShadowmapsPass %s] Cannot find shadowmap image attachment.", GetPathName().GetCStr()); return; } - AZ_Assert(attachment->m_descriptor.m_type == RHI::AttachmentType::Image, "[SpotLightShadowmapsPass %s] requires an image attachment", GetPathName().GetCStr()); + AZ_Assert(attachment->m_descriptor.m_type == RHI::AttachmentType::Image, "[ProjectedShadowmapsPass %s] requires an image attachment", GetPathName().GetCStr()); RPI::PassAttachmentBinding& binding = GetOutputBinding(0); binding.m_attachment = attachment; @@ -180,7 +180,7 @@ namespace AZ Base::BuildAttachmentsInternal(); } - void SpotLightShadowmapsPass::GetPipelineViewTags(RPI::SortedPipelineViewTags& outTags) const + void ProjectedShadowmapsPass::GetPipelineViewTags(RPI::SortedPipelineViewTags& outTags) const { const size_t childrenCount = GetChildren().size(); AZ_Assert(m_childrenPipelineViewTags.size() >= childrenCount, "There are not enough pipeline view tags."); @@ -190,7 +190,7 @@ namespace AZ } } - void SpotLightShadowmapsPass::GetViewDrawListInfo(RHI::DrawListMask& outDrawListMask, RPI::PassesByDrawList& outPassesByDrawList, const RPI::PipelineViewTag& viewTag) const + void ProjectedShadowmapsPass::GetViewDrawListInfo(RHI::DrawListMask& outDrawListMask, RPI::PassesByDrawList& outPassesByDrawList, const RPI::PipelineViewTag& viewTag) const { if (AZStd::find( m_childrenPipelineViewTags.begin(), @@ -203,9 +203,9 @@ namespace AZ } } - RPI::Ptr SpotLightShadowmapsPass::CreateChild(size_t childIndex) + RPI::Ptr ProjectedShadowmapsPass::CreateChild(size_t childIndex) { - const Name passName{ AZStd::string::format("SpotLightShadowmapPass.%zu", childIndex) }; + const Name passName{ AZStd::string::format("ProjectedShadowmapPass.%zu", childIndex) }; auto passData = AZStd::make_shared(); passData->m_drawListTag = m_drawListTagName; @@ -214,7 +214,7 @@ namespace AZ return ShadowmapPass::CreateWithPassRequest(passName, passData); } - void SpotLightShadowmapsPass::SetChildrenCount(size_t childrenCount) + void ProjectedShadowmapsPass::SetChildrenCount(size_t childrenCount) { // Reserve Tags if (childrenCount > 0) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h similarity index 82% rename from Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.h rename to Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h index 25c505950f..63640d22c6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightShadowmapsPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h @@ -23,16 +23,16 @@ namespace AZ { namespace Render { - //! SpotLightShadowmapsPass owns ShadowmapPasses for Spot Lights. - class SpotLightShadowmapsPass final + //! ProjectedShadowmapsPass owns shadowmap passes for projected lights. + class ProjectedShadowmapsPass final : public RPI::ParentPass { - AZ_RPI_PASS(SpotLightShadowmapsPass); + AZ_RPI_PASS(ProjectedShadowmapsPass); using Base = RPI::ParentPass; public: - AZ_CLASS_ALLOCATOR(SpotLightShadowmapsPass, SystemAllocator, 0); - AZ_RTTI(SpotLightShadowmapsPass, "00024B13-1095-40FA-BEC3-B0F68110BEA2", Base); + AZ_CLASS_ALLOCATOR(ProjectedShadowmapsPass, SystemAllocator, 0); + AZ_RTTI(ProjectedShadowmapsPass, "00024B13-1095-40FA-BEC3-B0F68110BEA2", Base); static constexpr uint16_t InvalidIndex = ~0; struct ShadowmapSizeWithIndices @@ -41,8 +41,8 @@ namespace AZ uint16_t m_shadowIndexInSrg = InvalidIndex; }; - virtual ~SpotLightShadowmapsPass(); - static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + virtual ~ProjectedShadowmapsPass(); + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); //! This returns true if this pass is of the given render pipeline. bool IsOfRenderPipeline(const RPI::RenderPipeline& renderPipeline) const; @@ -50,8 +50,8 @@ namespace AZ //! This returns the pipeline view tag used in shadowmap passes. const RPI::PipelineViewTag& GetPipelineViewTagOfChild(size_t childIndex); - //! This update shadowmap sizes for each spot light index. - //! @param sizes shadowmap sizes for each spot light index. + //! This update shadowmap sizes for each projected light shadow index. + //! @param sizes shadowmap sizes for each projected light shadow index. void UpdateShadowmapSizes(const AZStd::vector& sizes); //! This returns the image size(width/height) of shadowmap atlas. @@ -67,8 +67,8 @@ namespace AZ ShadowmapAtlas& GetShadowmapAtlas(); private: - SpotLightShadowmapsPass() = delete; - explicit SpotLightShadowmapsPass(const RPI::PassDescriptor& descriptor); + ProjectedShadowmapsPass() = delete; + explicit ProjectedShadowmapsPass(const RPI::PassDescriptor& descriptor); // RPI::Pass overrides... void BuildAttachmentsInternal() override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/Shadow.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/Shadow.h index 97d52cdff8..4601e77fa8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/Shadow.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/Shadow.h @@ -23,7 +23,7 @@ namespace AZ { AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE(ShadowmapType, uint32_t, (Directional, 0), - Spot); + Projected); const Matrix4x4& GetClipToShadowmapTextureMatrix(); } // namespace Shadow diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp new file mode 100644 index 0000000000..591abc1b57 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp @@ -0,0 +1,173 @@ +/* +* 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 +#include + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + void SimplePointLightFeatureProcessor::Reflect(ReflectContext* context) + { + if (auto * serializeContext = azrtti_cast(context)) + { + serializeContext + ->Class() + ->Version(0); + } + } + + SimplePointLightFeatureProcessor::SimplePointLightFeatureProcessor() + : SimplePointLightFeatureProcessorInterface() + { + } + + void SimplePointLightFeatureProcessor::Activate() + { + GpuBufferHandler::Descriptor desc; + desc.m_bufferName = "SimplePointLightBuffer"; + desc.m_bufferSrgName = "m_simplePointLights"; + desc.m_elementCountSrgName = "m_simplePointLightCount"; + desc.m_elementSize = sizeof(SimplePointLightData); + desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout(); + + m_lightBufferHandler = GpuBufferHandler(desc); + } + + void SimplePointLightFeatureProcessor::Deactivate() + { + m_pointLightData.Clear(); + m_lightBufferHandler.Release(); + } + + SimplePointLightFeatureProcessor::LightHandle SimplePointLightFeatureProcessor::AcquireLight() + { + uint16_t id = m_pointLightData.GetFreeSlotIndex(); + + if (id == IndexedDataVector::NoFreeSlot) + { + return LightHandle::Null; + } + else + { + m_deviceBufferNeedsUpdate = true; + return LightHandle(id); + } + } + + bool SimplePointLightFeatureProcessor::ReleaseLight(LightHandle& handle) + { + if (handle.IsValid()) + { + m_pointLightData.RemoveIndex(handle.GetIndex()); + m_deviceBufferNeedsUpdate = true; + handle.Reset(); + return true; + } + return false; + } + + SimplePointLightFeatureProcessor::LightHandle SimplePointLightFeatureProcessor::CloneLight(LightHandle sourceLightHandle) + { + AZ_Assert(sourceLightHandle.IsValid(), "Invalid LightHandle passed to SimplePointLightFeatureProcessor::CloneLight()."); + + LightHandle handle = AcquireLight(); + if (handle.IsValid()) + { + m_pointLightData.GetData(handle.GetIndex()) = m_pointLightData.GetData(sourceLightHandle.GetIndex()); + m_deviceBufferNeedsUpdate = true; + } + return handle; + } + + void SimplePointLightFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "SimplePointLightFeatureProcessor: Simulate"); + AZ_UNUSED(packet); + + if (m_deviceBufferNeedsUpdate) + { + m_lightBufferHandler.UpdateBuffer(m_pointLightData.GetDataVector()); + m_deviceBufferNeedsUpdate = false; + } + } + + void SimplePointLightFeatureProcessor::Render(const SimplePointLightFeatureProcessor::RenderPacket& packet) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "SimplePointLightFeatureProcessor: Render"); + + for (const RPI::ViewPtr& view : packet.m_views) + { + m_lightBufferHandler.UpdateSrg(view->GetShaderResourceGroup().get()); + } + } + + void SimplePointLightFeatureProcessor::SetRgbIntensity(LightHandle handle, const PhotometricColor& lightRgbIntensity) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimplePointLightFeatureProcessor::SetRgbIntensity()."); + + auto transformedColor = AZ::RPI::TransformColor(lightRgbIntensity, AZ::RPI::ColorSpaceId::LinearSRGB, AZ::RPI::ColorSpaceId::ACEScg); + + AZStd::array& rgbIntensity = m_pointLightData.GetData(handle.GetIndex()).m_rgbIntensity; + rgbIntensity[0] = transformedColor.GetR(); + rgbIntensity[1] = transformedColor.GetG(); + rgbIntensity[2] = transformedColor.GetB(); + + m_deviceBufferNeedsUpdate = true; + } + + void SimplePointLightFeatureProcessor::SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimplePointLightFeatureProcessor::SetPosition()."); + + AZStd::array& position = m_pointLightData.GetData(handle.GetIndex()).m_position; + lightPosition.StoreToFloat3(position.data()); + + m_deviceBufferNeedsUpdate = true; + } + + void SimplePointLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimplePointLightFeatureProcessor::SetAttenuationRadius()."); + + attenuationRadius = AZStd::max(attenuationRadius, 0.001f); // prevent divide by zero. + m_pointLightData.GetData(handle.GetIndex()).m_invAttenuationRadiusSquared = 1.0f / (attenuationRadius * attenuationRadius); + m_deviceBufferNeedsUpdate = true; + } + + const Data::Instance SimplePointLightFeatureProcessor::GetLightBuffer() const + { + return m_lightBufferHandler.GetBuffer(); + } + + uint32_t SimplePointLightFeatureProcessor::GetLightCount() const + { + return m_lightBufferHandler.GetElementCount(); + } + + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h new file mode 100644 index 0000000000..911868b088 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h @@ -0,0 +1,74 @@ +/* +* 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 +#include + +namespace AZ +{ + class Vector3; + class Color; + + namespace Render + { + + struct SimplePointLightData + { + AZStd::array m_position = { { 0.0f, 0.0f, 0.0f } }; + float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations. + AZStd::array m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } }; + float m_padding = 0.0f; // explicit padding. + }; + + class SimplePointLightFeatureProcessor final + : public SimplePointLightFeatureProcessorInterface + { + public: + AZ_RTTI(AZ::Render::SimplePointLightFeatureProcessor, "{310CE42A-FAD1-4778-ABF5-0DE04AC92246}", AZ::Render::SimplePointLightFeatureProcessorInterface); + + static void Reflect(AZ::ReflectContext* context); + + SimplePointLightFeatureProcessor(); + virtual ~SimplePointLightFeatureProcessor() = default; + + // FeatureProcessor overrides ... + void Activate() override; + void Deactivate() override; + void Simulate(const SimulatePacket& packet) override; + void Render(const RenderPacket& packet) override; + + // PointLightFeatureProcessorInterface overrides ... + LightHandle AcquireLight() override; + bool ReleaseLight(LightHandle& handle) override; + LightHandle CloneLight(LightHandle handle) override; + void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) override; + void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) override; + void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override; + + const Data::Instance GetLightBuffer() const; + uint32_t GetLightCount()const; + + private: + SimplePointLightFeatureProcessor(const SimplePointLightFeatureProcessor&) = delete; + + static constexpr const char* FeatureProcessorName = "SimplePointLightFeatureProcessor"; + + IndexedDataVector m_pointLightData; + GpuBufferHandler m_lightBufferHandler; + bool m_deviceBufferNeedsUpdate = false; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp new file mode 100644 index 0000000000..f26c0b19b3 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp @@ -0,0 +1,189 @@ +/* +* 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 +#include + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + void SimpleSpotLightFeatureProcessor::Reflect(ReflectContext* context) + { + if (auto * serializeContext = azrtti_cast(context)) + { + serializeContext + ->Class() + ->Version(0); + } + } + + SimpleSpotLightFeatureProcessor::SimpleSpotLightFeatureProcessor() + : SimpleSpotLightFeatureProcessorInterface() + { + } + + void SimpleSpotLightFeatureProcessor::Activate() + { + GpuBufferHandler::Descriptor desc; + desc.m_bufferName = "SimpleSpotLightBuffer"; + desc.m_bufferSrgName = "m_simpleSpotLights"; + desc.m_elementCountSrgName = "m_simpleSpotLightCount"; + desc.m_elementSize = sizeof(SimpleSpotLightData); + desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout(); + + m_lightBufferHandler = GpuBufferHandler(desc); + } + + void SimpleSpotLightFeatureProcessor::Deactivate() + { + m_pointLightData.Clear(); + m_lightBufferHandler.Release(); + } + + SimpleSpotLightFeatureProcessor::LightHandle SimpleSpotLightFeatureProcessor::AcquireLight() + { + uint16_t id = m_pointLightData.GetFreeSlotIndex(); + + if (id == IndexedDataVector::NoFreeSlot) + { + return LightHandle::Null; + } + else + { + m_deviceBufferNeedsUpdate = true; + return LightHandle(id); + } + } + + bool SimpleSpotLightFeatureProcessor::ReleaseLight(LightHandle& handle) + { + if (handle.IsValid()) + { + m_pointLightData.RemoveIndex(handle.GetIndex()); + m_deviceBufferNeedsUpdate = true; + handle.Reset(); + return true; + } + return false; + } + + SimpleSpotLightFeatureProcessor::LightHandle SimpleSpotLightFeatureProcessor::CloneLight(LightHandle sourceLightHandle) + { + AZ_Assert(sourceLightHandle.IsValid(), "Invalid LightHandle passed to SimpleSpotLightFeatureProcessor::CloneLight()."); + + LightHandle handle = AcquireLight(); + if (handle.IsValid()) + { + m_pointLightData.GetData(handle.GetIndex()) = m_pointLightData.GetData(sourceLightHandle.GetIndex()); + m_deviceBufferNeedsUpdate = true; + } + return handle; + } + + void SimpleSpotLightFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "SimpleSpotLightFeatureProcessor: Simulate"); + AZ_UNUSED(packet); + + if (m_deviceBufferNeedsUpdate) + { + m_lightBufferHandler.UpdateBuffer(m_pointLightData.GetDataVector()); + m_deviceBufferNeedsUpdate = false; + } + } + + void SimpleSpotLightFeatureProcessor::Render(const SimpleSpotLightFeatureProcessor::RenderPacket& packet) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "SimpleSpotLightFeatureProcessor: Render"); + + for (const RPI::ViewPtr& view : packet.m_views) + { + m_lightBufferHandler.UpdateSrg(view->GetShaderResourceGroup().get()); + } + } + + void SimpleSpotLightFeatureProcessor::SetRgbIntensity(LightHandle handle, const PhotometricColor& lightRgbIntensity) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimpleSpotLightFeatureProcessor::SetRgbIntensity()."); + + auto transformedColor = AZ::RPI::TransformColor(lightRgbIntensity, AZ::RPI::ColorSpaceId::LinearSRGB, AZ::RPI::ColorSpaceId::ACEScg); + + AZStd::array& rgbIntensity = m_pointLightData.GetData(handle.GetIndex()).m_rgbIntensity; + rgbIntensity[0] = transformedColor.GetR(); + rgbIntensity[1] = transformedColor.GetG(); + rgbIntensity[2] = transformedColor.GetB(); + + m_deviceBufferNeedsUpdate = true; + } + + void SimpleSpotLightFeatureProcessor::SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimpleSpotLightFeatureProcessor::SetPosition()."); + + AZStd::array& position = m_pointLightData.GetData(handle.GetIndex()).m_position; + lightPosition.StoreToFloat3(position.data()); + + m_deviceBufferNeedsUpdate = true; + } + + void SimpleSpotLightFeatureProcessor::SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimpleSpotLightFeatureProcessor::SetDirection()."); + + AZStd::array& direction = m_pointLightData.GetData(handle.GetIndex()).m_direction; + lightDirection.StoreToFloat3(direction.data()); + + m_deviceBufferNeedsUpdate = true; + } + + void SimpleSpotLightFeatureProcessor::SetConeAngles(LightHandle handle, float innerRadians, float outerRadians) + { + m_pointLightData.GetData(handle.GetIndex()).m_cosInnerConeAngle = cosf(innerRadians); + m_pointLightData.GetData(handle.GetIndex()).m_cosOuterConeAngle = cosf(outerRadians); + } + + void SimpleSpotLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius) + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SimpleSpotLightFeatureProcessor::SetAttenuationRadius()."); + + attenuationRadius = AZStd::max(attenuationRadius, 0.001f); // prevent divide by zero. + m_pointLightData.GetData(handle.GetIndex()).m_invAttenuationRadiusSquared = 1.0f / (attenuationRadius * attenuationRadius); + m_deviceBufferNeedsUpdate = true; + } + + const Data::Instance SimpleSpotLightFeatureProcessor::GetLightBuffer() const + { + return m_lightBufferHandler.GetBuffer(); + } + + uint32_t SimpleSpotLightFeatureProcessor::GetLightCount() const + { + return m_lightBufferHandler.GetElementCount(); + } + + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h new file mode 100644 index 0000000000..1b8d0058dd --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h @@ -0,0 +1,78 @@ +/* +* 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 +#include + +namespace AZ +{ + class Vector3; + class Color; + + namespace Render + { + + struct SimpleSpotLightData + { + AZStd::array m_position = { { 0.0f, 0.0f, 0.0f } }; + float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations. + AZStd::array m_direction = { { 0.0f, 0.0f, 0.0f } }; + float m_cosInnerConeAngle = 0.0f; // Cosine of the inner cone angle + AZStd::array m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } }; + float m_cosOuterConeAngle = 0.0f; // Cosine of the outer cone angle + }; + + class SimpleSpotLightFeatureProcessor final + : public SimpleSpotLightFeatureProcessorInterface + { + public: + AZ_RTTI(AZ::Render::SimpleSpotLightFeatureProcessor, "{01610AD4-0872-4F80-9F12-22FB7CCF6866}", AZ::Render::SimpleSpotLightFeatureProcessorInterface); + + static void Reflect(AZ::ReflectContext* context); + + SimpleSpotLightFeatureProcessor(); + virtual ~SimpleSpotLightFeatureProcessor() = default; + + // FeatureProcessor overrides ... + void Activate() override; + void Deactivate() override; + void Simulate(const SimulatePacket& packet) override; + void Render(const RenderPacket& packet) override; + + // SimpleSpotLightFeatureProcessorInterface overrides ... + LightHandle AcquireLight() override; + bool ReleaseLight(LightHandle& handle) override; + LightHandle CloneLight(LightHandle handle) override; + void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) override; + void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) override; + void SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) override; + virtual void SetConeAngles(LightHandle handle, float innerRadians, float outerRadians) override; + void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override; + + const Data::Instance GetLightBuffer() const; + uint32_t GetLightCount()const; + + private: + SimpleSpotLightFeatureProcessor(const SimpleSpotLightFeatureProcessor&) = delete; + + static constexpr const char* FeatureProcessorName = "SimpleSpotLightFeatureProcessor"; + + IndexedDataVector m_pointLightData; + GpuBufferHandler m_lightBufferHandler; + bool m_deviceBufferNeedsUpdate = false; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.cpp deleted file mode 100644 index 3dc31c2f32..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.cpp +++ /dev/null @@ -1,929 +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 -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace AZ -{ - namespace Render - { - namespace - { - static AZStd::array GetDepthUnprojectConstants(const RPI::ViewPtr view) - { - AZStd::array unprojectConstants; - unprojectConstants[0] = view->GetViewToClipMatrix().GetRow(2).GetElement(2); - unprojectConstants[1] = view->GetViewToClipMatrix().GetRow(2).GetElement(3); - return unprojectConstants; - } - } - - - void SpotLightFeatureProcessor::Reflect(ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext - ->Class() - ->Version(0); - } - } - - void SpotLightFeatureProcessor::Activate() - { - const RHI::ShaderResourceGroupLayout* viewSrgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout(); - - GpuBufferHandler::Descriptor desc; - - desc.m_bufferName = "SpotLightBuffer"; - desc.m_bufferSrgName = "m_spotLights"; - desc.m_elementCountSrgName = "m_spotLightCount"; - desc.m_elementSize = sizeof(SpotLightData); - desc.m_srgLayout = viewSrgLayout; - - m_lightBufferHandler = GpuBufferHandler(desc); - - desc.m_bufferName = "SpotLightShadowBuffer"; - desc.m_bufferSrgName = "m_spotLightShadows"; - desc.m_elementCountSrgName = ""; - desc.m_elementSize = sizeof(SpotLightShadowData); - desc.m_srgLayout = viewSrgLayout; - - m_shadowBufferHandler = GpuBufferHandler(desc); - - desc.m_bufferName = "EsmParameterBuffer(Spot)"; - desc.m_bufferSrgName = "m_esmsSpot"; - desc.m_elementCountSrgName = ""; - desc.m_elementSize = sizeof(EsmShadowmapsPass::FilterParameter); - desc.m_srgLayout = viewSrgLayout; - - m_esmParameterBufferHandler = GpuBufferHandler(desc); - - m_shadowmapAtlasSizeIndex = viewSrgLayout->FindShaderInputConstantIndex(Name("m_shadowmapAtlasSize")); - m_invShadowmapAtlasSize = viewSrgLayout->FindShaderInputConstantIndex(Name("m_invShadowmapAtlasSize")); - - CachePasses(); - EnableSceneNotification(); - } - - void SpotLightFeatureProcessor::Deactivate() - { - DisableSceneNotification(); - - m_spotLightData.Clear(); - m_lightBufferHandler.Release(); - - m_shadowData.Clear(); - m_shadowBufferHandler.Release(); - - m_esmParameterData.Clear(); - m_esmParameterBufferHandler.Release(); - - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->SetEnabledComputation(false); - } - } - - SpotLightFeatureProcessor::LightHandle SpotLightFeatureProcessor::AcquireLight() - { - const uint16_t index = m_spotLightData.GetFreeSlotIndex(); - const uint16_t propIndex = m_lightProperties.GetFreeSlotIndex(); - AZ_Assert(index == propIndex, "light index is illegal."); - if (index == IndexedDataVector::NoFreeSlot) - { - return LightHandle::Null; - } - else - { - m_deviceBufferNeedsUpdate = true; - const LightHandle handle(index); - return handle; - } - } - - bool SpotLightFeatureProcessor::ReleaseLight(LightHandle& handle) - { - if (handle.IsValid()) - { - CleanUpShadow(handle); - m_spotLightData.RemoveIndex(handle.GetIndex()); - m_lightProperties.RemoveIndex(handle.GetIndex()); - - m_deviceBufferNeedsUpdate = true; - handle.Reset(); - return true; - } - return false; - } - - SpotLightFeatureProcessor::LightHandle SpotLightFeatureProcessor::CloneLight(LightHandle sourceLightHandle) - { - AZ_Assert(sourceLightHandle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::CloneLight()."); - - LightHandle handle = AcquireLight(); - if (handle.IsValid()) - { - m_spotLightData.GetData(handle.GetIndex()) = m_spotLightData.GetData(sourceLightHandle.GetIndex()); - m_deviceBufferNeedsUpdate = true; - } - return handle; - } - - void SpotLightFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline) - { - CachePasses(); - } - - void SpotLightFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) - { - CachePasses(); - } - - void SpotLightFeatureProcessor::OnRenderPipelineRemoved([[maybe_unused]] RPI::RenderPipeline* pipeline) - { - CachePasses(); - } - - void SpotLightFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet) - { - AZ_ATOM_PROFILE_FUNCTION("RPI", "SpotLightFeatureProcessor: Simulate"); - AZ_UNUSED(packet); - - UpdateShadowmapViews(); - SetShadowParameterToShadowData(); - - if (m_shadowmapPassNeedsUpdate) - { - AZStd::vector shadowmapSizes(m_shadowProperties.size()); - for (auto& it : m_shadowProperties) - { - const int32_t shadowIndexInSrgSigned = m_spotLightData.GetData(it.first.GetIndex()).m_shadowIndex; - AZ_Assert(shadowIndexInSrgSigned >= 0, "Shadow index in SRG is illegal."); - const uint16_t shadowIndexInSrg = aznumeric_cast(shadowIndexInSrgSigned); - it.second.m_viewTagIndex = shadowIndexInSrg; - SpotLightShadowmapsPass::ShadowmapSizeWithIndices& sizeWithIndices = shadowmapSizes[shadowIndexInSrg]; - sizeWithIndices.m_size = static_cast(m_shadowData.GetData(it.second.m_shadowHandle.GetIndex()).m_shadowmapSize); - sizeWithIndices.m_shadowIndexInSrg = shadowIndexInSrg; - } - for (SpotLightShadowmapsPass* shadowPass : m_spotLightShadowmapsPasses) - { - shadowPass->UpdateShadowmapSizes(shadowmapSizes); - } - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->QueueForBuildAttachments(); - } - - for (const SpotLightShadowmapsPass* shadowPass : m_spotLightShadowmapsPasses) - { - for (const auto& it : m_shadowProperties) - { - const int32_t shadowIndexInSrg = m_spotLightData.GetData(it.first.GetIndex()).m_shadowIndex; - if (shadowIndexInSrg >= 0) - { - const ShadowmapAtlas::Origin origin = shadowPass->GetOriginInAtlas(aznumeric_cast(shadowIndexInSrg)); - SpotLightShadowData& shadow = m_shadowData.GetData(it.second.m_shadowHandle.GetIndex()); - shadow.m_shadowmapArraySlice = origin.m_arraySlice; - shadow.m_shadowmapOriginInSlice = origin.m_originInSlice; - m_deviceBufferNeedsUpdate = true; - } - } - break; - } - m_shadowmapPassNeedsUpdate = false; - } - - // This has to be called after UpdateShadowmapSizes(). - UpdateFilterParameters(); - - if (m_deviceBufferNeedsUpdate) - { - m_lightBufferHandler.UpdateBuffer(m_spotLightData.GetDataVector()); - m_shadowBufferHandler.UpdateBuffer(m_shadowData.GetDataVector()); - m_deviceBufferNeedsUpdate = false; - } - } - - void SpotLightFeatureProcessor::PrepareViews(const PrepareViewsPacket&, AZStd::vector>& outViews) - { - for (SpotLightShadowmapsPass* pass : m_spotLightShadowmapsPasses) - { - RPI::RenderPipeline* renderPipeline = pass->GetRenderPipeline(); - if (renderPipeline) - { - for (auto& it : m_shadowProperties) - { - SpotLightShadowData& shadow = m_shadowData.GetData(it.second.m_shadowHandle.GetIndex()); - if (shadow.m_shadowmapSize == aznumeric_cast(ShadowmapSize::None)) - { - continue; - } - - const RPI::PipelineViewTag& viewTag = pass->GetPipelineViewTagOfChild(it.second.m_viewTagIndex); - const RHI::DrawListMask drawListMask = renderPipeline->GetDrawListMask(viewTag); - if (it.second.m_shadowmapView->GetDrawListMask() != drawListMask) - { - it.second.m_shadowmapView->Reset(); - it.second.m_shadowmapView->SetDrawListMask(drawListMask); - } - - outViews.emplace_back(AZStd::make_pair( - viewTag, - it.second.m_shadowmapView)); - } - } - break; - } - } - - void SpotLightFeatureProcessor::Render(const SpotLightFeatureProcessor::RenderPacket& packet) - { - AZ_ATOM_PROFILE_FUNCTION("RPI", "SpotLightFeatureProcessor: Render"); - - for (const SpotLightShadowmapsPass* pass : m_spotLightShadowmapsPasses) - { - for (const RPI::ViewPtr& view : packet.m_views) - { - if (view->GetUsageFlags() & RPI::View::UsageFlags::UsageCamera) - { - RPI::ShaderResourceGroup* srg = view->GetShaderResourceGroup().get(); - srg->SetConstant(m_shadowmapAtlasSizeIndex, static_cast(pass->GetShadowmapAtlasSize())); - const float invShadowmapSize = 1.0f / static_cast(pass->GetShadowmapAtlasSize()); - srg->SetConstant(m_invShadowmapAtlasSize, invShadowmapSize); - - m_lightBufferHandler.UpdateSrg(srg); - m_shadowBufferHandler.UpdateSrg(srg); - m_esmParameterBufferHandler.UpdateSrg(srg); - } - } - break; - } - } - - void SpotLightFeatureProcessor::SetRgbIntensity(LightHandle handle, const PhotometricColor& lightRgbIntensity) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetRgbIntensity()."); - - auto transformedColor = AZ::RPI::TransformColor(lightRgbIntensity, AZ::RPI::ColorSpaceId::LinearSRGB, AZ::RPI::ColorSpaceId::ACEScg); - - AZStd::array& rgbIntensity = m_spotLightData.GetData(handle.GetIndex()).m_rgbIntensity; - rgbIntensity[0] = transformedColor.GetR(); - rgbIntensity[1] = transformedColor.GetG(); - rgbIntensity[2] = transformedColor.GetB(); - - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetPosition()."); - - SpotLightData& light = m_spotLightData.GetData(handle.GetIndex()); - lightPosition.StoreToFloat3(light.m_position.data()); - - if (light.m_shadowIndex >= 0) - { - AZ_Assert(m_shadowProperties.find(handle) != m_shadowProperties.end(), "ShadowmapProperty is incorrect."); - m_shadowProperties.at(handle).m_shadowmapViewNeedsUpdate = true; - m_filterParameterNeedsUpdate = true; - } - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetDirection(LightHandle handle, const AZ::Vector3& lightDirection) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetDirection()."); - - SpotLightData& light = m_spotLightData.GetData(handle.GetIndex()); - lightDirection.GetNormalized().StoreToFloat3(light.m_direction.data()); - - if (light.m_shadowIndex >= 0) - { - AZ_Assert(m_shadowProperties.find(handle) != m_shadowProperties.end(), "ShadowmapProperty is incorrect."); - m_shadowProperties.at(handle).m_shadowmapViewNeedsUpdate = true; - m_filterParameterNeedsUpdate = true; - } - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetBulbRadius(LightHandle handle, float bulbRadius) - { - SpotLightData& light = m_spotLightData.GetData(handle.GetIndex()); - light.m_bulbRadius = bulbRadius; - UpdateBulbPositionOffset(light); - - if (light.m_shadowIndex >= 0) - { - auto itr = m_shadowProperties.find(handle); - AZ_Assert(itr != m_shadowProperties.end(), "ShadowmapProperty is incorrect."); - itr->second.m_shadowmapViewNeedsUpdate = true; - m_filterParameterNeedsUpdate = true; - } - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetConeAngles()."); - SpotLightData& light = m_spotLightData.GetData(handle.GetIndex()); - - if (light.m_shadowIndex < 0) - { - innerDegrees = AZStd::GetMin(innerDegrees, MaxSpotLightConeAngleDegree); - outerDegrees = AZStd::GetMin(outerDegrees, MaxSpotLightConeAngleDegree); - } - else - { - innerDegrees = AZStd::GetMin(innerDegrees, MaxSpotLightConeAngleDegreeWithShadow); - outerDegrees = AZStd::GetMin(outerDegrees, MaxSpotLightConeAngleDegreeWithShadow); - - AZ_Assert(m_shadowProperties.find(handle) != m_shadowProperties.end(), "ShadowmapProperty is incorrect."); - m_shadowProperties[handle].m_shadowmapViewNeedsUpdate = true; - m_filterParameterNeedsUpdate = true; - } - - light.m_innerConeAngle = cosf(DegToRad(innerDegrees) * 0.5f); - light.m_outerConeAngle = cosf(DegToRad(outerDegrees) * 0.5f); - m_lightProperties.GetData(handle.GetIndex()).m_outerConeAngle = DegToRad(outerDegrees); - UpdateBulbPositionOffset(light); - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetPenumbraBias(LightHandle handle, float penumbraBias) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetPenumbraBias()."); - - // Biases at 1.0 and -1.0 exactly can cause div by zero / inf in the shader, so clamp them just inside that range. - penumbraBias = AZStd::clamp(penumbraBias, -0.999f, 0.999f); - - // Change space from (-1.0 to 1.0) to (-1.0 to infinity) - penumbraBias = (2.0f * penumbraBias) / (1.0f - penumbraBias); - - m_spotLightData.GetData(handle.GetIndex()).m_penumbraBias = penumbraBias; - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetAttenuationRadius()."); - - attenuationRadius = AZStd::max(attenuationRadius, 0.001f); // prevent divide by zero. - SpotLightData& light = m_spotLightData.GetData(handle.GetIndex()); - light.m_invAttenuationRadiusSquared = 1.0f / (attenuationRadius * attenuationRadius); - - if (light.m_shadowIndex >= 0) - { - AZ_Assert(m_shadowProperties.find(handle) != m_shadowProperties.end(), "ShadowmapProperty is incorrect."); - m_shadowProperties[handle].m_shadowmapViewNeedsUpdate = true; - m_filterParameterNeedsUpdate = true; - } - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetShadowmapSize(LightHandle handle, ShadowmapSize shadowmapSize) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetShadowmapSize()."); - - if (shadowmapSize == ShadowmapSize::None) - { - CleanUpShadow(handle); - } - else - { - PrepareForShadow(handle, shadowmapSize); - } - } - - void SpotLightFeatureProcessor::SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) - { - ShadowProperty& property = GetOrCreateShadowProperty(handle); - const uint16_t shadowIndex = property.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_shadowFilterMethod = aznumeric_cast(method); - - m_deviceBufferNeedsUpdate = true; - property.m_shadowmapViewNeedsUpdate = true; - - if (m_shadowData.GetData(shadowIndex).m_shadowmapSize != - aznumeric_cast(ShadowmapSize::None)) - { - m_filterParameterNeedsUpdate = true; - - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->SetEnabledComputation( - method == ShadowFilterMethod::Esm || - method == ShadowFilterMethod::EsmPcf); - } - } - } - - void SpotLightFeatureProcessor::SetShadowBoundaryWidthAngle(LightHandle handle, float boundaryWidthDegree) - { - const auto& property = GetOrCreateShadowProperty(handle); - const uint16_t shadowIndex = property.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_boundaryScale = DegToRad(boundaryWidthDegree / 2.f); - m_filterParameterNeedsUpdate = true; - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count) - { - if (count > Shadow::MaxPcfSamplingCount) - { - AZ_Warning("SpotLightFeatureProcessor", false, "Sampling count exceed the limit."); - count = Shadow::MaxPcfSamplingCount; - } - const auto& property = GetOrCreateShadowProperty(handle); - const uint16_t shadowIndex = property.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_predictionSampleCount = count; - - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) - { - const auto& property = GetOrCreateShadowProperty(handle); - const uint16_t shadowIndex = property.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_pcfMethod = method; - - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count) - { - if (count > Shadow::MaxPcfSamplingCount) - { - AZ_Warning("SpotLightFeatureProcessor", false, "Sampling count exceed the limit."); - count = Shadow::MaxPcfSamplingCount; - } - auto property = m_shadowProperties.find(handle); - if (property == m_shadowProperties.end()) - { - // If shadow has not been ready yet, prepare it - // for placeholder of shadow filter method value. - PrepareForShadow(handle, ShadowmapSize::None); - property = m_shadowProperties.find(handle); - } - - const uint16_t shadowIndex = property->second.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_filteringSampleCount = count; - m_deviceBufferNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::SetSpotLightData(LightHandle handle, const SpotLightData& data) - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::SetSpotLightData()."); - - m_spotLightData.GetData(handle.GetIndex()) = data; - m_deviceBufferNeedsUpdate = true; - m_shadowmapPassNeedsUpdate = true; - } - - const Data::Instance SpotLightFeatureProcessor::GetLightBuffer()const - { - return m_lightBufferHandler.GetBuffer(); - } - - uint32_t SpotLightFeatureProcessor::GetLightCount() const - { - return m_lightBufferHandler.GetElementCount(); - } - - SpotLightFeatureProcessor::ShadowProperty& SpotLightFeatureProcessor::GetOrCreateShadowProperty(LightHandle handle) - { - auto propIt = m_shadowProperties.find(handle); - if (propIt == m_shadowProperties.end()) - { - // If shadow has not been ready yet, prepare it - // for placeholder of shadow filter method value. - PrepareForShadow(handle, ShadowmapSize::None); - propIt = m_shadowProperties.find(handle); - } - return propIt->second; - } - - void SpotLightFeatureProcessor::PrepareForShadow(LightHandle handle, ShadowmapSize size) - { - m_deviceBufferNeedsUpdate = true; - m_shadowmapPassNeedsUpdate = true; - - auto propIt = m_shadowProperties.find(handle); - - // If shadowmap size is already set, early return; - if (propIt != m_shadowProperties.end() && - m_shadowData.GetData(propIt->second.m_shadowHandle.GetIndex()).m_shadowmapSize == aznumeric_cast(size)) - { - return; - } - - // If shadow is not ready, prepare related structures. - if (propIt == m_shadowProperties.end()) - { - const uint16_t shadowIndex = m_shadowData.GetFreeSlotIndex(); - const uint16_t esmIndex = m_esmParameterData.GetFreeSlotIndex(); - AZ_Assert(shadowIndex == esmIndex, "Indices of shadow must coincide."); - - m_spotLightData.GetData(handle.GetIndex()).m_shadowIndex = m_shadowData.GetRawIndex(shadowIndex); - - ShadowProperty property; - property.m_shadowHandle = LightHandle(shadowIndex); - AZ::Name viewName(AZStd::string::format("SpotLightShadowView (lightId:%d)", handle.GetIndex())); - property.m_shadowmapView = RPI::View::CreateView(viewName, RPI::View::UsageShadow); - property.m_shadowmapViewNeedsUpdate = true; - m_shadowProperties.insert(AZStd::make_pair(handle, AZStd::move(property))); - - propIt = m_shadowProperties.find(handle); - } - - // Set shadowmap size to shadow data. - const uint16_t shadowIndex = propIt->second.m_shadowHandle.GetIndex(); - m_shadowData.GetData(shadowIndex).m_shadowmapSize = aznumeric_cast(size); - - m_filterParameterNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::CleanUpShadow(LightHandle handle) - { - const auto& propIt = m_shadowProperties.find(handle); - if (propIt == m_shadowProperties.end()) - { - return; - } - - const uint16_t shadowIndex = propIt->second.m_shadowHandle.GetIndex(); - m_shadowData.RemoveIndex(shadowIndex); - m_esmParameterData.RemoveIndex(shadowIndex); - m_shadowProperties.erase(handle); - m_spotLightData.GetData(handle.GetIndex()).m_shadowIndex = -1; - - // By removing shadow of a light, shadow indices of the other lights - // can become stale. So they should be updated. - for (auto& propIt2 : m_shadowProperties) - { - const LightHandle lightHandle = propIt2.first; - const LightHandle shadowHandle = propIt2.second.m_shadowHandle; - m_spotLightData.GetData(lightHandle.GetIndex()).m_shadowIndex = m_shadowData.GetRawIndex(shadowHandle.GetIndex()); - } - - m_shadowmapPassNeedsUpdate = true; - } - - void SpotLightFeatureProcessor::UpdateShadowmapViews() - { - if (m_spotLightShadowmapsPasses.empty() || m_esmShadowmapsPasses.empty()) - { - return; - } - - for (auto& it : m_shadowProperties) - { - if (!it.second.m_shadowmapViewNeedsUpdate) - { - continue; - } - it.second.m_shadowmapViewNeedsUpdate = false; - const SpotLightData& light = m_spotLightData.GetData(it.first.GetIndex()); - - const float invRadiusSquared = light.m_invAttenuationRadiusSquared; - if (invRadiusSquared <= 0.f) - { - AZ_Assert(false, "Attenuation radius have to be set before use the light."); - continue; - } - const float attenuationRadius = sqrtf(1.f / invRadiusSquared); - - constexpr float SmallAngle = 0.01f; - const float coneAngle = GetMax(m_lightProperties.GetData(it.first.GetIndex()).m_outerConeAngle, SmallAngle); - - // Set view's matrices. - RPI::ViewPtr view = it.second.m_shadowmapView; - Vector3 position = Vector3::CreateFromFloat3(light.m_position.data()); - const Vector3 direction = Vector3::CreateFromFloat3(light.m_direction.data()); - - // To handle bulb radius, set the position of the shadow caster behind the actual light depending on the radius of the bulb - // - // \ / - // \ / - // \_____/ <-- position of light itself (and forward plane of shadow casting view) - // . . - // . . - // * <-- position of shadow casting view - // - position += light.m_bulbPostionOffset * -direction; - const auto transform = Matrix3x4::CreateLookAt(position, position + direction); - view->SetCameraTransform(transform); - - // If you adjust "NearFarRatio" below, the constant "bias" in SpotLightShadow::GetVisibility() - // in SpotLightShadow.azsli should also be adjusted in order to avoid Peter-Pannings. - constexpr float NearFarRatio = 10000.f; - const float minDist = attenuationRadius / NearFarRatio; - - const float nearDist = GetMax(minDist, light.m_bulbPostionOffset); - float farDist = attenuationRadius + light.m_bulbPostionOffset; - - constexpr float AspectRatio = 1.0f; - - Matrix4x4 viewToClipMatrix; - MakePerspectiveFovMatrixRH( - viewToClipMatrix, - coneAngle, - AspectRatio, - nearDist, - farDist); - - view->SetViewToClipMatrix(viewToClipMatrix); - - const uint16_t shadowIndex = it.second.m_shadowHandle.GetIndex(); - SpotLightShadowData& shadow = m_shadowData.GetData(shadowIndex); - - EsmShadowmapsPass::FilterParameter& esmData = m_esmParameterData.GetData(shadowIndex); - if (shadow.m_shadowFilterMethod == aznumeric_cast(ShadowFilterMethod::Esm) || - shadow.m_shadowFilterMethod == aznumeric_cast(ShadowFilterMethod::EsmPcf)) - { - // Set parameters to calculate linear depth if ESM is used. - m_filterParameterNeedsUpdate = true; - esmData.m_isEnabled = true; - esmData.m_n_f_n = nearDist / (farDist - nearDist); - esmData.m_n_f = nearDist - farDist; - esmData.m_f = farDist; - } - else - { - // Reset enabling flag if ESM is not used. - esmData.m_isEnabled = false; - } - } - } - - void SpotLightFeatureProcessor::SetShadowParameterToShadowData() - { - for (const auto& propIt : m_shadowProperties) - { - const LightHandle& shadowHandle = propIt.second.m_shadowHandle; - AZ_Assert(shadowHandle.IsValid(), "Shadow handle is invalid."); - SpotLightShadowData& shadowData = m_shadowData.GetData(shadowHandle.GetIndex()); - - // Set depth bias matrix. - const Matrix4x4& worldToLightClipMatrix = propIt.second.m_shadowmapView->GetWorldToClipMatrix(); - const Matrix4x4 depthBiasMatrix = Shadow::GetClipToShadowmapTextureMatrix() * worldToLightClipMatrix; - shadowData.m_depthBiasMatrix = depthBiasMatrix; - shadowData.m_unprojectConstants = GetDepthUnprojectConstants(propIt.second.m_shadowmapView); - - m_deviceBufferNeedsUpdate = true; - } - } - - uint16_t SpotLightFeatureProcessor::GetLightIndexInSrg(LightHandle handle) const - { - AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to SpotLightFeatureProcessor::GetLightIndexInSrg()."); - - return m_spotLightData.GetRawIndex(handle.GetIndex()); - } - - void SpotLightFeatureProcessor::CachePasses() - { - const AZStd::vector validPipelineIds = CacheSpotLightShadowmapsPass(); - CacheEsmShadowmapsPass(validPipelineIds); - m_shadowmapPassNeedsUpdate = true; - } - - AZStd::vector SpotLightFeatureProcessor::CacheSpotLightShadowmapsPass() - { - const AZStd::vector& renderPipelines = GetParentScene()->GetRenderPipelines(); - const auto* passSystem = RPI::PassSystemInterface::Get(); - const AZStd::vector& passes = passSystem->GetPassesForTemplateName(Name("SpotLightShadowmapsTemplate")); - - AZStd::vector validPipelineIds; - m_spotLightShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - SpotLightShadowmapsPass* shadowPass = azrtti_cast(pass); - AZ_Assert(shadowPass, "It is not a SpotLightShadowmapsPass."); - for (const RPI::RenderPipelinePtr& pipeline : renderPipelines) - { - if (pipeline.get() == shadowPass->GetRenderPipeline()) - { - m_spotLightShadowmapsPasses.emplace_back(shadowPass); - validPipelineIds.push_back(shadowPass->GetRenderPipeline()->GetId()); - } - } - } - return validPipelineIds; - } - - void SpotLightFeatureProcessor::CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds) - { - const auto* passSystem = RPI::PassSystemInterface::Get(); - const AZStd::vector passes = passSystem->GetPassesForTemplateName(Name("EsmShadowmapsTemplate")); - - m_esmShadowmapsPasses.clear(); - for (RPI::Pass* pass : passes) - { - EsmShadowmapsPass* esmPass = azrtti_cast(pass); - AZ_Assert(esmPass, "It is not an EsmShadowmapsPass."); - if (esmPass->GetRenderPipeline() && - AZStd::find(validPipelineIds.begin(), validPipelineIds.end(), esmPass->GetRenderPipeline()->GetId()) != validPipelineIds.end() && - esmPass->GetLightTypeName() == m_lightTypeName) - { - m_esmShadowmapsPasses.emplace_back(esmPass); - } - } - } - - void SpotLightFeatureProcessor::UpdateFilterParameters() - { - if (m_filterParameterNeedsUpdate) - { - UpdateStandardDeviations(); - UpdateFilterOffsetsCounts(); - UpdateShadowmapPositionsInAtlas(); - SetFilterParameterToPass(); - m_filterParameterNeedsUpdate = false; - } - } - - void SpotLightFeatureProcessor::UpdateStandardDeviations() - { - if (m_esmShadowmapsPasses.empty()) - { - AZ_Error("SpotLightFeatureProcessor", false, "Cannot find a required pass."); - return; - } - - AZStd::vector standardDeviations(m_shadowData.GetDataCount()); - for (const auto& propIt : m_shadowProperties) - { - if (!NeedsFilterUpdate(propIt.second.m_shadowHandle)) - { - continue; - } - const SpotLightShadowData& shadow = m_shadowData.GetData(propIt.second.m_shadowHandle.GetIndex()); - const float boundaryWidthAngle = shadow.m_boundaryScale * 2.f; - constexpr float SmallAngle = 0.01f; - const float coneAngle = GetMax(m_lightProperties.GetData(propIt.first.GetIndex()).m_outerConeAngle, SmallAngle); - const float ratioToEntireWidth = boundaryWidthAngle / coneAngle; - const float widthInPixels = ratioToEntireWidth * shadow.m_shadowmapSize; - const float standardDeviation = widthInPixels / (2 * GaussianMathFilter::ReliableSectionFactor); - const int32_t shadowIndexInSrg = m_spotLightData.GetData(propIt.first.GetIndex()).m_shadowIndex; - standardDeviations[shadowIndexInSrg] = standardDeviation; - } - if (standardDeviations.empty()) - { - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->SetEnabledComputation(false); - } - return; - } - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->SetEnabledComputation(true); - esmPass->SetFilterParameters(standardDeviations); - } - } - - void SpotLightFeatureProcessor::UpdateFilterOffsetsCounts() - { - if (m_esmShadowmapsPasses.empty()) - { - AZ_Error("SpotLightFeatureProcessor", false, "Cannot find a required pass."); - return; - } - - // Get array of filter counts for the camera view. - const AZStd::array_view filterCounts = m_esmShadowmapsPasses.front()->GetFilterCounts(); - - // Create array of filter offsets. - AZStd::vector filterOffsets; - filterOffsets.reserve(filterCounts.size()); - uint32_t filterOffset = 0; - for (const uint32_t count : filterCounts) - { - filterOffsets.push_back(filterOffset); - filterOffset += count; - } - - for (auto& propIt : m_shadowProperties) - { - const LightHandle shadowHandle = propIt.second.m_shadowHandle; - EsmShadowmapsPass::FilterParameter& filterParameter = m_esmParameterData.GetData(shadowHandle.GetIndex()); - if (NeedsFilterUpdate(shadowHandle)) - { - // Write filter offsets and filter counts to ESM data. - const int32_t shadowIndexInSrg = m_spotLightData.GetData(propIt.first.GetIndex()).m_shadowIndex; - AZ_Assert(shadowIndexInSrg >= 0, "Shadow index in SRG must be non-negative."); - filterParameter.m_parameterOffset = filterOffsets[shadowIndexInSrg]; - filterParameter.m_parameterCount = filterCounts[shadowIndexInSrg]; - } - else - { - // If filter is not required, reset offsets and counts of filter in ESM data. - filterParameter.m_parameterOffset = 0; - filterParameter.m_parameterCount = 0; - } - } - } - - void SpotLightFeatureProcessor::UpdateShadowmapPositionsInAtlas() - { - if (m_spotLightShadowmapsPasses.empty()) - { - AZ_Error("SpotLightFeatureProcessor", false, "Cannot find a required pass."); - return; - } - - const ShadowmapAtlas& atlas = m_spotLightShadowmapsPasses.front()->GetShadowmapAtlas(); - for (auto& propIt : m_shadowProperties) - { - const uint16_t shadowIndex = propIt.second.m_shadowHandle.GetIndex(); - EsmShadowmapsPass::FilterParameter& esmData = m_esmParameterData.GetData(shadowIndex); - - // Set shadowmap size to ESM data. - const uint32_t shadowmapSize = m_shadowData.GetData(shadowIndex).m_shadowmapSize; - esmData.m_shadowmapSize = shadowmapSize; - - // Set shadowmap origin to ESM data. - const int32_t shadowIndexInSrg = m_spotLightData.GetData(propIt.first.GetIndex()).m_shadowIndex; - AZ_Assert(shadowIndexInSrg >= 0, "Shadow index required to be non-negative.") - const ShadowmapAtlas::Origin origin = atlas.GetOrigin(aznumeric_cast(shadowIndexInSrg)); - const AZStd::array originInSlice = origin.m_originInSlice; - esmData.m_shadowmapOriginInSlice = originInSlice; - } - } - - void SpotLightFeatureProcessor::SetFilterParameterToPass() - { - if (m_spotLightShadowmapsPasses.empty() || m_esmShadowmapsPasses.empty()) - { - AZ_Error("SpotLightFeatureProcessor", false, "Cannot find a required pass."); - return; - } - - // Create index table buffer. - const AZStd::string indexTableBufferName = - AZStd::string::format("IndexTableBuffer(Spot) %d", - m_shadowmapIndexTableBufferNameIndex++); - const ShadowmapAtlas& atlas = m_spotLightShadowmapsPasses.front()->GetShadowmapAtlas(); - const Data::Instance indexTableBuffer = atlas.CreateShadowmapIndexTableBuffer(indexTableBufferName); - - // Update ESM parameter buffer which is attached to - // both of Forward Pass and ESM Shadowmaps Pass. - m_esmParameterBufferHandler.UpdateBuffer(m_esmParameterData.GetDataVector()); - - // Set index table buffer and ESM parameter buffer to ESM pass. - for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) - { - esmPass->SetShadowmapIndexTableBuffer(indexTableBuffer); - esmPass->SetFilterParameterBuffer(m_esmParameterBufferHandler.GetBuffer()); - } - } - - bool SpotLightFeatureProcessor::NeedsFilterUpdate(LightHandle shadowHandle) const - { - const SpotLightShadowData& shadow = m_shadowData.GetData(shadowHandle.GetIndex()); - const bool useEsm = - (aznumeric_cast(shadow.m_shadowFilterMethod) == ShadowFilterMethod::Esm || - aznumeric_cast(shadow.m_shadowFilterMethod) == ShadowFilterMethod::EsmPcf); - return (aznumeric_cast(shadow.m_shadowmapSize) != ShadowmapSize::None) && useEsm; - } - - void SpotLightFeatureProcessor::UpdateBulbPositionOffset(SpotLightData& light) - { - // If we have the outer cone angle in radians, the offset is (radius * tan(pi/2 - coneRadians)). However - // light stores the cosine of outerConeRadians, making the equation (radius * tan(pi/2 - acosf(cosConeRadians)). - // This simplifies to the equation below. - float cosConeRadians = light.m_outerConeAngle; - light.m_bulbPostionOffset = light.m_bulbRadius * cosConeRadians / sqrt(1 - cosConeRadians * cosConeRadians); - } - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.h deleted file mode 100644 index fc48dde1a7..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SpotLightFeatureProcessor.h +++ /dev/null @@ -1,158 +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 -#include -#include -#include -#include -#include -#include -#include - -namespace AZ -{ - class Vector3; - class Color; - - namespace Render - { - struct SpotLightShadowData - { - Matrix4x4 m_depthBiasMatrix = Matrix4x4::CreateIdentity(); - uint32_t m_shadowmapArraySlice = 0; // array slice who has shadowmap in the atlas. - AZStd::array m_shadowmapOriginInSlice = { {0, 0 } }; // shadowmap origin in the slice of the atlas. - uint32_t m_shadowmapSize = static_cast(ShadowmapSize::None); // width and height of shadowmap. - uint32_t m_shadowFilterMethod = 0; // filtering method of shadows. - float m_boundaryScale = 0.f; // the half of boundary of lit/shadowed areas. (in degrees) - uint32_t m_predictionSampleCount = 0; // sample count to judge whether it is on the shadow boundary or not. - uint32_t m_filteringSampleCount = 0; - AZStd::array m_unprojectConstants = { {0, 0} }; - float m_bias = 0.0f; // Consider making this variable or the slope-scale depth bias be tuneable in the Editor - PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; - }; - - class SpotLightFeatureProcessor final - : public SpotLightFeatureProcessorInterface - { - public: - AZ_RTTI(AZ::Render::SpotLightFeatureProcessor, "{8823AFBB-761E-42A2-B665-BBDF6F63E10A}", AZ::Render::SpotLightFeatureProcessorInterface); - - static void Reflect(AZ::ReflectContext* context); - - SpotLightFeatureProcessor() = default; - virtual ~SpotLightFeatureProcessor() = default; - - // FeatureProcessor overrides ... - void Activate() override; - void Deactivate() override; - void Simulate(const SimulatePacket& packet) override; - void PrepareViews(const PrepareViewsPacket&, AZStd::vector>&) override; - void Render(const RenderPacket& packet) override; - - // SpotLightFeatureProcessorInterface overrides ... - LightHandle AcquireLight() override; - bool ReleaseLight(LightHandle& handle) override; - LightHandle CloneLight(LightHandle handle) override; - void SetRgbIntensity(LightHandle handle, const PhotometricColor& lightColor) override; - void SetPosition(LightHandle handle, const Vector3& lightPosition) override; - void SetDirection(LightHandle handle, const Vector3& direction) override; - void SetBulbRadius(LightHandle handle, float bulbRadius) override; - void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) override; - void SetPenumbraBias(LightHandle handle, float penumbraBias) override; - void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override; - void SetShadowmapSize(LightHandle lightId, ShadowmapSize shadowmapSize) override; - void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; - void SetShadowBoundaryWidthAngle(LightHandle handle, float boundaryWidthDegree) override; - void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; - void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; - void SetPcfMethod(LightHandle handle, PcfMethod method); - void SetSpotLightData(LightHandle handle, const SpotLightData& data) override; - - const Data::Instance GetLightBuffer() const; - uint32_t GetLightCount()const; - - private: - struct LightProperty - { - float m_outerConeAngle = 0.f; // in radians. - }; - struct ShadowProperty - { - LightHandle m_shadowHandle; - RPI::ViewPtr m_shadowmapView; - uint16_t m_viewTagIndex = SpotLightShadowmapsPass::InvalidIndex; - bool m_shadowmapViewNeedsUpdate = false; - }; - - SpotLightFeatureProcessor(const SpotLightFeatureProcessor&) = delete; - - // RPI::SceneNotificationBus::Handler overrides... - void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override; - void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override; - void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override; - - uint16_t GetLightIndexInSrg(LightHandle handle) const; - - // shadow specific functions - ShadowProperty& GetOrCreateShadowProperty(LightHandle handle); - void PrepareForShadow(LightHandle handle, ShadowmapSize size); - void CleanUpShadow(LightHandle handle); - void UpdateShadowmapViews(); - void SetShadowParameterToShadowData(); - - void UpdateBulbPositionOffset(SpotLightData& light); - - // This caches SpotLightShadowmapsPass and EsmShadowmapsPass. - void CachePasses(); - AZStd::vector CacheSpotLightShadowmapsPass(); - void CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds); - - //! This updates the parameter of Gaussian filter used in ESM. - void UpdateFilterParameters(); - void UpdateStandardDeviations(); - void UpdateFilterOffsetsCounts(); - void UpdateShadowmapPositionsInAtlas(); - void SetFilterParameterToPass(); - bool NeedsFilterUpdate(LightHandle shadowHandle) const; - - AZStd::unordered_map m_shadowProperties; - IndexedDataVector m_lightProperties; - - AZStd::vector m_spotLightShadowmapsPasses; - AZStd::vector m_esmShadowmapsPasses; - - GpuBufferHandler m_lightBufferHandler; - IndexedDataVector m_spotLightData; - - GpuBufferHandler m_shadowBufferHandler; - IndexedDataVector m_shadowData; - - GpuBufferHandler m_esmParameterBufferHandler; - IndexedDataVector m_esmParameterData; - - bool m_deviceBufferNeedsUpdate = false; - bool m_shadowmapPassNeedsUpdate = true; - bool m_filterParameterNeedsUpdate = false; - uint32_t m_shadowmapIndexTableBufferNameIndex = 0; - - RHI::ShaderInputConstantIndex m_shadowmapAtlasSizeIndex; - RHI::ShaderInputConstantIndex m_invShadowmapAtlasSize; - - const Name m_lightTypeName = Name("spot"); - }; - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp index 87f7396fc4..7abc6698fa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp @@ -265,7 +265,7 @@ namespace AZ void DecalFeatureProcessor::SetDecalTransform(DecalHandle handle, const AZ::Transform& world) { // https://jira.agscollab.com/browse/ATOM-4330 - // Original Lumberyard uploads a 4x4 matrix rather than quaternion, rotation, scale. + // Original Open 3D Engine uploads a 4x4 matrix rather than quaternion, rotation, scale. // That is more memory but less calculation because it is doing a matrix inverse rather than a polar decomposition // I've done some experiments and uploading a 3x4 transform matrix with 3x3 matrix inverse should be possible // I am putting it as part of a separate Jira because I would have to upload different data to the light culling system diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp index e96c119a5a..eeb32cdd07 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp @@ -25,7 +25,7 @@ namespace AZ { DiffuseProbeGrid::~DiffuseProbeGrid() { - m_scene->GetCullingSystem()->UnregisterCullable(m_cullable); + m_scene->GetCullingScene()->UnregisterCullable(m_cullable); } void DiffuseProbeGrid::Init(RPI::Scene* scene, DiffuseProbeGridRenderData* renderData) @@ -646,7 +646,7 @@ namespace AZ m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable; // register with culling system - m_scene->GetCullingSystem()->RegisterOrUpdateCullable(m_cullable); + m_scene->GetCullingScene()->RegisterOrUpdateCullable(m_cullable); } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 694a8be9dd..95bbe13586 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -473,7 +473,7 @@ namespace AZ void MeshDataInstance::DeInit() { - m_scene->GetCullingSystem()->UnregisterCullable(m_cullable); + m_scene->GetCullingScene()->UnregisterCullable(m_cullable); // remove from ray tracing RayTracingFeatureProcessor* rayTracingFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -851,7 +851,7 @@ namespace AZ m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = localAabb.GetTransformedAabb(localToWorld); m_cullable.m_cullData.m_visibilityEntry.m_userData = &m_cullable; m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable; - m_scene->GetCullingSystem()->RegisterOrUpdateCullable(m_cullable); + m_scene->GetCullingScene()->RegisterOrUpdateCullable(m_cullable); m_cullBoundsNeedsUpdate = false; } diff --git a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp index d01eb1e8a4..d7bbc315ed 100644 --- a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp @@ -55,17 +55,29 @@ namespace AZ return false; } - // Get the shader variant and instance SRG - const RPI::ShaderVariant& shaderVariant = m_morphTargetShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + AZ::RPI::ShaderOptionGroup shaderOptionGroup = m_morphTargetShader->CreateShaderOptionGroup(); + // In case there are several options you don't care about, it's good practice to initialize them with default values. + shaderOptionGroup.SetUnspecifiedToDefaultValues(); + shaderOptionGroup.SetValue(AZ::Name("o_hasColorDeltas"), RPI::ShaderOptionValue{ m_morphTargetMetaData.m_hasColorDeltas }); - RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor; - shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); + // Get the shader variant and instance SRG + RPI::ShaderReloadNotificationBus::Handler::BusConnect(m_morphTargetShader->GetAssetId()); + const RPI::ShaderVariant& shaderVariant = m_morphTargetShader->GetVariant(shaderOptionGroup.GetShaderVariantId()); if (!InitPerInstanceSRG()) { return false; } + if (!shaderVariant.IsFullyBaked() && m_instanceSrg->HasShaderVariantKeyFallbackEntry()) + { + m_instanceSrg->SetShaderVariantKeyFallbackValue(shaderOptionGroup.GetShaderVariantKeyFallbackValue()); + } + + RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor; + shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); + + InitRootConstants(pipelineStateDescriptor.m_pipelineLayoutDescriptor->GetRootConstantsLayout()); m_dispatchItem.m_pipelineState = m_morphTargetShader->AcquirePipelineState(pipelineStateDescriptor); @@ -130,6 +142,9 @@ namespace AZ AZ_Error("MorphTargetDispatchItem", tangentOffsetIndex.IsValid(), "Could not find root constant 's_targetTangentOffset' in the shader"); auto bitangentOffsetIndex = rootConstantsLayout->FindShaderInputIndex(AZ::Name{ "s_targetBitangentOffset" }); AZ_Error("MorphTargetDispatchItem", bitangentOffsetIndex.IsValid(), "Could not find root constant 's_targetBitangentOffset' in the shader"); + auto colorOffsetIndex = rootConstantsLayout->FindShaderInputIndex(AZ::Name{ "s_targetColorOffset" }); + AZ_Error("MorphTargetDispatchItem", colorOffsetIndex.IsValid(), "Could not find root constant 's_targetColorOffset' in the shader"); + auto minIndex = rootConstantsLayout->FindShaderInputIndex(AZ::Name{ "s_min" }); AZ_Error("MorphTargetDispatchItem", minIndex.IsValid(), "Could not find root constant 's_min' in the shader"); auto maxIndex = rootConstantsLayout->FindShaderInputIndex(AZ::Name{ "s_max" }); @@ -151,6 +166,11 @@ namespace AZ m_rootConstantData.SetConstant(tangentOffsetIndex, m_morphInstanceMetaData.m_accumulatedTangentDeltaOffsetInBytes / 4); m_rootConstantData.SetConstant(bitangentOffsetIndex, m_morphInstanceMetaData.m_accumulatedBitangentDeltaOffsetInBytes / 4); + if (m_morphTargetMetaData.m_hasColorDeltas) + { + m_rootConstantData.SetConstant(colorOffsetIndex, m_morphInstanceMetaData.m_accumulatedColorDeltaOffsetInBytes / 4); + } + m_dispatchItem.m_rootConstantSize = m_rootConstantData.GetConstantData().size(); m_dispatchItem.m_rootConstants = m_rootConstantData.GetConstantData().data(); } @@ -179,6 +199,22 @@ namespace AZ } } + void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset) + { + if (!Init()) + { + AZ_Error("MorphTargetDispatchItem", false, "Failed to re-initialize after the shader asset was re-loaded."); + } + } + + void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId) + { + if (!Init()) + { + AZ_Error("MorphTargetDispatchItem", false, "Failed to re-initialize after the shader variant was loaded."); + } + } + float ComputeMorphTargetIntegerEncoding(const AZStd::vector& morphTargetMetaDatas) { // The accumulation buffer must be stored as an int to support InterlockedAdd in AZSL diff --git a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h index c12de5ec9a..46680eb465 100644 --- a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h +++ b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h @@ -72,6 +72,8 @@ namespace AZ // ShaderInstanceNotificationBus::Handler overrides void OnShaderReinitialized(const RPI::Shader& shader) override; + void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; + void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override; RHI::DispatchItem m_dispatchItem; diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 68de2b87bb..6e95944dab 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -195,14 +194,6 @@ namespace AZ constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_directionalLightCount")); m_rayTracingSceneSrg->SetConstant(constantIndex, directionalLightFP->GetLightCount()); - // spot lights - const auto spotLightFP = GetParentScene()->GetFeatureProcessor(); - bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_spotLights")); - m_rayTracingSceneSrg->SetBufferView(bufferIndex, spotLightFP->GetLightBuffer()->GetBufferView()); - - constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_spotLightCount")); - m_rayTracingSceneSrg->SetConstant(constantIndex, spotLightFP->GetLightCount()); - // point lights const auto pointLightFP = GetParentScene()->GetFeatureProcessor(); bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_pointLights")); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 51303436ee..86c012731c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -31,7 +31,7 @@ namespace AZ ReflectionProbe::~ReflectionProbe() { Data::AssetBus::MultiHandler::BusDisconnect(); - m_scene->GetCullingSystem()->UnregisterCullable(m_cullable); + m_scene->GetCullingScene()->UnregisterCullable(m_cullable); m_meshFeatureProcessor->ReleaseMesh(m_visualizationMeshHandle); } @@ -363,7 +363,7 @@ namespace AZ m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable; // register with culling system - m_scene->GetCullingSystem()->RegisterOrUpdateCullable(m_cullable); + m_scene->GetCullingScene()->RegisterOrUpdateCullable(m_cullable); } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp new file mode 100644 index 0000000000..216a126953 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -0,0 +1,632 @@ +/* +* 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 +#include +#include +#include +#include +#include +#include + +namespace AZ::Render +{ + void ProjectedShadowFeatureProcessor::Reflect(ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext + ->Class() + ->Version(0); + } + } + + void ProjectedShadowFeatureProcessor::Activate() + { + const RHI::ShaderResourceGroupLayout* viewSrgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout(); + + GpuBufferHandler::Descriptor desc; + + desc.m_bufferName = "ProjectedShadowBuffer"; + desc.m_bufferSrgName = "m_projectedShadows"; + desc.m_elementCountSrgName = ""; + desc.m_elementSize = sizeof(ShadowData); + desc.m_srgLayout = viewSrgLayout; + + m_shadowBufferHandler = GpuBufferHandler(desc); + + desc.m_bufferName = "ProjectedFilterParamsBuffer"; + desc.m_bufferSrgName = "m_projectedFilterParams"; + desc.m_elementCountSrgName = ""; + desc.m_elementSize = sizeof(EsmShadowmapsPass::FilterParameter); + desc.m_srgLayout = viewSrgLayout; + + m_filterParamBufferHandler = GpuBufferHandler(desc); + + m_shadowmapAtlasSizeIndex = viewSrgLayout->FindShaderInputConstantIndex(Name("m_shadowmapAtlasSize")); + m_invShadowmapAtlasSizeIndex = viewSrgLayout->FindShaderInputConstantIndex(Name("m_invShadowmapAtlasSize")); + + CachePasses(); + EnableSceneNotification(); + } + + void ProjectedShadowFeatureProcessor::Deactivate() + { + DisableSceneNotification(); + + m_shadowData.Clear(); + m_shadowBufferHandler.Release(); + m_filterParamBufferHandler.Release(); + + m_shadowProperties.Clear(); + + m_projectedShadowmapsPasses.clear(); + m_esmShadowmapsPasses.clear(); + + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->SetEnabledComputation(false); + } + } + + + ProjectedShadowFeatureProcessor::ShadowId ProjectedShadowFeatureProcessor::AcquireShadow() + { + // Reserve a new slot in m_shadowData + size_t index = m_shadowData.Reserve(); + if (index >= std::numeric_limits::max()) + { + m_shadowData.Release(index); + return ShadowId::Null; + } + + ShadowId id = ShadowId(aznumeric_cast(index)); + InitializeShadow(id); + + return id; + } + + void ProjectedShadowFeatureProcessor::ReleaseShadow(ShadowId id) + { + if (id.IsValid()) + { + m_shadowProperties.RemoveIndex(m_shadowData.GetElement(id.GetIndex())); + m_shadowData.Release(id.GetIndex()); + } + + m_shadowmapPassNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetShadowTransform(ShadowId id, Transform transform) + { + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_desc.m_transform = transform; + UpdateShadowView(shadowProperty); + } + + void ProjectedShadowFeatureProcessor::SetNearFarPlanes(ShadowId id, float nearPlaneDistance, float farPlaneDistance) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetFrontBackPlanes()."); + + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_desc.m_nearPlaneDistance = GetMax(nearPlaneDistance, 0.0001f); + shadowProperty.m_desc.m_farPlaneDistance = GetMax(farPlaneDistance, nearPlaneDistance + 0.0001f); + UpdateShadowView(shadowProperty); + } + + void ProjectedShadowFeatureProcessor::SetAspectRatio(ShadowId id, float aspectRatio) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetAspectRatio()."); + + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_desc.m_aspectRatio = aspectRatio; + UpdateShadowView(shadowProperty); + } + + void ProjectedShadowFeatureProcessor::SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetFieldOfViewY()."); + + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_desc.m_fieldOfViewYRadians = fieldOfViewYRadians; + UpdateShadowView(shadowProperty); + } + + void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution()."); + AZ_Assert(size != ShadowmapSize::None, "Shadowmap size cannot be set to None, remove the shadow instead."); + + FilterParameter& esmData = m_shadowData.GetElement(id.GetIndex()); + esmData.m_shadowmapSize = aznumeric_cast(size); + + m_deviceBufferNeedsUpdate = true; + m_shadowmapPassNeedsUpdate = true; + m_filterParameterNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method) + { + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_pcfMethod = method; + + m_deviceBufferNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod()."); + + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_shadowFilterMethod = aznumeric_cast(method); + + UpdateShadowView(shadowProperty); + + m_shadowmapPassNeedsUpdate = true; + m_filterParameterNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowBoundaryWidthAngle()."); + + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_boundaryScale = boundaryWidthRadians / 2.0f; + + m_shadowmapPassNeedsUpdate = true; + m_filterParameterNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetPredictionSampleCount(ShadowId id, uint16_t count) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPredictionSampleCount()."); + + AZ_Warning("ProjectedShadowFeatureProcessor", count <= Shadow::MaxPcfSamplingCount, "Sampling count exceed the limit."); + count = GetMin(count, Shadow::MaxPcfSamplingCount); + + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_predictionSampleCount = count; + + m_deviceBufferNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetFilteringSampleCount(ShadowId id, uint16_t count) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetFilteringSampleCount()."); + + AZ_Warning("ProjectedShadowFeatureProcessor", count <= Shadow::MaxPcfSamplingCount, "Sampling count exceed the limit."); + count = GetMin(count, Shadow::MaxPcfSamplingCount); + + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_filteringSampleCount = count; + + m_deviceBufferNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowProperties()."); + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_desc = descriptor; + UpdateShadowView(shadowProperty); + m_shadowmapPassNeedsUpdate = true; + m_filterParameterNeedsUpdate = true; + } + + auto ProjectedShadowFeatureProcessor::GetShadowProperties(ShadowId id) -> const ProjectedShadowDescriptor& + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::GetShadowProperties()."); + return GetShadowPropertyFromShadowId(id).m_desc; + } + + void ProjectedShadowFeatureProcessor::UpdateShadowView(ShadowProperty& shadowProperty) + { + const ProjectedShadowDescriptor& desc = shadowProperty.m_desc; + float nearDist = desc.m_nearPlaneDistance; + float farDist = desc.m_farPlaneDistance; + + // Adjust the near plane if it's too close to ensure accuracy. + constexpr float NearFarRatio = 1000.0f; + const float minDist = desc.m_farPlaneDistance / NearFarRatio; + nearDist = GetMax(minDist, nearDist); + + Matrix4x4 viewToClipMatrix; + MakePerspectiveFovMatrixRH( + viewToClipMatrix, + GetMax(desc.m_fieldOfViewYRadians, MinimumFieldOfView), + desc.m_aspectRatio, + nearDist, + farDist); + + RPI::ViewPtr view = shadowProperty.m_shadowmapView; + view->SetViewToClipMatrix(viewToClipMatrix); + view->SetCameraTransform(Matrix3x4::CreateFromTransform(desc.m_transform)); + + ShadowData& shadowData = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); + shadowData.m_bias = (nearDist / farDist) * 0.1f; + + FilterParameter& esmData = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); + if (FilterMethodIsEsm(shadowData)) + { + // Set parameters to calculate linear depth if ESM is used. + m_filterParameterNeedsUpdate = true; + esmData.m_isEnabled = true; + esmData.m_n_f_n = nearDist / (farDist - nearDist); + esmData.m_n_f = nearDist - farDist; + esmData.m_f = farDist; + } + else + { + // Reset enabling flag if ESM is not used. + esmData.m_isEnabled = false; + } + + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->SetEnabledComputation(esmData.m_isEnabled); + } + + // Set depth bias matrix. + const Matrix4x4& worldToLightClipMatrix = view->GetWorldToClipMatrix(); + const Matrix4x4 depthBiasMatrix = Shadow::GetClipToShadowmapTextureMatrix() * worldToLightClipMatrix; + shadowData.m_depthBiasMatrix = depthBiasMatrix; + + shadowData.m_unprojectConstants[0] = view->GetViewToClipMatrix().GetRow(2).GetElement(2); + shadowData.m_unprojectConstants[1] = view->GetViewToClipMatrix().GetRow(2).GetElement(3); + + m_deviceBufferNeedsUpdate = true; + } + + void ProjectedShadowFeatureProcessor::InitializeShadow(ShadowId shadowId) + { + m_deviceBufferNeedsUpdate = true; + m_shadowmapPassNeedsUpdate = true; + + // Reserve a slot in m_shadowProperties, and store that index in m_shadowData's second vector + uint16_t shadowPropertyIndex = m_shadowProperties.GetFreeSlotIndex(); + m_shadowData.GetElement(shadowId.GetIndex()) = shadowPropertyIndex; + + ShadowProperty& shadowProperty = m_shadowProperties.GetData(shadowPropertyIndex); + shadowProperty.m_shadowId = shadowId; + + AZ::Name viewName(AZStd::string::format("ProjectedShadowView (shadowId:%d)", shadowId.GetIndex())); + shadowProperty.m_shadowmapView = RPI::View::CreateView(viewName, RPI::View::UsageShadow); + + UpdateShadowView(shadowProperty); + } + + void ProjectedShadowFeatureProcessor::OnRenderPipelinePassesChanged(RPI::RenderPipeline* /*renderPipeline*/) + { + CachePasses(); + } + + void ProjectedShadowFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr /*renderPipeline*/) + { + CachePasses(); + } + + void ProjectedShadowFeatureProcessor::OnRenderPipelineRemoved( RPI::RenderPipeline* /*renderPipeline*/) + { + CachePasses(); + } + + void ProjectedShadowFeatureProcessor::CachePasses() + { + const AZStd::vector validPipelineIds = CacheProjectedShadowmapsPass(); + CacheEsmShadowmapsPass(validPipelineIds); + m_shadowmapPassNeedsUpdate = true; + } + + AZStd::vector ProjectedShadowFeatureProcessor::CacheProjectedShadowmapsPass() + { + const AZStd::vector& renderPipelines = GetParentScene()->GetRenderPipelines(); + const auto* passSystem = RPI::PassSystemInterface::Get();; + const AZStd::vector& passes = passSystem->GetPassesForTemplateName(Name("ProjectedShadowmapsTemplate")); + + AZStd::vector validPipelineIds; + m_projectedShadowmapsPasses.clear(); + for (RPI::Pass* pass : passes) + { + ProjectedShadowmapsPass* shadowPass = static_cast(pass); + for (const RPI::RenderPipelinePtr& pipeline : renderPipelines) + { + if (pipeline.get() == shadowPass->GetRenderPipeline()) + { + m_projectedShadowmapsPasses.emplace_back(shadowPass); + validPipelineIds.push_back(shadowPass->GetRenderPipeline()->GetId()); + } + } + } + return validPipelineIds; + } + + void ProjectedShadowFeatureProcessor::CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds) + { + static const Name LightTypeName = Name("projected"); + + const auto* passSystem = RPI::PassSystemInterface::Get(); + const AZStd::vector passes = passSystem->GetPassesForTemplateName(Name("EsmShadowmapsTemplate")); + + m_esmShadowmapsPasses.clear(); + for (RPI::Pass* pass : passes) + { + EsmShadowmapsPass* esmPass = static_cast(pass); + if (esmPass->GetRenderPipeline() && + AZStd::find(validPipelineIds.begin(), validPipelineIds.end(), esmPass->GetRenderPipeline()->GetId()) != validPipelineIds.end() && + esmPass->GetLightTypeName() == LightTypeName) + { + m_esmShadowmapsPasses.emplace_back(esmPass); + } + } + } + + void ProjectedShadowFeatureProcessor::UpdateFilterParameters() + { + if (m_filterParameterNeedsUpdate) + { + UpdateStandardDeviations(); + UpdateFilterOffsetsCounts(); + SetFilterParameterToPass(); + m_filterParameterNeedsUpdate = false; + } + } + + void ProjectedShadowFeatureProcessor::UpdateStandardDeviations() + { + if (m_esmShadowmapsPasses.empty()) + { + AZ_Error("ProjectedShadowFeatureProcessor", false, "Cannot find a required pass."); + return; + } + + AZStd::vector standardDeviations(m_shadowProperties.GetDataCount()); + + for (uint32_t i = 0; i < m_shadowProperties.GetDataCount(); ++i) + { + ShadowProperty& shadowProperty = m_shadowProperties.GetDataVector().at(i); + const ShadowData& shadow = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); + if (!FilterMethodIsEsm(shadow)) + { + continue; + } + const FilterParameter& filter = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); + const float boundaryWidthAngle = shadow.m_boundaryScale * 2.0f; + constexpr float SmallAngle = 0.01f; + const float fieldOfView = GetMax(shadowProperty.m_desc.m_fieldOfViewYRadians, MinimumFieldOfView); + const float ratioToEntireWidth = boundaryWidthAngle / fieldOfView; + const float widthInPixels = ratioToEntireWidth * filter.m_shadowmapSize; + standardDeviations.at(i) = widthInPixels / (2.0f * GaussianMathFilter::ReliableSectionFactor); + } + if (standardDeviations.empty()) + { + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->SetEnabledComputation(false); + } + return; + } + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->SetEnabledComputation(true); + esmPass->SetFilterParameters(standardDeviations); + } + } + + void ProjectedShadowFeatureProcessor::UpdateFilterOffsetsCounts() + { + if (m_esmShadowmapsPasses.empty()) + { + AZ_Error("ProjectedShadowFeatureProcessor", false, "Cannot find a required pass."); + return; + } + + // Get array of filter counts for the camera view. + const AZStd::array_view filterCounts = m_esmShadowmapsPasses.front()->GetFilterCounts(); + + // Create array of filter offsets. + AZStd::vector filterOffsets; + filterOffsets.reserve(filterCounts.size()); + uint32_t filterOffset = 0; + for (const uint32_t count : filterCounts) + { + filterOffsets.push_back(filterOffset); + filterOffset += count; + } + + auto& shadowProperties = m_shadowProperties.GetDataVector(); + for (uint32_t i = 0; i < shadowProperties.size(); ++i) + { + ShadowProperty& shadowProperty = shadowProperties.at(i); + const ShadowId shadowId = shadowProperty.m_shadowId; + ShadowData& shadowData = m_shadowData.GetElement(shadowId.GetIndex()); + FilterParameter& filterData = m_shadowData.GetElement(shadowId.GetIndex()); + + if (FilterMethodIsEsm(shadowData)) + { + filterData.m_parameterOffset = filterOffsets[i]; + filterData.m_parameterCount = filterCounts[i]; + } + else + { + // If filter is not required, reset offsets and counts of filter in ESM data. + filterData.m_parameterOffset = 0; + filterData.m_parameterCount = 0; + } + } + } + + void ProjectedShadowFeatureProcessor::SetFilterParameterToPass() + { + static uint32_t nameIndex = 0; + if (m_projectedShadowmapsPasses.empty() || m_esmShadowmapsPasses.empty()) + { + AZ_Error("ProjectedShadowFeatureProcessor", false, "Cannot find a required pass."); + return; + } + + // Create index table buffer. + // [GFX TODO ATOM-14851] Should not be creating a new buffer here, just map the data or orphan with new data. + const AZStd::string indexTableBufferName = AZStd::string::format("IndexTableBuffer(Projected) %d", nameIndex++); + const ShadowmapAtlas& atlas = m_projectedShadowmapsPasses.front()->GetShadowmapAtlas(); + const Data::Instance indexTableBuffer = atlas.CreateShadowmapIndexTableBuffer(indexTableBufferName); + + m_filterParamBufferHandler.UpdateBuffer(m_shadowData.GetRawData(), m_shadowData.GetSize()); + + // Set index table buffer and ESM parameter buffer to ESM pass. + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->SetShadowmapIndexTableBuffer(indexTableBuffer); + esmPass->SetFilterParameterBuffer(m_filterParamBufferHandler.GetBuffer()); + } + } + + void ProjectedShadowFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& /*packet*/) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "ProjectedShadowFeatureProcessor: Simulate"); + + if (m_shadowmapPassNeedsUpdate) + { + // Rebuild the shadow map sizes + AZStd::vector shadowmapSizes; + shadowmapSizes.reserve(m_shadowProperties.GetDataCount()); + + auto& shadowProperties = m_shadowProperties.GetDataVector(); + for (uint32_t i = 0; i < shadowProperties.size(); ++i) + { + ShadowProperty& shadowProperty = shadowProperties.at(i); + uint16_t shadowIndex = shadowProperty.m_shadowId.GetIndex(); + FilterParameter& filterData = m_shadowData.GetElement(shadowIndex); + + shadowmapSizes.push_back(); + ProjectedShadowmapsPass::ShadowmapSizeWithIndices& sizeWithIndices = shadowmapSizes.back(); + sizeWithIndices.m_size = static_cast(filterData.m_shadowmapSize); + sizeWithIndices.m_shadowIndexInSrg = shadowIndex; + } + + for (ProjectedShadowmapsPass* shadowPass : m_projectedShadowmapsPasses) + { + shadowPass->UpdateShadowmapSizes(shadowmapSizes); + } + + for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) + { + esmPass->QueueForBuildAttachments(); + } + + for (ProjectedShadowmapsPass* shadowPass : m_projectedShadowmapsPasses) + { + for (const auto& shadowProperty : shadowProperties) + { + const int16_t shadowIndexInSrg = shadowProperty.m_shadowId.GetIndex(); + ShadowData& shadowData = m_shadowData.GetElement(shadowIndexInSrg); + FilterParameter& filterData = m_shadowData.GetElement(shadowIndexInSrg); + const ShadowmapAtlas::Origin origin = shadowPass->GetOriginInAtlas(shadowIndexInSrg); + + shadowData.m_shadowmapArraySlice = origin.m_arraySlice; + filterData.m_shadowmapOriginInSlice = origin.m_originInSlice; + m_deviceBufferNeedsUpdate = true; + } + break; + } + + m_shadowmapPassNeedsUpdate = false; + } + + // This has to be called after UpdateShadowmapSizes(). + UpdateFilterParameters(); + + if (m_deviceBufferNeedsUpdate) + { + m_shadowBufferHandler.UpdateBuffer(m_shadowData.GetRawData(), m_shadowData.GetSize()); + m_deviceBufferNeedsUpdate = false; + } + } + + void ProjectedShadowFeatureProcessor::PrepareViews(const PrepareViewsPacket&, AZStd::vector>& outViews) + { + for (ProjectedShadowmapsPass* pass : m_projectedShadowmapsPasses) + { + RPI::RenderPipeline* renderPipeline = pass->GetRenderPipeline(); + if (renderPipeline) + { + auto& shadowProperties = m_shadowProperties.GetDataVector(); + for (uint32_t i = 0; i < shadowProperties.size(); ++i) + { + ShadowProperty& shadowProperty = shadowProperties.at(i); + uint16_t shadowIndex = shadowProperty.m_shadowId.GetIndex(); + const FilterParameter& filterData = m_shadowData.GetElement(shadowIndex); + if (filterData.m_shadowmapSize == aznumeric_cast(ShadowmapSize::None)) + { + continue; + } + + const RPI::PipelineViewTag& viewTag = pass->GetPipelineViewTagOfChild(i); + const RHI::DrawListMask drawListMask = renderPipeline->GetDrawListMask(viewTag); + if (shadowProperty.m_shadowmapView->GetDrawListMask() != drawListMask) + { + shadowProperty.m_shadowmapView->Reset(); + shadowProperty.m_shadowmapView->SetDrawListMask(drawListMask); + } + + outViews.emplace_back(AZStd::make_pair(viewTag, shadowProperty.m_shadowmapView)); + } + } + break; + } + } + + void ProjectedShadowFeatureProcessor::Render(const ProjectedShadowFeatureProcessor::RenderPacket& packet) + { + AZ_ATOM_PROFILE_FUNCTION("RPI", "ProjectedShadowFeatureProcessor: Render"); + + for (const ProjectedShadowmapsPass* pass : m_projectedShadowmapsPasses) + { + for (const RPI::ViewPtr& view : packet.m_views) + { + if (view->GetUsageFlags() & RPI::View::UsageFlags::UsageCamera) + { + RPI::ShaderResourceGroup* srg = view->GetShaderResourceGroup().get(); + + srg->SetConstant(m_shadowmapAtlasSizeIndex, static_cast(pass->GetShadowmapAtlasSize())); + const float invShadowmapSize = 1.0f / static_cast(pass->GetShadowmapAtlasSize()); + srg->SetConstant(m_invShadowmapAtlasSizeIndex, invShadowmapSize); + + m_shadowBufferHandler.UpdateSrg(srg); + m_filterParamBufferHandler.UpdateSrg(srg); + } + } + break; + } + } + + bool ProjectedShadowFeatureProcessor::FilterMethodIsEsm(const ShadowData& shadowData) const + { + return + aznumeric_cast(shadowData.m_shadowFilterMethod) == ShadowFilterMethod::Esm || + aznumeric_cast(shadowData.m_shadowFilterMethod) == ShadowFilterMethod::EsmPcf; + } + + auto ProjectedShadowFeatureProcessor::GetShadowPropertyFromShadowId(ShadowId id) -> ShadowProperty& + { + AZ_Assert(id.IsValid(), "Error: Invalid ShadowId"); + uint16_t shadowPropertyId = m_shadowData.GetElement(id.GetIndex()); + return m_shadowProperties.GetData(shadowPropertyId); + } + +} diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h new file mode 100644 index 0000000000..a131c914f2 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -0,0 +1,141 @@ +/* +* 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 +#include +#include +#include + +namespace AZ::Render +{ + //! This feature processor handles creation of shadow passes and manages shadow related data. Use AcquireShadow() + //! to create a new shadow. The ID that is returned from AcquireShadow() corresponds to an index in the + //! m_projectedShadows and m_projectedFilterParams buffers in the View SRG. + class ProjectedShadowFeatureProcessor final + : public ProjectedShadowFeatureProcessorInterface + { + public: + + AZ_RTTI(AZ::Render::ProjectedShadowFeatureProcessor, "{02AFA06D-8B37-4D47-91BD-849CAC7FB330}", AZ::Render::ProjectedShadowFeatureProcessorInterface); + + static void Reflect(AZ::ReflectContext* context); + + ProjectedShadowFeatureProcessor() = default; + virtual ~ProjectedShadowFeatureProcessor() = default; + + // FeatureProcessor overrides ... + void Activate() override; + void Deactivate() override; + void Simulate(const SimulatePacket& packet) override; + void PrepareViews(const PrepareViewsPacket&, AZStd::vector>&) override; + void Render(const RenderPacket& packet) override; + + // ProjectedShadowFeatureProcessorInterface overrides ... + ShadowId AcquireShadow() override; + void ReleaseShadow(ShadowId id) override; + void SetShadowTransform(ShadowId id, Transform transform) override; + void SetNearFarPlanes(ShadowId id, float nearPlaneDistance, float farPlaneDistance) override; + void SetAspectRatio(ShadowId id, float aspectRatio) override; + void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; + void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; + void SetPcfMethod(ShadowId id, PcfMethod method); + void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; + void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; + void SetPredictionSampleCount(ShadowId id, uint16_t count) override; + void SetFilteringSampleCount(ShadowId id, uint16_t count) override; + void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) override; + const ProjectedShadowDescriptor& GetShadowProperties(ShadowId id) override; + + private: + + // GPU data stored in m_projectedShadows. + struct ShadowData + { + Matrix4x4 m_depthBiasMatrix = Matrix4x4::CreateIdentity(); + uint32_t m_shadowmapArraySlice = 0; // array slice who has shadowmap in the atlas. + uint16_t m_shadowFilterMethod = 0; // filtering method of shadows. + PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; // method for performing Pcf (uint16_t) + float m_boundaryScale = 0.f; // the half of boundary of lit/shadowed areas. (in degrees) + uint32_t m_predictionSampleCount = 0; // sample count to judge whether it is on the shadow boundary or not. + uint32_t m_filteringSampleCount = 0; + AZStd::array m_unprojectConstants = { {0, 0} }; + float m_bias; + }; + + // CPU data used for constructing & updating ShadowData + struct ShadowProperty + { + ProjectedShadowDescriptor m_desc; + RPI::ViewPtr m_shadowmapView; + ShadowId m_shadowId; + }; + + using FilterParameter = EsmShadowmapsPass::FilterParameter; + static constexpr float MinimumFieldOfView = 0.001f; + + // RPI::SceneNotificationBus::Handler overrides... + void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override; + void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override; + void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override; + + // Shadow specific functions + void UpdateShadowView(ShadowProperty& shadowProperty); + void InitializeShadow(ShadowId shadowId); + + // Functions for caching the ProjectedShadowmapsPass and EsmShadowmapsPass. + void CachePasses(); + AZStd::vector CacheProjectedShadowmapsPass(); + void CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds); + + //! Functions to update the parameter of Gaussian filter used in ESM. + void UpdateFilterParameters(); + void UpdateStandardDeviations(); + void UpdateFilterOffsetsCounts(); + void SetFilterParameterToPass(); + bool FilterMethodIsEsm(const ShadowData& shadowData) const; + + ShadowProperty& GetShadowPropertyFromShadowId(ShadowId id); + + GpuBufferHandler m_shadowBufferHandler; // For ViewSRG m_projectedShadows + GpuBufferHandler m_filterParamBufferHandler; // For ViewSRG m_projectedFilterParams + + // Stores CPU side shadow information in a packed vector so it's easy to iterate through. + IndexedDataVector m_shadowProperties; + + // Used for easier indexing of m_shadowData + enum + { + ShadowDataIndex, + FilterParamIndex, + ShadowPropertyIdIndex, + }; + + // Stores GPU data that is pushed to buffers in the View SRG. ShadowData corresponds to m_projectedShadows and + // FilterParameter corresponds to m_projectedFilterParams. The uint16_t is used to reference data in + // m_shadowProperties. + MultiSparseVector m_shadowData; + + AZStd::vector m_projectedShadowmapsPasses; + AZStd::vector m_esmShadowmapsPasses; + + RHI::ShaderInputConstantIndex m_shadowmapAtlasSizeIndex; + RHI::ShaderInputConstantIndex m_invShadowmapAtlasSizeIndex; + + bool m_deviceBufferNeedsUpdate = false; + bool m_shadowmapPassNeedsUpdate = true; + bool m_filterParameterNeedsUpdate = false; + }; +} diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp index e415d25038..c9054fc6c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp @@ -52,6 +52,10 @@ namespace AZ { m_shaderOptions.m_applyMorphTargets = true; } + if (inputBuffers->GetLod(lodIndex).HasDynamicColors()) + { + m_shaderOptions.m_applyColorMorphTargets = true; + } // CreateShaderOptionGroup will also connect to the SkinnedMeshShaderOptionNotificationBus m_shaderOptionGroup = skinnedMeshComputePass->CreateShaderOptionGroup(m_shaderOptions, *this); @@ -129,9 +133,18 @@ namespace AZ AZ_Assert(false, "Invalid skinning method for SkinnedMeshDispatchItem."); } - AZ_Assert(aznumeric_cast(m_outputBufferOffsetsInBytes.size()) == static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams), "Not enough offsets were given to the SkinnedMeshDispatchItem"); + AZ_Assert(aznumeric_cast(m_outputBufferOffsetsInBytes.size()) == static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams) && m_shaderOptions.m_applyColorMorphTargets + || aznumeric_cast(m_outputBufferOffsetsInBytes.size()) == static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams) - 1 && !m_shaderOptions.m_applyColorMorphTargets, + "Not enough offsets were given to the SkinnedMeshDispatchItem"); + for (uint8_t outputStream = 0; outputStream < static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams); outputStream++) { + // Skip colors if they are not being morphed + if (outputStream == static_cast(SkinnedMeshOutputVertexStreams::Color) && !m_shaderOptions.m_applyColorMorphTargets) + { + continue; + } + // Set the buffer offsets const SkinnedMeshOutputVertexStreamInfo& outputStreamInfo = SkinnedMeshVertexStreamPropertyInterface::Get()->GetOutputStreamInfo(static_cast(outputStream)); { @@ -142,7 +155,7 @@ namespace AZ return false; } - // The shader has a view of with 4 bytes per element + // The shader has a view with 4 bytes per element // Divide the byte offset here so it doesn't need to be done in the shader m_instanceSrg->SetConstant(outputOffsetIndex, m_outputBufferOffsetsInBytes[outputStream] / 4); } @@ -164,6 +177,13 @@ namespace AZ // The buffer is using 32-bit integers, so divide the offset by 4 here so it doesn't have to be done in the shader m_instanceSrg->SetConstant(morphBitangentOffsetIndex, m_morphTargetInstanceMetaData.m_accumulatedBitangentDeltaOffsetInBytes / 4); + if (m_shaderOptions.m_applyColorMorphTargets) + { + RHI::ShaderInputConstantIndex morphColorOffsetIndex = m_instanceSrg->FindShaderInputConstantIndex(Name{ "m_morphTargetColorDeltaOffset" }); + // The buffer is using 32-bit integers, so divide the offset by 4 here so it doesn't have to be done in the shader + m_instanceSrg->SetConstant(morphColorOffsetIndex, m_morphTargetInstanceMetaData.m_accumulatedColorDeltaOffsetInBytes / 4); + } + RHI::ShaderInputConstantIndex morphDeltaIntegerEncodingIndex = m_instanceSrg->FindShaderInputConstantIndex(Name{ "m_morphTargetDeltaInverseIntegerEncoding" }); m_instanceSrg->SetConstant(morphDeltaIntegerEncodingIndex, 1.0f / m_morphTargetDeltaIntegerEncoding); diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index f6ad70ddce..343370ae35 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -74,7 +74,7 @@ namespace AZ return m_vertexCount; } - void SkinnedMeshInputLod::SetIndexBuffer(const Data::Asset bufferAsset) + void SkinnedMeshInputLod::SetIndexBufferAsset(const Data::Asset bufferAsset) { m_indexBufferAsset = bufferAsset; m_indexBuffer = RPI::Buffer::FindOrCreate(bufferAsset); @@ -109,12 +109,35 @@ namespace AZ m_inputBuffers[static_cast(inputStream)] = RPI::Buffer::FindOrCreate(bufferAsset); } + void SkinnedMeshInputLod::SetModelLodAsset(const Data::Asset& modelLodAsset) + { + m_modelLodAsset = modelLodAsset; + } + void SkinnedMeshInputLod::SetSkinningInputBufferAsset(const Data::Asset bufferAsset, SkinnedMeshInputVertexStreams inputStream) { + if (inputStream == SkinnedMeshInputVertexStreams::Color) + { + AZ_Assert(!m_hasStaticColors, "Attempting to set colors as skinning input (meaning they are dynamic) when they already exist as a static stream"); + m_hasDynamicColors = true; + } + m_inputBufferAssets[static_cast(inputStream)] = bufferAsset; m_inputBuffers[static_cast(inputStream)] = RPI::Buffer::FindOrCreate(bufferAsset); } + void SkinnedMeshInputLod::SetStaticBufferAsset(const Data::Asset bufferAsset, SkinnedMeshStaticVertexStreams staticStream) + { + if (staticStream == SkinnedMeshStaticVertexStreams::Color) + { + AZ_Assert(!m_hasDynamicColors, "Attempting to set colors as a static stream on a skinned mesh, when they already exist as a dynamic stream"); + m_hasStaticColors = true; + } + + m_staticBufferAssets[static_cast(staticStream)] = bufferAsset; + m_staticBuffers[static_cast(staticStream)] = RPI::Buffer::FindOrCreate(bufferAsset); + } + void SkinnedMeshInputLod::CreateStaticBuffer(void* data, SkinnedMeshStaticVertexStreams staticStream, const AZStd::string& bufferNamePrefix) { AZ_Assert(m_vertexCount > 0, "SkinnedMeshInputLod::CreateStaticBuffer called with a vertex count of 0. Make sure SetVertexCount has been called before trying to create any buffers."); @@ -169,24 +192,30 @@ namespace AZ void SkinnedMeshInputLod::CreateSharedSubMeshBufferViews() { - m_sharedSubMeshViews.resize(m_subMeshProperties.size()); + AZStd::array_view meshes = m_modelLodAsset->GetMeshes(); + m_sharedSubMeshViews.resize(meshes.size()); - // The index and static buffer views will be shared by all instances that use the same SkinnedMeshInputBuffers, so create them here - for (size_t i = 0; i < m_subMeshProperties.size(); ++i) - { - // Create the view into the index buffer - RHI::BufferViewDescriptor indexBufferViewDescriptor = RHI::BufferViewDescriptor::CreateTyped(m_subMeshProperties[i].m_indexOffset, m_subMeshProperties[i].m_indexCount, RHI::Format::R32_UINT); + // The index and static buffer views will be shared by all instances that use the same SkinnedMeshInputBuffers, so set them here + for (size_t i = 0; i < meshes.size(); ++i) + { + // Set the view into the index buffer + m_sharedSubMeshViews[i].m_indexBufferView = meshes[i].GetIndexBufferAssetView(); - m_sharedSubMeshViews[i].m_indexBufferView = RPI::BufferAssetView{ m_indexBufferAsset, indexBufferViewDescriptor }; - - // Create the views into the static buffers + // Set the views into the static buffers for (uint8_t staticStreamIndex = 0; staticStreamIndex < static_cast(SkinnedMeshStaticVertexStreams::NumVertexStreams); ++staticStreamIndex) { - const SkinnedMeshVertexStreamInfo& streamInfo = SkinnedMeshVertexStreamPropertyInterface::Get()->GetStaticStreamInfo(static_cast(staticStreamIndex)); - RHI::BufferViewDescriptor viewDescriptor = RHI::BufferViewDescriptor::CreateTyped(m_subMeshProperties[i].m_vertexOffset, m_subMeshProperties[i].m_vertexCount, streamInfo.m_elementFormat); + // Skip colors if they don't exist or are dynamic + if (staticStreamIndex == static_cast(SkinnedMeshStaticVertexStreams::Color) && !m_hasStaticColors) + { + continue; + } - RPI::BufferAssetView bufferView{ m_staticBufferAssets[staticStreamIndex], viewDescriptor }; - m_sharedSubMeshViews[i].m_staticStreamViews[staticStreamIndex] = bufferView; + const SkinnedMeshVertexStreamInfo& streamInfo = SkinnedMeshVertexStreamPropertyInterface::Get()->GetStaticStreamInfo(static_cast(staticStreamIndex)); + const RPI::BufferAssetView* bufferView = meshes[i].GetSemanticBufferAssetView(streamInfo.m_semantic.m_name); + if (bufferView) + { + m_sharedSubMeshViews[i].m_staticStreamViews[staticStreamIndex] = bufferView; + } } } } @@ -194,11 +223,24 @@ namespace AZ void SkinnedMeshInputLod::AddMorphTarget(const RPI::MorphTargetMetaAsset::MorphTarget& morphTarget, const Data::Asset& morphBufferAsset, const AZStd::string& bufferNamePrefix, float minWeight = 0.0f, float maxWeight = 1.0f) { m_morphTargetMetaDatas.push_back(MorphTargetMetaData{ minWeight, maxWeight, morphTarget.m_minPositionDelta, morphTarget.m_maxPositionDelta, morphTarget.m_numVertices, morphTarget.m_startIndex }); + + // Create a view into the larger per-lod morph buffer for this particular morph RHI::BufferViewDescriptor morphView = RHI::BufferViewDescriptor::CreateStructured(morphTarget.m_startIndex, morphTarget.m_numVertices, sizeof(RPI::PackedCompressedMorphTargetDelta)); RPI::BufferAssetView morphTargetDeltaView{ morphBufferAsset, morphView }; + m_morphTargetInputBuffers.push_back(aznew MorphTargetInputBuffers{ morphTargetDeltaView, bufferNamePrefix }); + + // If colors are going to be morphed, the SkinnedMeshInputLod needs to know so that it allocates memory for the dynamically updated colors + if (morphTarget.m_hasColorDeltas) + { + m_hasDynamicColors = true; + } } + bool SkinnedMeshInputLod::HasDynamicColors() const + { + return m_hasDynamicColors; + } const AZStd::vector& SkinnedMeshInputLod::GetMorphTargetMetaDatas() const { @@ -265,11 +307,22 @@ namespace AZ // Get the SRG indices for each input stream for (uint8_t inputStream = 0; inputStream < static_cast(SkinnedMeshInputVertexStreams::NumVertexStreams); ++inputStream) { + // Skip colors if they don't exist or are not being morphed + if (inputStream == static_cast(SkinnedMeshInputVertexStreams::Color) && !m_lods[lodIndex].m_hasDynamicColors) + { + continue; + } + const SkinnedMeshVertexStreamInfo& streamInfo = SkinnedMeshVertexStreamPropertyInterface::Get()->GetInputStreamInfo(static_cast(inputStream)); RHI::ShaderInputBufferIndex srgIndex = perInstanceSRG->FindShaderInputBufferIndex(streamInfo.m_shaderResourceGroupName); AZ_Error("SkinnedMeshInputBuffers", srgIndex.IsValid(), "Failed to find shader input index for '%s' in the skinning compute shader per-instance SRG.", streamInfo.m_shaderResourceGroupName.GetCStr()); - [[maybe_unused]] bool success = perInstanceSRG->SetBufferView(srgIndex, m_lods[lodIndex].m_inputBuffers[inputStream]->GetBufferView()); + [[maybe_unused]] bool success = false; + if (m_lods[lodIndex].m_inputBuffers[inputStream]) + { + success = perInstanceSRG->SetBufferView(srgIndex, m_lods[lodIndex].m_inputBuffers[inputStream]->GetBufferView()); + } + AZ_Error("SkinnedMeshInputBuffers", success, "Failed to bind buffer view for %s", streamInfo.m_bufferName.GetCStr()); } @@ -336,7 +389,22 @@ namespace AZ // used for dependency tracking between passes. This can be switched to a transient memory pool so that the memory is free // later in the frame once skinning is finished ATOM-14429 - AZStd::intrusive_ptr allocation = SkinnedMeshOutputStreamManagerInterface::Get()->Allocate(vertexCount * static_cast(MorphTargetConstants::s_unpackedMorphTargetDeltaSizeInBytes) * MorphTargetConstants::s_morphTargetDeltaTypeCount); + size_t perVertexSizeInBytes = static_cast(MorphTargetConstants::s_unpackedMorphTargetDeltaSizeInBytes) * MorphTargetConstants::s_morphTargetDeltaTypeCount; + if (lod.HasDynamicColors()) + { + // Naively, if colors are morphed by any of the morph targets, + // we'll allocate enough memory to store the accumulated color deltas for every vertex in the lod. + // This could be reduced by ATOM-14427 + + // We assume that the model has been padded to include colors even for the meshes which don't use them + // this could be reduced by dispatching the skinning shade + // for one mesh at a time instead of the entire lod at once ATOM-15078 + + // Add four floats for colors + perVertexSizeInBytes += 4 * sizeof(float); + } + + AZStd::intrusive_ptr allocation = SkinnedMeshOutputStreamManagerInterface::Get()->Allocate(vertexCount * perVertexSizeInBytes); if (!allocation) { // Suppress the OnMemoryFreed signal when releasing the previous successful allocations @@ -367,6 +435,16 @@ namespace AZ instanceMetaData.m_accumulatedTangentDeltaOffsetInBytes = instanceMetaData.m_accumulatedNormalDeltaOffsetInBytes + deltaStreamSizeInBytes; instanceMetaData.m_accumulatedBitangentDeltaOffsetInBytes = instanceMetaData.m_accumulatedTangentDeltaOffsetInBytes + deltaStreamSizeInBytes; + // Followed by colors + if (lod.HasDynamicColors()) + { + instanceMetaData.m_accumulatedColorDeltaOffsetInBytes = instanceMetaData.m_accumulatedBitangentDeltaOffsetInBytes + deltaStreamSizeInBytes; + } + else + { + instanceMetaData.m_accumulatedColorDeltaOffsetInBytes = MorphTargetConstants::s_invalidDeltaOffset; + } + // Track both the allocation and the metadata in the instance instance->m_morphTargetInstanceMetaData.push_back(instanceMetaData); lodAllocations.push_back(allocation); @@ -481,6 +559,12 @@ namespace AZ // So we want to pack all the positions for each sub-mesh together, all the normals together, etc. for (uint8_t outputStreamIndex = 0; outputStreamIndex < static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams); ++outputStreamIndex) { + // Skip colors if they don't exist or are not being morphed + if (outputStreamIndex == static_cast(SkinnedMeshOutputVertexStreams::Color) && !lod.m_hasDynamicColors) + { + continue; + } + if (!AllocateLodStream(outputStreamIndex, aznumeric_cast(lod.m_vertexCount), instance, streamOffsetsFromBufferStart, lodAllocations)) { return nullptr; @@ -513,14 +597,26 @@ namespace AZ // Create and set the views into the skinning output buffers for (uint8_t outputStreamIndex = 0; outputStreamIndex < static_cast(SkinnedMeshOutputVertexStreams::NumVertexStreams); ++outputStreamIndex) { + // Skip colors if they don't exist or are not being morphed + if (outputStreamIndex == static_cast(SkinnedMeshOutputVertexStreams::Color) && !lod.m_hasDynamicColors) + { + continue; + } AddSubMeshViewToModelLodCreator(outputStreamIndex, lod.m_vertexCount, lod.m_subMeshProperties[i].m_vertexCount, skinnedMeshOutputBufferAsset, streamOffsetsFromBufferStart, subMeshOffsetsFromStreamStart, modelLodCreator); } // Set the views into the static buffers for (uint8_t staticStreamIndex = 0; staticStreamIndex < static_cast(SkinnedMeshStaticVertexStreams::NumVertexStreams); ++staticStreamIndex) { + // Skip colors if they don't exist or are dynamic + if (!lod.m_sharedSubMeshViews[i].m_staticStreamViews[staticStreamIndex] + || (staticStreamIndex == static_cast(SkinnedMeshStaticVertexStreams::Color) && !lod.m_hasStaticColors)) + { + continue; + } + const SkinnedMeshVertexStreamInfo& staticStreamInfo = SkinnedMeshVertexStreamPropertyInterface::Get()->GetStaticStreamInfo(static_cast(staticStreamIndex)); - modelLodCreator.AddMeshStreamBuffer(staticStreamInfo.m_semantic, AZ::Name(), lod.m_sharedSubMeshViews[i].m_staticStreamViews[staticStreamIndex]); + modelLodCreator.AddMeshStreamBuffer(staticStreamInfo.m_semantic, AZ::Name(), *lod.m_sharedSubMeshViews[i].m_staticStreamViews[staticStreamIndex]); } Aabb localAabb = lod.m_subMeshProperties[i].m_aabb; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.cpp index e5f5018b77..a799acff7f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.cpp @@ -32,6 +32,10 @@ namespace AZ m_applyMorphTargetFalseValue = layout->FindValue(m_applyMorphTargetOptionIndex, AZ::Name("false")); m_applyMorphTargetTrueValue = layout->FindValue(m_applyMorphTargetOptionIndex, AZ::Name("true")); + m_applyColorMorphTargetOptionIndex = layout->FindShaderOptionIndex(AZ::Name("o_applyColorMorphTargets")); + m_applyColorMorphTargetFalseValue = layout->FindValue(m_applyColorMorphTargetOptionIndex, AZ::Name("false")); + m_applyColorMorphTargetTrueValue = layout->FindValue(m_applyColorMorphTargetOptionIndex, AZ::Name("true")); + SkinnedMeshShaderOptionNotificationBus::Event(this, &SkinnedMeshShaderOptionNotificationBus::Events::OnShaderReinitialized, this); } @@ -62,6 +66,15 @@ namespace AZ shaderOptionGroup.SetValue(m_applyMorphTargetOptionIndex, m_applyMorphTargetFalseValue); } + if (shaderOptions.m_applyColorMorphTargets) + { + shaderOptionGroup.SetValue(m_applyColorMorphTargetOptionIndex, m_applyColorMorphTargetTrueValue); + } + else + { + shaderOptionGroup.SetValue(m_applyColorMorphTargetOptionIndex, m_applyColorMorphTargetFalseValue); + } + shaderOptionGroup.SetUnspecifiedToDefaultValues(); return shaderOptionGroup; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.h b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.h index 23fe796141..aeff874f6f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.h +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshShaderOptionsCache.h @@ -59,6 +59,10 @@ namespace AZ RPI::ShaderOptionIndex m_applyMorphTargetOptionIndex; RPI::ShaderOptionValue m_applyMorphTargetFalseValue; RPI::ShaderOptionValue m_applyMorphTargetTrueValue; + + RPI::ShaderOptionIndex m_applyColorMorphTargetOptionIndex; + RPI::ShaderOptionValue m_applyColorMorphTargetFalseValue; + RPI::ShaderOptionValue m_applyColorMorphTargetTrueValue; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshVertexStreamProperties.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshVertexStreamProperties.cpp index 1fd3019050..de82d103ea 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshVertexStreamProperties.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshVertexStreamProperties.cpp @@ -74,6 +74,14 @@ namespace AZ RHI::ShaderSemantic{Name{"UNUSED"}} }; + m_inputStreamInfo[static_cast(SkinnedMeshInputVertexStreams::Color)] = SkinnedMeshVertexStreamInfo{ + RHI::Format::R32G32B32A32_FLOAT, + sizeof(AZ::Vector4), + Name{"SkinnedMeshInputColors"}, + Name{"m_sourceColors"}, + RHI::ShaderSemantic{Name{"UNUSED"}} + }; + // Attributes of the vertex buffers that are not used or modified during skinning, but are shared between all target models that share the same source m_staticStreamInfo[static_cast(SkinnedMeshStaticVertexStreams::UV_0)] = SkinnedMeshVertexStreamInfo{ RHI::Format::R32G32_FLOAT, @@ -83,6 +91,14 @@ namespace AZ RHI::ShaderSemantic{Name{"UV"}} }; + m_staticStreamInfo[static_cast(SkinnedMeshStaticVertexStreams::Color)] = SkinnedMeshVertexStreamInfo{ + RHI::Format::R32G32B32A32_FLOAT, + sizeof(AZ::Vector4), + Name{"SkinnedMeshStaticColors"}, + Name{"unused"}, + RHI::ShaderSemantic{Name{"COLOR"}} + }; + // Attributes of the vertex streams of the target model that is written to during skinning m_outputStreamInfo[static_cast(SkinnedMeshOutputVertexStreams::Position)] = SkinnedMeshOutputVertexStreamInfo{ RHI::Format::R32G32B32_FLOAT, @@ -119,6 +135,15 @@ namespace AZ RHI::ShaderSemantic{Name{"BITANGENT"}}, SkinnedMeshInputVertexStreams::BiTangent }; + + m_outputStreamInfo[static_cast(SkinnedMeshOutputVertexStreams::Color)] = SkinnedMeshOutputVertexStreamInfo{ + RHI::Format::R32G32B32A32_FLOAT, + sizeof(AZ::Vector4), + Name{"SkinnedMeshOutputColors"}, + Name{"m_targetColors"}, + RHI::ShaderSemantic{Name{"COLOR"}}, + SkinnedMeshInputVertexStreams::Color + }; { auto bufferPoolDesc = AZStd::make_unique(); diff --git a/Gems/Atom/Feature/Common/Code/Tests/SparseVectorTests.cpp b/Gems/Atom/Feature/Common/Code/Tests/SparseVectorTests.cpp new file mode 100644 index 0000000000..df46db36ff --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Tests/SparseVectorTests.cpp @@ -0,0 +1,292 @@ +/* +* 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 + +namespace UnitTest +{ + using namespace AZ; + using namespace AZ::Render; + + class SparseVectorTests + : public UnitTest::AllocatorsTestFixture + { + public: + void SetUp() override + { + UnitTest::AllocatorsTestFixture::SetUp(); + } + + void TearDown() override + { + UnitTest::AllocatorsTestFixture::TearDown(); + } + }; + + struct TestData + { + static constexpr int DefaultValueA = 100; + static constexpr float DefaultValueB = 123.45f; + static constexpr bool DefaultValueC = true; + + int a = DefaultValueA; + float b = DefaultValueB; + bool c = DefaultValueC; + }; + + TEST_F(SparseVectorTests, SparseVectorCreate) + { + // Simple test to make sure we can create a SparseVector and it initializes with no values. + SparseVector container; + EXPECT_EQ(0, container.GetSize()); + container.Clear(); + EXPECT_EQ(0, container.GetSize()); + } + + TEST_F(SparseVectorTests, SparseVectorReserveRelease) + { + SparseVector container; + constexpr size_t Count = 10; + size_t indices[Count]; + + // Create some elements + for (size_t i = 0; i < Count; ++i) + { + indices[i] = container.Reserve(); + } + + EXPECT_EQ(container.GetSize(), Count); + + // Ensure that the elements were created with valid indices + for (size_t i = 0; i < Count; ++i) + { + EXPECT_EQ(indices[i], i); + } + + // Check default initialization of struct and initialize primitive types + for (size_t i = 0; i < Count; ++i) + { + TestData& data = container.GetElement(indices[i]); + + // Ensure that the data was initialized properly. + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + + // Assign new unique values + data.a = TestData::DefaultValueA * i; + data.b = TestData::DefaultValueB * float(i); + data.c = i % 2 == 0; + } + + // Release every other element. + for (size_t i = 0; i < Count; i += 2) + { + container.Release(indices[i]); + } + + // Size should be unaffected by release since it just leaves empty slots. + EXPECT_EQ(container.GetSize(), Count); + + // Check the remaining slots to make sure the data is still correct + for (size_t i = 1; i < Count; i += 2) + { + TestData& data = container.GetElement(indices[i]); + + EXPECT_EQ(data.a, TestData::DefaultValueA * i); + EXPECT_EQ(data.b, TestData::DefaultValueB * float(i)); + EXPECT_EQ(data.c, i % 2 == 0); + } + + // Re-reserve the previously deleted elements + for (size_t i = 0; i < Count; i += 2) + { + indices[i] = container.Reserve(); + } + + // Make sure the new elements data is initialized to default. + for (size_t i = 0; i < Count; i += 2) + { + TestData& data = container.GetElement(indices[i]); + + // Ensure that the data was initialized properly. + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + } + + } + + TEST_F(SparseVectorTests, SparseVectorGetRawData) + { + SparseVector container; + constexpr size_t Count = 10; + size_t indices[Count]; + + // Create some elements + for (size_t i = 0; i < Count; ++i) + { + indices[i] = container.Reserve(); + } + + // Get the raw data pointer + const TestData* testData = container.GetRawData(); + + // Make sure the data in the raw array matches what's expected. + for (size_t i = 0; i < container.GetSize(); ++i) + { + const TestData& data = testData[i]; + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + } + + container.Clear(); + EXPECT_EQ(0, container.GetSize()); + } + + TEST_F(SparseVectorTests, MultiSparseVectorCreate) + { + // Simple test to make sure we can create a MultiSparseVector and it initializes with no values. + MultiSparseVector container; + EXPECT_EQ(0, container.GetSize()); + container.Clear(); + EXPECT_EQ(0, container.GetSize()); + } + + TEST_F(SparseVectorTests, MultiSparseVectorReserve) + { + MultiSparseVector container; + constexpr size_t Count = 10; + size_t indices[Count]; + + // Create some elements + for (size_t i = 0; i < Count; ++i) + { + indices[i] = container.Reserve(); + } + + EXPECT_EQ(container.GetSize(), Count); + + // Ensure that the elements were created with valid indices + for (size_t i = 0; i < Count; ++i) + { + EXPECT_EQ(indices[i], i); + } + + // Ensure that the data was initialized properly. + for (size_t i = 0; i < Count; ++i) + { + TestData& data = container.GetElement<0>(indices[i]); + + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + + data.a = TestData::DefaultValueA * i; + data.b = TestData::DefaultValueB * float(i); + data.c = i % 2 == 0; + + // Assign some values to the uninitialized primitive types + container.GetElement<1>(indices[i]) = i * 10; + container.GetElement<2>(indices[i]) = i * 20.0f; + } + + // Release every other element + for (size_t i = 0; i < Count; i += 2) + { + container.Release(indices[i]); + } + + // Size should be unaffected by release since it just leaves empty slots. + EXPECT_EQ(container.GetSize(), Count); + + // Check the remaining slots to make sure the data is still correct + for (size_t i = 1; i < Count; i += 2) + { + TestData& data = container.GetElement<0>(indices[i]); + + EXPECT_EQ(data.a, TestData::DefaultValueA * i); + EXPECT_EQ(data.b, TestData::DefaultValueB * float(i)); + EXPECT_EQ(data.c, i % 2 == 0); + + EXPECT_EQ(container.GetElement<1>(indices[i]), i * 10); + EXPECT_EQ(container.GetElement<2>(indices[i]), i * 20.0f); + } + + // Re-reserve the previously deleted elements + for (size_t i = 0; i < Count; i += 2) + { + indices[i] = container.Reserve(); + } + + // Make sure the new elements data is initialized to default. + for (size_t i = 0; i < Count; i += 2) + { + TestData& data = container.GetElement<0>(indices[i]); + + // Ensure that the data was initialized properly. + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + + EXPECT_EQ(container.GetElement<1>(indices[i]), 0); + EXPECT_EQ(container.GetElement<2>(indices[i]), 0.0f); + } + + } + + TEST_F(SparseVectorTests, MultiSparseVectorGetRawData) + { + MultiSparseVector container; + constexpr size_t Count = 10; + size_t indices[Count]; + + // Create some elements and give them values to check later. + for (size_t i = 0; i < Count; ++i) + { + indices[i] = container.Reserve(); + + container.GetElement<1>(i) = i * 10; + container.GetElement<2>(i) = i * 20.0f; + } + + // Get raw data arrays + const TestData* testData = container.GetRawData<0>(); + const int* testints = container.GetRawData<1>(); + const float* testfloats = container.GetRawData<2>(); + + // Check all the data to make sure it's accurate. + for (size_t i = 0; i < container.GetSize(); ++i) + { + const TestData& data = testData[i]; + EXPECT_EQ(data.a, TestData::DefaultValueA); + EXPECT_EQ(data.b, TestData::DefaultValueB); + EXPECT_EQ(data.c, TestData::DefaultValueC); + } + + for (size_t i = 0; i < container.GetSize(); ++i) + { + EXPECT_EQ(testints[i], i * 10); + } + + for (size_t i = 0; i < container.GetSize(); ++i) + { + EXPECT_EQ(testfloats[i], i * 20.0f); + } + + container.Clear(); + EXPECT_EQ(0, container.GetSize()); + } +} 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 954a418ac0..7e23bc340f 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -42,7 +42,9 @@ set(FILES Include/Atom/Feature/Utils/FrameCaptureBus.h Include/Atom/Feature/Utils/GpuBufferHandler.h Include/Atom/Feature/Utils/MultiIndexedDataVector.h + Include/Atom/Feature/Utils/MultiSparseVector.h Include/Atom/Feature/Utils/ProfilingCaptureBus.h + Include/Atom/Feature/Utils/SparseVector.h Include/Atom/Feature/LuxCore/LuxCoreBus.h Include/Atom/Feature/LuxCore/LuxCoreTexturePass.h Include/Atom/Feature/LuxCore/RenderTexturePass.h @@ -83,16 +85,18 @@ set(FILES Source/CoreLights/IndexedDataVector.inl Source/CoreLights/LtcCommon.h Source/CoreLights/LtcCommon.cpp - Source/CoreLights/SpotLightFeatureProcessor.h - Source/CoreLights/SpotLightFeatureProcessor.cpp - Source/CoreLights/SpotLightShadowmapsPass.h - Source/CoreLights/SpotLightShadowmapsPass.cpp Source/CoreLights/PointLightFeatureProcessor.h Source/CoreLights/PointLightFeatureProcessor.cpp Source/CoreLights/PolygonLightFeatureProcessor.h Source/CoreLights/PolygonLightFeatureProcessor.cpp + Source/CoreLights/ProjectedShadowmapsPass.h + Source/CoreLights/ProjectedShadowmapsPass.cpp Source/CoreLights/QuadLightFeatureProcessor.h Source/CoreLights/QuadLightFeatureProcessor.cpp + Source/CoreLights/SimplePointLightFeatureProcessor.h + Source/CoreLights/SimplePointLightFeatureProcessor.cpp + Source/CoreLights/SimpleSpotLightFeatureProcessor.h + Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp Source/CoreLights/Shadow.h Source/CoreLights/Shadow.cpp Source/CoreLights/ShadowmapAtlas.h @@ -246,10 +250,6 @@ set(FILES Source/PostProcessing/SsaoPasses.h Source/PostProcessing/SubsurfaceScatteringPass.cpp Source/PostProcessing/SubsurfaceScatteringPass.h - Source/ScreenSpace/DeferredFogSettings.cpp - Source/ScreenSpace/DeferredFogSettings.h - Source/ScreenSpace/DeferredFogPass.cpp - Source/ScreenSpace/DeferredFogPass.h Source/RayTracing/RayTracingFeatureProcessor.h Source/RayTracing/RayTracingFeatureProcessor.cpp Source/RayTracing/RayTracingAccelerationStructurePass.cpp @@ -262,6 +262,12 @@ set(FILES Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.h + Source/ScreenSpace/DeferredFogSettings.cpp + Source/ScreenSpace/DeferredFogSettings.h + Source/ScreenSpace/DeferredFogPass.cpp + Source/ScreenSpace/DeferredFogPass.h + Source/Shadows/ProjectedShadowFeatureProcessor.h + Source/Shadows/ProjectedShadowFeatureProcessor.cpp Source/SkinnedMesh/SkinnedMeshComputePass.cpp Source/SkinnedMesh/SkinnedMeshComputePass.h Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake index 7565c462e8..9034859707 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake @@ -18,8 +18,9 @@ set(FILES Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h Include/Atom/Feature/CoreLights/PolygonLightFeatureProcessorInterface.h Include/Atom/Feature/CoreLights/QuadLightFeatureProcessorInterface.h + Include/Atom/Feature/CoreLights/SimplePointLightFeatureProcessorInterface.h + Include/Atom/Feature/CoreLights/SimpleSpotLightFeatureProcessorInterface.h Include/Atom/Feature/CoreLights/ShadowConstants.h - Include/Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h Include/Atom/Feature/Decals/DecalFeatureProcessorInterface.h Include/Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h Include/Atom/Feature/DisplayMapper/DisplayMapperFeatureProcessorInterface.h @@ -64,6 +65,7 @@ set(FILES Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h + Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h Include/Atom/Feature/SkinnedMesh/SkinnedMeshFeatureProcessorBus.h Include/Atom/Feature/SkinnedMesh/SkinnedMeshFeatureProcessorInterface.h Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_tests_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_tests_files.cmake index 33b851aa25..17a596effa 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_tests_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_tests_files.cmake @@ -15,6 +15,7 @@ set(FILES Tests/CoreLights/ShadowmapAtlasTest.cpp Tests/IndexedDataVectorTests.cpp Tests/IndexableListTests.cpp + Tests/SparseVectorTests.cpp Tests/SkinnedMesh/SkinnedMeshDispatchItemTests.cpp Tests/Decals/DecalTextureArrayTests.cpp ) diff --git a/Gems/Atom/RHI/Vulkan/3rdParty/Findglad_vulkan.cmake b/Gems/Atom/RHI/Vulkan/3rdParty/Findglad_vulkan.cmake index 0a201e808a..1142e59009 100644 --- a/Gems/Atom/RHI/Vulkan/3rdParty/Findglad_vulkan.cmake +++ b/Gems/Atom/RHI/Vulkan/3rdParty/Findglad_vulkan.cmake @@ -12,6 +12,6 @@ ly_add_external_target( NAME glad_vulkan VERSION 2.0.0-beta - 3RDPARTY_ROOT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../External/glad + 3RDPARTY_ROOT_DIRECTORY ${LY_ROOT_FOLDER}/Gems/Atom/RHI/Vulkan/External/glad INCLUDE_DIRECTORIES include ) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h index c082e20332..c7e9cc4706 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h @@ -197,26 +197,26 @@ namespace AZ //! Selects an lod (based on size-in-screnspace) and adds the appropriate DrawPackets to the view. uint32_t AddLodDataToView(const Vector3& pos, const Cullable::LodData& lodData, RPI::View& view); - //! Centralized manager for culling-related processing. - //! There is one CullingSystem owned by each Scene, so external systems (such as FeatureProcessors) should - //! access the CullingSystem via their parent Scene. - class CullingSystem + //! Centralized manager for culling-related processing for a given scene. + //! There is one CullingScene owned by each Scene, so external systems (such as FeatureProcessors) should + //! access the CullingScene via their parent Scene. + class CullingScene { public: - AZ_RTTI(CullingSystem, "{5B23B55B-8A1D-4B0D-9760-15E87FC8518A}"); - AZ_CLASS_ALLOCATOR(CullingSystem, AZ::SystemAllocator, 0); - AZ_DISABLE_COPY_MOVE(CullingSystem); + AZ_RTTI(CullingScene, "{5B23B55B-8A1D-4B0D-9760-15E87FC8518A}"); + AZ_CLASS_ALLOCATOR(CullingScene, AZ::SystemAllocator, 0); + AZ_DISABLE_COPY_MOVE(CullingScene); - CullingSystem() = default; - virtual ~CullingSystem() = default; + CullingScene() = default; + virtual ~CullingScene() = default; void Activate(const class Scene* parentScene); void Deactivate(); - //! Notifies the CullingSystem that culling will begin for this frame. + //! Notifies the CullingScene that culling will begin for this frame. void BeginCulling(const AZStd::vector& views); - //! Notifies the CullingSystem that the culling is done for this frame. + //! Notifies the CullingScene that the culling is done for this frame. void EndCulling(); //! Performs render culling and lod selection for a View, then adds the visible renderpackets to that View. @@ -235,7 +235,7 @@ namespace AZ //! Is not threadsafe, so call this from the main thread outside of Begin/EndCulling() void UnregisterCullable(Cullable& cullable); - //! Returns the number of cullables that have been added to the CullingSystem + //! Returns the number of cullables that have been added to the CullingScene uint32_t GetNumCullables() const; CullingDebugContext& GetDebugContext() @@ -244,12 +244,13 @@ namespace AZ } static const size_t WorkListCapacity = 5; - using WorkListType = AZStd::fixed_vector; + using WorkListType = AZStd::fixed_vector; protected: size_t CountObjectsInScene(); const Scene* m_parentScene = nullptr; + AzFramework::IVisibilityScene* m_visScene = nullptr; CullingDebugContext m_debugCtx; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/FeatureProcessor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/FeatureProcessor.h index cf280bbd75..ccc5103bfc 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/FeatureProcessor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/FeatureProcessor.h @@ -70,7 +70,7 @@ namespace AZ //! Whether to run jobs in parallel or not (for debugging) RHI::JobPolicy m_jobPolicy; - class CullingSystem* m_cullingSystem; + class CullingScene* m_cullingScene; }; AZ_RTTI(FeatureProcessor, "{B8027170-C65C-4237-964D-B557FC9D7575}"); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h index a848f42068..aac6f4fb97 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -44,7 +44,7 @@ namespace AZ class FeatureProcessor; class ShaderResourceGroup; class ShaderResourceGroupAsset; - class CullingSystem; + class CullingScene; class DynamicDrawSystem; // Callback function to modify values of a ShaderResourceGroup @@ -162,9 +162,9 @@ namespace AZ bool HasOutputForPipelineState(RHI::DrawListTag drawListTag) const; - AZ::RPI::CullingSystem* GetCullingSystem() + AZ::RPI::CullingScene* GetCullingScene() { - return m_cullingSystem; + return m_cullingScene; } RenderPipelinePtr FindRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle); @@ -212,7 +212,7 @@ namespace AZ // CPU simulation job completion for track all feature processors' simulation jobs AZ::JobCompletion* m_simulationCompletion = nullptr; - AZ::RPI::CullingSystem* m_cullingSystem; + AZ::RPI::CullingScene* m_cullingScene; // Cached views for current rendering frame. It gets re-built every frame. AZ::RPI::FeatureProcessor::SimulatePacket m_simulatePacket; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetDelta.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetDelta.h index 6d3a6805ef..2cc46dc748 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetDelta.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetDelta.h @@ -16,6 +16,23 @@ namespace AZ::RPI { + namespace MorphTargetDeltaConstants + { + // Min/max values for compression should correspond to what is used in MorphTargetCompression.azsli + + // A tangent/bitangent/normal will be between -1.0 and 1.0 on any given axis + // The largest a delta needs to be is 2.0 in either positive or negative direction + // to modify a value from 1 to -1 or from -1 to 1 + constexpr float s_tangentSpaceDeltaMin = -2.0f; + constexpr float s_tangentSpaceDeltaMax = 2.0f; + + // A color will be between 0.0 and 1.0 for any given channel + // The largest a delta needs to be is positive or negative 1.0 + // to modify a value from 0 to 1 or from 1 to 0 + constexpr float s_colorDeltaMin = -1.0f; + constexpr float s_colorDeltaMax = 1.0f; + } + //! This class represents the data that is passed to the morph target compute shader for an individual delta //! See MorphTargetSRG.azsli for the corresponding shader struct //! It is 16-byte aligned to work with structured buffers @@ -32,8 +49,10 @@ namespace AZ::RPI uint32_t m_normalZTangentXYZ; // 8 bit padding plus 8 bits per component for bitangent deltas uint32_t m_padBitangentXYZ; + // 8 bits per component for color deltas + uint32_t m_colorRGBA; // Explicit padding so the struct is 16 byte aligned for structured buffers - uint32_t m_pad[3]; + uint32_t m_pad[2]; }; //! A morph target delta that is compressed, but split into individual components @@ -60,6 +79,12 @@ namespace AZ::RPI uint8_t m_bitangentX; uint8_t m_bitangentY; uint8_t m_bitangentZ; + + // 8 bits per channel for color deltas + uint8_t m_colorR; + uint8_t m_colorG; + uint8_t m_colorB; + uint8_t m_colorA; }; PackedCompressedMorphTargetDelta PackMorphTargetDelta(const CompressedMorphTargetDelta& compressedDelta); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetMetaAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetMetaAsset.h index 19b18347bc..5b92047226 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetMetaAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/MorphTargetMetaAsset.h @@ -56,6 +56,9 @@ namespace AZ::RPI float m_minPositionDelta; float m_maxPositionDelta; + //! Boolean to indicate the presence or absence of color deltas + bool m_hasColorDeltas = false; + static void Reflect(AZ::ReflectContext* context); }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index 4a26746e28..f16d2c6fc9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -114,7 +114,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(25); // [ATOM-14876] + ->Version(26); // [ATOM-14992] } } @@ -375,6 +375,8 @@ namespace AZ { ProductMeshContentList lodMeshes = SourceMeshListToProductMeshList(context, sourceMeshContentList, jointNameToIndexMap, morphTargetMetaCreator); + PadVerticesForSkinning(lodMeshes); + // By default, we merge meshes that share the same material bool canMergeMeshes = true; @@ -881,6 +883,61 @@ namespace AZ return productMeshList; } + void ModelAssetBuilderComponent::PadVerticesForSkinning(ProductMeshContentList& productMeshList) + { + // Check if this is a skinned mesh + if (!productMeshList.empty() && !productMeshList[0].m_skinWeights.empty()) + { + // First, do a pass to see if any mesh has morphed colors + bool hasMorphedColors = false; + for (ProductMeshContent& productMesh : productMeshList) + { + if (productMesh.m_hasMorphedColors) + { + hasMorphedColors = true; + break; + } + } + + for (ProductMeshContent& productMesh : productMeshList) + { + size_t vertexCount = productMesh.m_positions.size() / PositionFloatsPerVert; + + // Skinned meshes require that positions, normals, tangents, bitangents, all exist and have the same number + // of total elements. Pad buffers with missing data to make them align with positions and normals + if (productMesh.m_tangents.empty()) + { + productMesh.m_tangents.resize(vertexCount * TangentFloatsPerVert, 1.0f); + AZ_Warning(s_builderName, false, "Mesh '%s' is missing tangents and no defaults were generated. Skinned meshes require tangents. Dummy tangents will be inserted, which may result in rendering artifacts.", productMesh.m_name.GetCStr()); + } + if (productMesh.m_bitangents.empty()) + { + productMesh.m_bitangents.resize(vertexCount * BitangentFloatsPerVert, 1.0f); + AZ_Warning(s_builderName, false, "Mesh '%s' is missing bitangents and no defaults were generated. Skinned meshes require bitangents. Dummy bitangents will be inserted, which may result in rendering artifacts.", productMesh.m_name.GetCStr()); + } + + // If any of the meshes have morphed colors, padd all the meshes so that the color stream is aligned with the other skinned streams + if (hasMorphedColors) + { + if (productMesh.m_colorCustomNames.empty()) + { + productMesh.m_colorCustomNames.push_back(Name{ "COLOR" }); + } + + if (productMesh.m_colorSets.empty()) + { + productMesh.m_colorSets.resize(1); + } + + if (productMesh.m_colorSets[0].empty()) + { + productMesh.m_colorSets[0].resize(vertexCount * ColorFloatsPerVert, 0.0f); + } + } + } + } + } + void ModelAssetBuilderComponent::GatherVertexSkinningInfluences( const SourceMeshContent& sourceMesh, ProductMeshContent& productMesh, diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h index 44a49a72cb..a4fb569ef1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h @@ -124,6 +124,7 @@ namespace AZ MaterialUid m_materialUid; bool CanBeMerged() const { return m_clothData.empty(); } + bool m_hasMorphedColors = false; }; using ProductMeshContentList = AZStd::vector; @@ -197,6 +198,12 @@ namespace AZ AZStd::unordered_map& jointNameToIndexMap, MorphTargetMetaAssetCreator& morphTargetMetaCreator); + //! Checks if this is a skinned mesh and if soe, + //! adds some extra padding to make vertex streams align for skinning + //! Skinning is applied on an entire lod at once, so it presumes that + //! Each vertex stream that is modified by skinning is the same length + void PadVerticesForSkinning(ProductMeshContentList& productMeshList); + //! Takes in a ProductMeshContentList and merges all elements that share the same MaterialUid. ProductMeshContentList MergeMeshesByMaterialUid( const ProductMeshContentList& productMeshList); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp index 65d2fe72e4..7aace50760 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp @@ -232,25 +232,35 @@ namespace AZ::RPI const AZ::Vector3 deltaNormal = targetNormal - neutralNormal; - currentDelta.m_normalX = Compress(deltaNormal.GetX(), -2.0f, 2.0f); - currentDelta.m_normalY = Compress(deltaNormal.GetY(), -2.0f, 2.0f); - currentDelta.m_normalZ = Compress(deltaNormal.GetZ(), -2.0f, 2.0f); + currentDelta.m_normalX = Compress(deltaNormal.GetX(), MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_normalY = Compress(deltaNormal.GetY(), MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_normalZ = Compress(deltaNormal.GetZ(), MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); } // Tangent { // Insert zero-delta until morphed tangents are supported in SceneAPI - currentDelta.m_tangentX = Compress(0.0f, -2.0f, 2.0f); - currentDelta.m_tangentY = Compress(0.0f, -2.0f, 2.0f); - currentDelta.m_tangentZ = Compress(0.0f, -2.0f, 2.0f); + currentDelta.m_tangentX = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_tangentY = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_tangentZ = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); } // Bitangent { // Insert zero-delta until morphed bitangents are supported in SceneAPI - currentDelta.m_bitangentX = Compress(0.0f, -2.0f, 2.0f); - currentDelta.m_bitangentY = Compress(0.0f, -2.0f, 2.0f); - currentDelta.m_bitangentZ = Compress(0.0f, -2.0f, 2.0f); + currentDelta.m_bitangentX = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_bitangentY = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + currentDelta.m_bitangentZ = Compress(0.0f, MorphTargetDeltaConstants::s_tangentSpaceDeltaMin, MorphTargetDeltaConstants::s_tangentSpaceDeltaMax); + } + + // Color + { + metaData.m_hasColorDeltas = true; + productMesh.m_hasMorphedColors = true; + currentDelta.m_colorR = Compress(0.0f, MorphTargetDeltaConstants::s_colorDeltaMin, MorphTargetDeltaConstants::s_colorDeltaMax); + currentDelta.m_colorG = Compress(0.0f, MorphTargetDeltaConstants::s_colorDeltaMin, MorphTargetDeltaConstants::s_colorDeltaMax); + currentDelta.m_colorB = Compress(0.0f, MorphTargetDeltaConstants::s_colorDeltaMin, MorphTargetDeltaConstants::s_colorDeltaMax); + currentDelta.m_colorA = Compress(0.0f, MorphTargetDeltaConstants::s_colorDeltaMin, MorphTargetDeltaConstants::s_colorDeltaMax); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index e05dc6f506..c64f08e4f8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -237,25 +237,23 @@ namespace AZ } } - void CullingSystem::RegisterOrUpdateCullable(Cullable& cullable) + void CullingScene::RegisterOrUpdateCullable(Cullable& cullable) { - // [GFX TODO][ATOM-15036] Remove lock from CullingSystem visibility updates - m_mutex.lock(); - AZ::Interface::Get()->InsertOrUpdateEntry(cullable.m_cullData.m_visibilityEntry); - m_mutex.unlock(); + m_cullDataConcurrencyCheck.soft_lock(); + m_visScene->InsertOrUpdateEntry(cullable.m_cullData.m_visibilityEntry); + m_cullDataConcurrencyCheck.soft_unlock(); } - void CullingSystem::UnregisterCullable(Cullable& cullable) + void CullingScene::UnregisterCullable(Cullable& cullable) { - // [GFX TODO][ATOM-15036] Remove lock from CullingSystem visibility updates - m_mutex.lock(); - AZ::Interface::Get()->RemoveEntry(cullable.m_cullData.m_visibilityEntry); - m_mutex.unlock(); + m_cullDataConcurrencyCheck.soft_lock(); + m_visScene->RemoveEntry(cullable.m_cullData.m_visibilityEntry); + m_cullDataConcurrencyCheck.soft_unlock(); } - uint32_t CullingSystem::GetNumCullables() const + uint32_t CullingScene::GetNumCullables() const { - return AZ::Interface::Get()->GetEntryCount(); + return m_visScene->GetEntryCount(); } class AddObjectsToViewJob final @@ -269,10 +267,10 @@ namespace AZ const Scene* m_scene; View* m_view; Frustum m_frustum; - CullingSystem::WorkListType m_worklist; + CullingScene::WorkListType m_worklist; public: - AddObjectsToViewJob(CullingDebugContext& debugCtx, const Scene& scene, View& view, Frustum& frustum, CullingSystem::WorkListType& worklist) + AddObjectsToViewJob(CullingDebugContext& debugCtx, const Scene& scene, View& view, Frustum& frustum, CullingScene::WorkListType& worklist) : Job(true, nullptr) //auto-deletes, no JobContext , m_debugCtx(&debugCtx) , m_scene(&scene) @@ -292,7 +290,7 @@ namespace AZ uint32_t numDrawPackets = 0; uint32_t numVisibleCullables = 0; - for (const AzFramework::IVisibilitySystem::NodeData& nodeData : m_worklist) + for (const AzFramework::IVisibilityScene::NodeData& nodeData : m_worklist) { //If a node is entirely contained within the frustum, then we can skip the fine grained culling. bool nodeIsContainedInFrustum = ShapeIntersection::Contains(m_frustum, nodeData.m_bounds); @@ -415,9 +413,9 @@ namespace AZ } }; - void CullingSystem::ProcessCullables(const Scene& scene, View& view, AZ::Job& parentJob) + void CullingScene::ProcessCullables(const Scene& scene, View& view, AZ::Job& parentJob) { - AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "CullingSystem::ProcessCullables() - %s", view.GetName().GetCStr()); + AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "CullingScene::ProcessCullables() - %s", view.GetName().GetCStr()); const Matrix4x4& worldToClip = view.GetWorldToClipMatrix(); Frustum frustum = Frustum::CreateFromMatrixColumnMajor(worldToClip); @@ -447,7 +445,7 @@ namespace AZ } WorkListType worklist; - auto nodeVisitorLambda = [this, &scene, &view, &parentJob, &frustum, &worklist](const AzFramework::IVisibilitySystem::NodeData& nodeData) -> void + auto nodeVisitorLambda = [this, &scene, &view, &parentJob, &frustum, &worklist](const AzFramework::IVisibilityScene::NodeData& nodeData) -> void { AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "nodeVisitorLambda()"); AZ_Assert(nodeData.m_entries.size() > 0, "should not get called with 0 entries"); @@ -469,11 +467,11 @@ namespace AZ if (m_debugCtx.m_enableFrustumCulling) { - AZ::Interface::Get()->Enumerate(frustum, nodeVisitorLambda); + m_visScene->Enumerate(frustum, nodeVisitorLambda); } else { - AZ::Interface::Get()->EnumerateNoCull(nodeVisitorLambda); + m_visScene->EnumerateNoCull(nodeVisitorLambda); } if (worklist.size() > 0) @@ -534,23 +532,34 @@ namespace AZ return numVisibleDrawPackets; } - void CullingSystem::Activate(const Scene* parentScene) + void CullingScene::Activate(const Scene* parentScene) { m_parentScene = parentScene; + AZ_Assert(m_visScene == nullptr, "IVisibilityScene already created for this RPI::Scene"); + char sceneIdBuf[40] = ""; + m_parentScene->GetId().ToString(sceneIdBuf); + AZ::Name visSceneName(AZStd::string::format("RenderCullScene[%s]", sceneIdBuf)); + m_visScene = AZ::Interface::Get()->CreateVisibilityScene(visSceneName); + #ifdef AZ_CULL_DEBUG_ENABLED AZ_Assert(CountObjectsInScene() == 0, "The culling system should start with 0 entries in this scene."); #endif } - void CullingSystem::Deactivate() + void CullingScene::Deactivate() { #ifdef AZ_CULL_DEBUG_ENABLED AZ_Assert(CountObjectsInScene() == 0, "All culling entries must be removed from the scene before shutdown."); #endif + if (m_visScene) + { + AZ::Interface::Get()->DestroyVisibilityScene(m_visScene); + m_visScene = nullptr; + } } - void CullingSystem::BeginCulling(const AZStd::vector& views) + void CullingScene::BeginCulling(const AZStd::vector& views) { m_cullDataConcurrencyCheck.soft_lock(); @@ -591,16 +600,16 @@ namespace AZ } } - void CullingSystem::EndCulling() + void CullingScene::EndCulling() { m_cullDataConcurrencyCheck.soft_unlock(); } - size_t CullingSystem::CountObjectsInScene() + size_t CullingScene::CountObjectsInScene() { size_t numObjects = 0; - AZ::Interface::Get()->EnumerateNoCull( - [this, &numObjects](const AzFramework::IVisibilitySystem::NodeData& nodeData) + m_visScene->EnumerateNoCull( + [this, &numObjects](const AzFramework::IVisibilityScene::NodeData& nodeData) { for (AzFramework::VisibilityEntry* visibleEntry : nodeData.m_entries) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index a9c2714653..84d1499602 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -136,15 +136,16 @@ namespace AZ // -- View & DrawList -- const AZStd::vector& views = m_pipeline->GetViews(GetPipelineViewTag()); m_drawListView = {}; - for (const ViewPtr& view : views) + + if (!views.empty()) { + const ViewPtr& view = views.front(); + // Assert the view has our draw list (the view's DrawlistTags are collected from passes using its viewTag) AZ_Assert(view->HasDrawListTag(m_drawListTag), "View's DrawListTags out of sync with pass'. "); // Draw List m_drawListView = view->GetDrawList(m_drawListTag); - - break; } RenderPass::FrameBeginInternal(params); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index dc3b56e7d3..00054881a1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -85,7 +85,7 @@ namespace AZ Scene::Scene() { m_id = Uuid::CreateRandom(); - m_cullingSystem = aznew CullingSystem(); + m_cullingScene = aznew CullingScene(); SceneRequestBus::Handler::BusConnect(m_id); } @@ -105,7 +105,7 @@ namespace AZ m_pipelines.clear(); AZ::RPI::PassSystemInterface::Get()->ProcessQueuedChanges(); - delete m_cullingSystem; + delete m_cullingScene; } void Scene::Activate() @@ -114,7 +114,7 @@ namespace AZ m_activated = true; - m_cullingSystem->Activate(this); + m_cullingScene->Activate(this); // We have to tick the PassSystem in order for all the pass attachments to get created. // This has to be done before FeatureProcessors are activated, because they may try to @@ -139,7 +139,7 @@ namespace AZ fp->Deactivate(); } - m_cullingSystem->Deactivate(); + m_cullingScene->Deactivate(); m_activated = false; m_pipelineStatesLookup.clear(); @@ -424,8 +424,8 @@ namespace AZ // Init render packet m_renderPacket.m_views.clear(); - AZ_Assert(m_cullingSystem, "Culling System is not initialized"); - m_renderPacket.m_cullingSystem = m_cullingSystem; + AZ_Assert(m_cullingScene, "m_cullingScene is not initialized"); + m_renderPacket.m_cullingScene = m_cullingScene; m_renderPacket.m_jobPolicy = jobPolicy; @@ -486,15 +486,15 @@ namespace AZ } // Launch CullingSystem::ProcessCullables() jobs (will run concurrently with FeatureProcessor::Render() jobs) - m_cullingSystem->BeginCulling(m_renderPacket.m_views); + m_cullingScene->BeginCulling(m_renderPacket.m_views); for (ViewPtr& viewPtr : m_renderPacket.m_views) { AZ::Job* processCullablesJob = AZ::CreateJobFunction([this, &viewPtr](AZ::Job& thisJob) { - m_cullingSystem->ProcessCullables(*this, *viewPtr, thisJob); + m_cullingScene->ProcessCullables(*this, *viewPtr, thisJob); }, true, nullptr); //auto-deletes - if (m_cullingSystem->GetDebugContext().m_parallelOctreeTraversal) + if (m_cullingScene->GetDebugContext().m_parallelOctreeTraversal) { processCullablesJob->SetDependent(collectDrawPacketsCompletion); processCullablesJob->Start(); @@ -507,7 +507,7 @@ namespace AZ WaitAndCleanCompletionJob(collectDrawPacketsCompletion); - m_cullingSystem->EndCulling(); + m_cullingScene->EndCulling(); // Add dynamic draw data for all the views if (m_dynamicDrawSystem) 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 5b58e6ec6c..92ab90a9ab 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp @@ -103,7 +103,6 @@ namespace AZ pairItor->m_shaderAsset->GetShaderOptionGroupLayout(), pairItor->m_shaderVariantId); if (searchResult.IsRoot()) { - AZ_Error(LogName, false, "Searching for a variant should never yield the root variant: %s", shaderVariantTreeAsset.GetHint().c_str()); pairItor = newShaderVariantPendingRequests.erase(pairItor); continue; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetDelta.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetDelta.cpp index 287f7892c7..d49d42a001 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetDelta.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetDelta.cpp @@ -18,7 +18,7 @@ namespace AZ::RPI PackedCompressedMorphTargetDelta PackMorphTargetDelta(const CompressedMorphTargetDelta& compressedDelta) { - PackedCompressedMorphTargetDelta packedDelta{ 0,0,0,0,0,{0,0,0} }; + PackedCompressedMorphTargetDelta packedDelta{ 0,0,0,0,0,0,{0,0} }; packedDelta.m_morphedVertexIndex = compressedDelta.m_morphedVertexIndex; // Position x is in the most significant 16 bits, y is in the least significant 16 bits @@ -45,6 +45,12 @@ namespace AZ::RPI packedDelta.m_padBitangentXYZ |= static_cast(compressedDelta.m_bitangentY) << 8; packedDelta.m_padBitangentXYZ |= static_cast(compressedDelta.m_bitangentZ); + // Colors are in the least significant 24 bits (8 bits per channel) + packedDelta.m_colorRGBA |= static_cast(compressedDelta.m_colorR) << 24; + packedDelta.m_colorRGBA |= static_cast(compressedDelta.m_colorG) << 16; + packedDelta.m_colorRGBA |= static_cast(compressedDelta.m_colorB) << 8; + packedDelta.m_colorRGBA |= static_cast(compressedDelta.m_colorA); + return packedDelta; } @@ -77,6 +83,12 @@ namespace AZ::RPI compressedDelta.m_bitangentY = (packedDelta.m_padBitangentXYZ >> 8 ) & 0x000000FF; compressedDelta.m_bitangentZ = packedDelta.m_padBitangentXYZ & 0x000000FF; + // Colors are 4 channels, 8 bits per channel + compressedDelta.m_colorR = (packedDelta.m_colorRGBA >> 24) & 0x000000FF; + compressedDelta.m_colorG = (packedDelta.m_colorRGBA >> 16) & 0x000000FF; + compressedDelta.m_colorB = (packedDelta.m_colorRGBA >> 8) & 0x000000FF; + compressedDelta.m_colorA = packedDelta.m_colorRGBA & 0x000000FF; + return compressedDelta; } } // namespace AZ::RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetMetaAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetMetaAsset.cpp index ce91e66bd5..313e0bea31 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetMetaAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/MorphTargetMetaAsset.cpp @@ -28,6 +28,7 @@ namespace AZ::RPI ->Field("numVertices", &MorphTargetMetaAsset::MorphTarget::m_numVertices) ->Field("minPositionDelta", &MorphTargetMetaAsset::MorphTarget::m_minPositionDelta) ->Field("maxPositionDelta", &MorphTargetMetaAsset::MorphTarget::m_maxPositionDelta) + ->Field("hasColorDeltas", &MorphTargetMetaAsset::MorphTarget::m_hasColorDeltas) ; } } diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index e80e2870bb..980a9ac320 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -934,6 +934,7 @@ namespace UnitTest // *---*---*---* // \ / \ / \ / \ // *---*---*---* + template class TD; class TwoSeparatedPlanesMesh { public: diff --git a/Gems/Atom/RPI/Code/Tests/System/SceneTests.cpp b/Gems/Atom/RPI/Code/Tests/System/SceneTests.cpp index 527ea76b18..9acdc264c0 100644 --- a/Gems/Atom/RPI/Code/Tests/System/SceneTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/System/SceneTests.cpp @@ -204,6 +204,8 @@ namespace UnitTest EXPECT_TRUE(feature->m_viewSetCount == 1); pipeline2->SetPersistentView(viewTag, nullptr); EXPECT_TRUE(feature->m_viewSetCount == 2); + + testScene->Deactivate(); } TEST_F(SceneTests, SceneNotificationTest_ConnectAfterRenderPipelineAdded) @@ -253,6 +255,8 @@ namespace UnitTest EXPECT_TRUE(feature->m_lastPipeline == pipeline1.get()); EXPECT_TRUE(feature->m_viewSetCount == 1); EXPECT_TRUE(feature->m_pipelineChangedCount == 0); + + testScene->Deactivate(); } @@ -286,6 +290,8 @@ namespace UnitTest testScene->DisableFeatureProcessor(); EXPECT_TRUE(testScene->GetFeatureProcessor() == nullptr); EXPECT_TRUE(testScene->GetFeatureProcessor() == nullptr); + + testScene->Deactivate(); } TEST_F(SceneTests, GetFeatureProcessorByNameId_UsingStringForFeatureProcessorId_ReturnsValidFeatureProcessor) @@ -297,6 +303,8 @@ namespace UnitTest testScene->Activate(); EXPECT_TRUE(testScene->GetFeatureProcessor(FeatureProcessorId{ "TestFeatureProcessor1" }) != nullptr); + + testScene->Deactivate(); } // @@ -315,6 +323,8 @@ namespace UnitTest FeatureProcessor* secondImplementation = testScene->EnableFeatureProcessor(FeatureProcessorId{ TestFeatureProcessorImplementation2::RTTI_TypeName() }); EXPECT_TRUE(secondImplementation != nullptr); + + testScene->Deactivate(); } TEST_F(SceneTests, EnableDisableFeatureProcessorByType_MultipleImplmentationsOfTheSameInterface_ReturnsValidFeatureProcessor) @@ -330,6 +340,8 @@ namespace UnitTest FeatureProcessor* secondImplementation = testScene->EnableFeatureProcessor(); EXPECT_TRUE(secondImplementation != nullptr); + + testScene->Deactivate(); } TEST_F(SceneTests, GetFeatureProcessorByNameId_MultipleImplmentationsOfTheSameInterface_ReturnsValidFeatureProcessor) @@ -347,6 +359,8 @@ namespace UnitTest FeatureProcessor* secondImplementation = testScene->EnableFeatureProcessor(); featureProcessor = testScene->GetFeatureProcessor(FeatureProcessorId{ TestFeatureProcessorImplementation2::RTTI_TypeName() }); EXPECT_TRUE(secondImplementation == featureProcessor); + + testScene->Deactivate(); } TEST_F(SceneTests, GetFeatureProcessorByInterface_MultipleImplmentationsOfTheSameInterface_ReturnsValidFeatureProcessor) @@ -366,6 +380,8 @@ namespace UnitTest featureProcessorInterface = testScene->GetFeatureProcessor(); EXPECT_TRUE(secondImplementation == featureProcessorInterface); + + testScene->Deactivate(); } // @@ -384,6 +400,8 @@ namespace UnitTest EXPECT_TRUE(featureProcessor == nullptr); EXPECT_TRUE(testScene->GetFeatureProcessor() == nullptr); EXPECT_TRUE(testScene->GetFeatureProcessor() == nullptr); + + testScene->Deactivate(); } TEST_F(SceneTests, DisableFeatureProcessor_ByInterface_FailsToDisable) @@ -396,6 +414,8 @@ namespace UnitTest testScene->DisableFeatureProcessor(FeatureProcessorId{ TestFeatureProcessorInterface::RTTI_TypeName() }); EXPECT_TRUE(testScene->GetFeatureProcessor() != nullptr); EXPECT_TRUE(testScene->GetFeatureProcessor() != nullptr); + + testScene->Deactivate(); } TEST_F(SceneTests, EnableFeatureProcessor_MultipleImplmentationsOfTheSameInterface_FailsToEnable) @@ -416,6 +436,8 @@ namespace UnitTest // If another implementation that uses the same interface exists, that will be the feature processor that is returned EXPECT_TRUE(secondImplementation == firstImplementation); + + testScene->Deactivate(); } } // namespace UnitTest diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp index 9fe3c8093c..31a291c845 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp @@ -17,7 +17,7 @@ #include #include #include -#include "Inspector/ui_InspectorWidget.h" +#include namespace AtomToolsFramework { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.ico b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.ico deleted file mode 100644 index 0ab3150890..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41c2e2ba186961c89b25789cdd3f59655367f5a6529c1cf6bb49cef5b7252406 -size 103713 diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.ico b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.ico new file mode 100644 index 0000000000..ce7d79def7 --- /dev/null +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40dd06da9f9dcfef7536255fb53278c9dc4e7ee175d0395f655df6714912ce02 +size 109153 diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.rc b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.rc similarity index 100% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditor.rc rename to Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor.rc diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake index e5882dcd3d..7c6923b5f8 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake @@ -13,4 +13,5 @@ set(FILES MaterialEditor_Traits_Platform.h MaterialEditor_Traits_Windows.h MaterialEditor_Windows.cpp + MaterialEditor.rc ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index ece05f04c1..e1bfaa3872 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -357,6 +357,11 @@ namespace MaterialEditor return; } + if (preset->m_modelAsset.GetId() == m_modelAssetId) + { + return; + } + AZ::Render::MeshComponentRequestBus::Event(m_modelEntity->GetId(), &AZ::Render::MeshComponentRequestBus::Events::SetModelAsset, preset->m_modelAsset); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h index 9eaa2db5c7..bf39671343 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h @@ -14,7 +14,7 @@ #include -#include +#include #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.h index 3dd1147ce0..f516ecf28a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.h @@ -18,7 +18,7 @@ #include #endif -#include +#include class QImage; class QListWidgetItem; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp index 0b3c5e1cfc..dad4a34b1e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp @@ -1,30 +1,29 @@ /* -* 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. -* -*/ + * 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 #include -#include -#include -#include - -#include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include +#include #include #include #include -#include AZ_POP_DISABLE_WARNING namespace MaterialEditor @@ -35,24 +34,25 @@ namespace MaterialEditor AzQtComponents::ToolBar::addMainToolBarStyle(this); // Add toggle grid button - QAction* toggleGrid = addAction(QIcon(":/Icons/grid.svg"), "Toggle Grid"); - toggleGrid->setCheckable(true); - connect(toggleGrid, &QAction::triggered, [this, toggleGrid]() { - MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, toggleGrid->isChecked()); - }); + m_toggleGrid = addAction(QIcon(":/Icons/grid.svg"), "Toggle Grid"); + m_toggleGrid->setCheckable(true); + connect(m_toggleGrid, &QAction::triggered, [this]() { + MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_toggleGrid->isChecked()); + }); bool enableGrid = false; MaterialViewportRequestBus::BroadcastResult(enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled); - toggleGrid->setChecked(enableGrid); + m_toggleGrid->setChecked(enableGrid); // Add toggle shadow catcher button - QAction* toggleShadowCatcher = addAction(QIcon(":/Icons/shadow.svg"), "Toggle Shadow Catcher"); - toggleShadowCatcher->setCheckable(true); - connect(toggleShadowCatcher, &QAction::triggered, [this, toggleShadowCatcher]() { - MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, toggleShadowCatcher->isChecked()); - }); + m_toggleShadowCatcher = addAction(QIcon(":/Icons/shadow.svg"), "Toggle Shadow Catcher"); + m_toggleShadowCatcher->setCheckable(true); + connect(m_toggleShadowCatcher, &QAction::triggered, [this]() { + MaterialViewportRequestBus::Broadcast( + &MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_toggleShadowCatcher->isChecked()); + }); bool enableShadowCatcher = false; MaterialViewportRequestBus::BroadcastResult(enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled); - toggleShadowCatcher->setChecked(enableShadowCatcher); + m_toggleShadowCatcher->setChecked(enableShadowCatcher); // Add mapping selection button //[GFX TODO][ATOM-3992] @@ -60,13 +60,13 @@ namespace MaterialEditor QMenu* toneMappingMenu = new QMenu(toneMappingButton); toneMappingMenu->addAction("None", [this]() { MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "None"); - }); + }); toneMappingMenu->addAction("Gamma2.2", [this]() { MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "Gamma2.2"); - }); + }); toneMappingMenu->addAction("ACES", [this]() { MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "ACES"); - }); + }); toneMappingButton->setMenu(toneMappingMenu); toneMappingButton->setText("Tone Mapping"); toneMappingButton->setIcon(QIcon(":/Icons/toneMapping.svg")); @@ -85,7 +85,25 @@ namespace MaterialEditor auto lightingPresetComboBox = new LightingPresetComboBox(this); lightingPresetComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); addWidget(lightingPresetComboBox); + + MaterialViewportNotificationBus::Handler::BusConnect(); } + + MaterialEditorToolBar::~MaterialEditorToolBar() + { + MaterialViewportNotificationBus::Handler::BusDisconnect(); + } + + void MaterialEditorToolBar::OnGridEnabledChanged(bool enable) + { + m_toggleGrid->setChecked(enable); + } + + void MaterialEditorToolBar::OnShadowCatcherEnabledChanged(bool enable) + { + m_toggleShadowCatcher->setChecked(enable); + } + } // namespace MaterialEditor #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h index 63dd5ae84d..147608bc23 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h @@ -13,16 +13,28 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include +#include #endif namespace MaterialEditor { class MaterialEditorToolBar : public QToolBar + , public MaterialViewportNotificationBus::Handler { Q_OBJECT public: MaterialEditorToolBar(QWidget* parent = 0); + ~MaterialEditorToolBar(); + + private: + // MaterialViewportNotificationBus::Handler overrides... + void OnShadowCatcherEnabledChanged([[maybe_unused]] bool enable) override; + void OnGridEnabledChanged([[maybe_unused]] bool enable) override; + + QAction* m_toggleGrid = {}; + QAction* m_toggleShadowCatcher = {}; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp index ee936d7476..8efed36197 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp @@ -134,7 +134,7 @@ namespace MaterialEditor if (m_modelPreset) { auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), nullptr, groupWidget); + m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget); groupWidget->layout()->addWidget(inspectorWidget); } @@ -221,7 +221,7 @@ namespace MaterialEditor if (m_lightingPreset) { auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), nullptr, groupWidget); + m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), this, groupWidget); groupWidget->layout()->addWidget(inspectorWidget); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp index eb80638a4d..92d76c4373 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.ico b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.ico new file mode 100644 index 0000000000..05273e213f --- /dev/null +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:090db466524f15068d1bc30466e51a7123f403798176a273e8060abf72d366d8 +size 109469 diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.rc b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.rc similarity index 100% rename from Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.rc rename to Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole.rc diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake index bf1e8d6fec..aa202bad51 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake @@ -13,4 +13,5 @@ set(FILES ShaderManagementConsole_Traits_Platform.h ShaderManagementConsole_Traits_Windows.h ShaderManagementConsole_Windows.cpp + ShaderManagementConsole.rc ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.ico b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.ico deleted file mode 100644 index 0ab3150890..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsole.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41c2e2ba186961c89b25789cdd3f59655367f5a6529c1cf6bb49cef5b7252406 -size 103713 diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/main.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/main.cpp index 5692522e58..795b835027 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/main.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/main.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCullingDebug.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCullingDebug.inl index a6f1a34ad2..1b1adb0f3c 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCullingDebug.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCullingDebug.inl @@ -30,8 +30,8 @@ namespace AZ { using namespace RPI; - CullingSystem* cullSys = scene->GetCullingSystem(); - CullingDebugContext& debugCtx = cullSys->GetDebugContext(); + CullingScene* cullScene = scene->GetCullingScene(); + CullingDebugContext& debugCtx = cullScene->GetDebugContext(); ImGui::SetNextWindowSize(ImVec2(900.f, 700.f), ImGuiCond_Once); if (ImGui::Begin("Culling Debug", &draw, ImGuiWindowFlags_None)) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl index 15c6990dcc..b5cf2e8f6b 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl @@ -454,7 +454,6 @@ namespace ImGui { return m_rootNode->AddChild(name, numInputs, numOutputs); } - return nullptr; } //!Resolve all the overlapping nodes. diff --git a/Gems/AtomLyIntegration/AtomImGuiTools/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomImGuiTools/Code/CMakeLists.txt index d653d54f6b..82db2c7271 100644 --- a/Gems/AtomLyIntegration/AtomImGuiTools/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomImGuiTools/Code/CMakeLists.txt @@ -17,8 +17,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore @@ -34,8 +32,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE Gem::AtomImGuiTools.Static diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h index 76ac5f6123..f4cb319c2f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -77,6 +77,72 @@ namespace AZ //! Sets the photometric unit to the one provided and converts the intensity to the photometric unit so actual light intensity remains constant. virtual void ConvertToIntensityMode(PhotometricUnit intensityMode) = 0; + + // Shutters + + //! Returns true if shutters are enabled. + virtual bool GetEnableShutters() const = 0; + + //! Sets if shutters should be enabled. + virtual void SetEnableShutters(bool enabled) = 0; + + //! Returns the inner angle of the shutters in degrees + virtual float GetInnerShutterAngle() const = 0; + + //! Sets the inner angle of the shutters in degrees + virtual void SetInnerShutterAngle(float degrees) = 0; + + //! Returns the outer angle of the shutters in degrees + virtual float GetOuterShutterAngle() const = 0; + + //! Sets the outer angle of the shutters in degrees + virtual void SetOuterShutterAngle(float degrees) = 0; + + // Shadows + + //! Returns true if shadows are enabled. + virtual bool GetEnableShadow() const = 0; + + //! Sets if shadows should be enabled. + virtual void SetEnableShadow(bool enabled) = 0; + + //! Returns the maximum width and height of shadowmap. + virtual ShadowmapSize GetShadowmapMaxSize() const = 0; + + //! Sets the maximum width and height of shadowmap. + virtual void SetShadowmapMaxSize(ShadowmapSize size) = 0; + + //! Returns the filter method of shadows. + virtual ShadowFilterMethod GetShadowFilterMethod() const = 0; + + //! Sets the filter method of shadows. + virtual void SetShadowFilterMethod(ShadowFilterMethod method) = 0; + + //! Gets the width of softening boundary between shadowed area and lit area in degrees. + virtual float GetSofteningBoundaryWidthAngle() const = 0; + + //! Sets the width of softening boundary between shadowed area and lit area in degrees. + //! 0 disables softening. + virtual void SetSofteningBoundaryWidthAngle(float degrees) = 0; + + //! Gets the sample count to predict boundary of shadow. + virtual uint32_t GetPredictionSampleCount() const = 0; + + //! Sets the sample count to predict boundary of shadow. Maximum 16, and should also be + //! less than the filtering sample count. + virtual void SetPredictionSampleCount(uint32_t count) = 0; + + //! Gets the sample count for filtering of the shadow boundary. + virtual uint32_t GetFilteringSampleCount() const = 0; + + //! Sets the sample count for filtering of the shadow boundary. Maximum 64. + virtual void SetFilteringSampleCount(uint32_t count) = 0; + + //! Gets the type of Pcf (percentage-closer filtering) to use. + virtual PcfMethod GetPcfMethod() const = 0; + + //! Sets the type of Pcf (percentage-closer filtering) to use. + virtual void SetPcfMethod(PcfMethod method) = 0; }; //! The EBus for requests to for setting and getting light component properties. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 66a30285c2..857e795257 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -14,9 +14,9 @@ #include #include +#include #include #include -#include namespace AZ { @@ -28,6 +28,20 @@ namespace AZ AZ_RTTI(AZ::Render::AreaLightComponentConfig, "{11C08FED-7F94-4926-8517-46D08E4DD837}", ComponentConfig); static void Reflect(AZ::ReflectContext* context); + enum class LightType : uint8_t + { + Unknown, + Sphere, + SpotDisk, + Capsule, + Quad, + Polygon, + SimplePoint, + SimpleSpot, + + LightTypeCount, + }; + static constexpr float CutoffIntensity = 0.1f; AZ::Color m_color = AZ::Color::CreateOne(); @@ -39,17 +53,50 @@ namespace AZ bool m_useFastApproximation = false; AZ::Crc32 m_shapeType; + bool m_enableShutters = false; + LightType m_lightType = LightType::Unknown; + float m_innerShutterAngleDegrees = 35.0f; + float m_outerShutterAngleDegrees = 45.0f; + + // Shadows (only used for supported shapes) + bool m_enableShadow = false; + ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256; + ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; + PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; + float m_boundaryWidthInDegrees = 0.25f; + uint16_t m_predictionSampleCount = 4; + uint16_t m_filteringSampleCount = 12; + // The following functions provide information to an EditContext... + AZStd::vector> GetValidPhotometricUnits() const; + + bool RequiresShapeComponent() const; + //! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic bool IsAttenuationRadiusModeAutomatic() const; - //! Returns true if the shape type is a 2D surface - bool Is2DSurface() const; + //! Returns true if the shape type can emit light from both sides + bool SupportsBothDirections() const; //! Returns true if the light type supports a faster and less accurate approximation for the lighting algorithm. bool SupportsFastApproximation() const; + //! Returns true if the light type supports restricting the light beam to an angle + bool SupportsShutters() const; + + //! Returns true if the light type supports shutters, but they must be turned on. + bool ShuttersMustBeEnabled() const; + + //! Returns true if shutters are turned off + bool ShuttersDisabled() const; + + //! Returns true if the light type supports shadows. + bool SupportsShadows() const; + + //! Returns true if shadows are turned on + bool ShadowsDisabled() const; + //! Returns characters for a suffix for the light type including a space. " lm" for lumens for example. const char* GetIntensitySuffix() const; @@ -65,6 +112,15 @@ namespace AZ //! Returns the maximum intensity value for UI depending on the m_intensityMode, but users may still type in a greater value depending on GetIntensityMin(). float GetIntensitySoftMax() const; + //! Returns true if shadow filtering is disabled. + bool IsShadowFilteringDisabled() const; + + //! Returns true if pcf shadows are disabled. + bool IsShadowPcfDisabled() const; + + //! Returns true if pcf boundary search is disabled. + bool IsPcfBoundarySearchDisabled() const; + }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/CoreLightsConstants.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/CoreLightsConstants.h index 88ddebbbcd..7db19ec8b1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/CoreLightsConstants.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/CoreLightsConstants.h @@ -22,10 +22,6 @@ namespace AZ { static constexpr const char* const AreaLightComponentTypeId = "{744B3961-6242-4461-983F-2817D9D29C30}"; static constexpr const char* const EditorAreaLightComponentTypeId = "{8B605C0C-9027-4E0B-BA8C-19E396F8F262}"; - static constexpr const char* const PointLightComponentTypeId = "{0A0E44AB-F583-481F-8AE8-68C4B1F9CD05}"; - static constexpr const char* const EditorPointLightComponentTypeId = "{C4D354BE-5247-41FD-9A8D-550C6772EE5B}"; - static constexpr const char* const SpotLightComponentTypeId = "{441DF0EC-6B70-451E-AEBE-6452A17BB852}"; - static constexpr const char* const EditorSpotLightComponentTypeId = "{9A32D37B-C5D2-43A7-B574-E2EA1CDC7D64}"; static constexpr const char* const DirectionalLightComponentTypeId = "{13054592-2753-46C2-B19E-59670D4CE03D}"; static constexpr const char* const EditorDirectionalLightComponentTypeId = "{45B97527-6E72-411B-BC23-00068CF01580}"; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h index c34c5dd62e..7ce844ca0b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h @@ -182,6 +182,13 @@ namespace AZ //! This sets the sample count for filtering of the shadow boundary. //! @param count Sample Count for filtering (up to 64) virtual void SetFilteringSampleCount(uint32_t count) = 0; + + //! This gets the type of Pcf (percentage-closer filtering) to use. + virtual PcfMethod GetPcfMethod() const = 0; + + //! This sets the type of Pcf (percentage-closer filtering) to use. + //! @param method The Pcf method to use. + virtual void SetPcfMethod(PcfMethod method) = 0; }; using DirectionalLightRequestBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h index f1f794bed7..7de2857541 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h @@ -117,11 +117,14 @@ namespace AZ //! It is used only when the pixel is predicted as on the boundary. uint16_t m_filteringSampleCount = 32; + PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; + bool IsSplitManual() const; bool IsSplitAutomatic() const; bool IsCascadeCorrectionDisabled() const; bool IsShadowFilteringDisabled() const; bool IsShadowPcfDisabled() const; + bool IsPcfBoundarySearchDisabled() const; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightBus.h deleted file mode 100644 index cdd8bb275d..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightBus.h +++ /dev/null @@ -1,130 +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 -#include - -#include - -namespace AZ -{ - namespace Render - { - class PointLightRequests - : public ComponentBus - { - public: - AZ_RTTI(PointLightRequests, "{359BE514-DBEB-4D6A-B283-F8C5E83CD477}"); - - /// Overrides the default AZ::EBusTraits handler policy to allow one listener only. - static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; - - virtual ~PointLightRequests() {} - - /// Gets a point light's color. This value is indepedent from its intensity. - virtual const Color& GetColor() const = 0; - - /// Sets a point light's color. This value is indepedent from its intensity. - virtual void SetColor(const Color& color) = 0; - - /// Gets a point light's intensity. This value is indepedent from its color. - virtual float GetIntensity() const = 0; - - //! Gets a point light's photometric type. - virtual PhotometricUnit GetIntensityMode() const = 0; - - /// Sets a point light's intensity. This value is indepedent from its color. - virtual void SetIntensity(float intensity) = 0; - - //! Sets a point light's intensity and intensity mode. This value is indepedent from its color. - virtual void SetIntensity(float intensity, PhotometricUnit intensityMode) = 0; - - /// Gets the distance at which the point light will no longer affect lighting. - virtual float GetAttenuationRadius() const = 0; - - /// Set the distance and which a point light will no longer affect lighitng. Setting this forces the RadiusCalculation to Explicit mode. - virtual void SetAttenuationRadius(float radius) = 0; - - /// Gets the size in meters of the sphere representing the light bulb. - virtual float GetBulbRadius() const = 0; - - /// Sets the size in meters of the sphere representing the light bulb in meters. - virtual void SetBulbRadius(float bulbSize) = 0; - - /* - * If this is set to Automatic, the radius will immediately be recalculated based on the intensity. - * If this is set to Explicit, the radius value will be unchanged from its previous value. - */ - virtual void SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) = 0; - - /// Gets the flag whether attenuation radius calculation is automatic or not. - virtual bool GetAttenuationRadiusIsAutomatic() const = 0; - - /// Sets the flag whether attenuation radius calculation is automatic or not. - virtual void SetAttenuationRadiusIsAutomatic(bool flag) - { - SetAttenuationRadiusMode(flag ? LightAttenuationRadiusMode::Automatic : LightAttenuationRadiusMode::Explicit); - } - - //! Sets the photometric unit to the one provided and converts the intensity to the photometric unit so actual light intensity remains constant. - virtual void ConvertToIntensityMode(PhotometricUnit intensityMode) = 0; - }; - - /// The EBus for requests to for setting and getting light component properties. - typedef AZ::EBus PointLightRequestBus; - - class PointLightNotifications - : public ComponentBus - { - public: - AZ_RTTI(PointLightNotifications, "{7363728D-E3EE-4AC8-AAA7-C299782763F0}"); - - virtual ~PointLightNotifications() {} - - /** - * Signals that the color of the light changed. - * @param color A reference to the new color of the light. - */ - virtual void OnColorChanged(const Color& /*color*/) { } - - /** - * Signals that the intensity of the light changed. - * @param color A reference to the new intensity of the light. - */ - virtual void OnIntensityChanged(float /*intensity*/) { } - - /** - * Signals that the color or intensity of the light changed. This is useful when both the color and intensity are need in the same call. - * @param color A reference to the new color of the light. - * @param color A reference to the new intensity of the light. - */ - virtual void OnColorOrIntensityChanged(const Color& /*color*/, float /*intensity*/) { } - - /** - * Signals that the attenuation radius of the light changed. - * @param attenuationRadius The distance at which this light no longer affects lighting. - */ - virtual void OnAttenutationRadiusChanged(float /*attenuationRadius*/) { } - - /** - * Signals that the bulb size of the light changed. - * @param bulbRadius The size in meters of the sphere representing the light bulb in meters. - */ - virtual void OnBulbRadiusChanged(float /*bulbRadius*/) { } - - }; - - /// The EBus for light notification events. - typedef AZ::EBus PointLightNotificationBus; - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightComponentConfig.h deleted file mode 100644 index df8454ccc2..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightComponentConfig.h +++ /dev/null @@ -1,113 +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 -#include -#include - -namespace AZ -{ - namespace Render - { - struct PointLightComponentConfig final - : public ComponentConfig - { - AZ_RTTI(PointLightComponentConfig, "{B6FC35BA-D22F-4C20-BFFC-3FE7A48858FA}", ComponentConfig); - static void Reflect(AZ::ReflectContext* context); - - static constexpr float DefaultIntensity = 800.0f; // 800 lumes is roughly equivalent to a 60 watt incandescent bulb - static constexpr float DefaultBulbRadius = 0.05f; // 5cm - - AZ::Color m_color = AZ::Color::CreateOne(); - PhotometricUnit m_intensityMode = PhotometricUnit::Lumen; - float m_intensity = DefaultIntensity; - float m_attenuationRadius = 0.0f; - float m_bulbRadius = DefaultBulbRadius; - LightAttenuationRadiusMode m_attenuationRadiusMode = LightAttenuationRadiusMode::Automatic; - - // Not serialized, but used to keep scaled and unscaled properties in sync. - float m_scale = 1.0f; - - // These values are used to deal adjusting the brightness and bulb radius based on the transform component's scale - // so that point lights scale concistently with meshes. Not serialized. - float m_unscaledIntensity = DefaultIntensity; - float m_unscaledBulbRadius = DefaultBulbRadius; - - //! Updates scale and adjusts the values of intensity and bulb radius based on the new scale and the unscaled values. - void UpdateScale(float newScale) - { - m_scale = newScale; - - m_intensity = m_unscaledIntensity; - - // Lumens & Candela aren't based on surface area, so scale them. - if (!IsAreaBasedIntensityMode()) - { - // Light surface area and brightness increases at scale^2 because of equation of sphere surface area. - m_intensity *= m_scale * m_scale; - } - - m_bulbRadius = m_unscaledBulbRadius * m_scale; - } - - //! Updates the unscaled intensity based on the current scaled value. - void UpdateUnscaledIntensity() - { - m_unscaledIntensity = m_intensity; - - // Lumens & Candela aren't based on surface area, so scale them. - if (!IsAreaBasedIntensityMode()) - { - // Light surface area and brightness increases at scale^2 because of equation of sphere surface area. - m_unscaledIntensity /= m_scale * m_scale; - } - } - - //! Updates the unscaled bulb radius based on the current scaled value. - void UpdateUnscaledBulbRadius() - { - m_unscaledBulbRadius = m_bulbRadius / m_scale; - } - - // Returns true if the intensity mode is an area based light unit (not lumens or candela) - bool IsAreaBasedIntensityMode() - { - return m_intensityMode != PhotometricUnit::Lumen && m_intensityMode != PhotometricUnit::Candela; - } - - // Returns the surface area of the light bulb. 4.0 * pi * m_bulbRadius^2 - float GetArea() - { - return 4.0f * Constants::Pi * m_bulbRadius * m_bulbRadius; - } - - // The following functions provide information to an EditContext... - - //! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic - bool IsAttenuationRadiusModeAutomatic() const - { - return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic; - } - - //! Returns characters for a suffix for the light type including a space. " lm" for lumens for example. - const char* GetIntensitySuffix() const - { - return PhotometricValue::GetTypeSuffix(m_intensityMode); - } - - }; - } -} diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightBus.h deleted file mode 100644 index 934059d76b..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightBus.h +++ /dev/null @@ -1,172 +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 -#include - -namespace AZ -{ - namespace Render - { - class SpotLightRequests - : public ComponentBus - { - public: - //! Overrides the default AZ::EBusTraits handler policy to allow one listener only. - static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; - - virtual ~SpotLightRequests() = default; - - //! Gets a spot light's color. This value is independent from its intensity. - virtual const Color& GetColor() const = 0; - - //! Sets a spot light's color. This value is independent from its intensity. - virtual void SetColor(const Color& color) = 0; - - //! Gets a spot light's intensity. This value is independent from its color. - virtual float GetIntensity() const = 0; - - //! Sets a spot light's intensity. This value is independent from its color. - virtual void SetIntensity(float intensity) = 0; - - //! Gets a spot light's bulb radius in meters. - virtual float GetBulbRadius() const = 0; - - //! Sets a spot light's bulb radius in meters. - virtual void SetBulbRadius(float bulbRadius) = 0; - - //! @return Returns inner cone angle of the spot light in degrees. - virtual float GetInnerConeAngleInDegrees() const = 0; - //! @brief Sets inner cone angle of the spot light in degrees. - virtual void SetInnerConeAngleInDegrees(float degrees) = 0; - - //! @return Returns outer cone angle of the spot light in degrees. - virtual float GetOuterConeAngleInDegrees() const = 0; - //! @brief Sets outer cone angle of the spot light in degrees. - virtual void SetOuterConeAngleInDegrees(float degrees) = 0; - - //! @return Returns penumbra bias for the falloff curve of the spot light. - virtual float GetPenumbraBias() const = 0; - //! @brief Sets penumbra bias for the falloff curve of the spot light. - virtual void SetPenumbraBias(float penumbraBias) = 0; - - //! @return Returns radius attenuation of the spot light. - virtual float GetAttenuationRadius() const = 0; - //! @return Sets radius attenuation of the spot light. - virtual void SetAttenuationRadius(float radius) = 0; - - //! @return Returns radius attenuation mode (Auto or Explicit). - virtual LightAttenuationRadiusMode GetAttenuationRadiusMode() const = 0; - //! If this is set to Automatic, the radius will immediately be recalculated based on the intensity. - //! If this is set to Explicit, the radius value will be unchanged from its previous value. - virtual void SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) = 0; - - //! @return the flag whether attenuation radius calculation is automatic or not. - virtual bool GetAttenuationRadiusIsAutomatic() const - { - return (GetAttenuationRadiusMode() == LightAttenuationRadiusMode::Automatic); - } - //! This sets flag whether attenuation radius calculation is automatic or not. - //! @param flag flag whether attenuation radius calculation is automatic or not. - virtual void SetAttenuationRadiusIsAutomatic(bool flag) - { - SetAttenuationRadiusMode(flag ? LightAttenuationRadiusMode::Automatic : LightAttenuationRadiusMode::Explicit); - } - - //! @return the flag indicates this light have shadow or not. - virtual bool GetEnableShadow() const = 0; - //! This specify this spot light uses shadow or not. - //! @param enabled true if shadow is used, false otherwise. - virtual void SetEnableShadow(bool enabled) = 0; - - //! @return the size of shadowmap (width and height). - virtual ShadowmapSize GetShadowmapSize() const = 0; - - //! This specifies the size of shadowmap to size x size. - virtual void SetShadowmapSize(ShadowmapSize size) = 0; - - //! This gets the filter method of shadows. - //! @return filter method - virtual ShadowFilterMethod GetShadowFilterMethod() const = 0; - - //! This specifies filter method of shadows. - //! @param method Filter method. - virtual void SetShadowFilterMethod(ShadowFilterMethod method) = 0; - - //! This gets the width of boundary between shadowed area and lit area. - //! The width is given by the angle, and the units are in degrees. - //! @return Boundary width. The degree of the shadowed region is gradually changed on the boundary. - virtual float GetSofteningBoundaryWidthAngle() const = 0; - - //! This specifies the width of boundary between shadowed area and lit area. - //! @param width Boundary width. The degree of shadowed is gradually changed on the boundary. - //! If width == 0, softening edge is disabled. Units are in degrees. - virtual void SetSofteningBoundaryWidthAngle(float degrees) = 0; - - //! This gets the sample count to predict boundary of shadow. - //! @return Sample Count for prediction of whether the pixel is on the boundary (up to 16) - virtual uint32_t GetPredictionSampleCount() const = 0; - - //! This sets the sample count to predict boundary of shadow. - //! @param count Sample count for prediction of whether the pixel is on the boundary (up to 16) - //! This value should be less than or equal to m_filteringSampleCount. - virtual void SetPredictionSampleCount(uint32_t count) = 0; - - //! This gets the sample count for filtering of the shadow boundary. - //! @return Sample Count for filtering (up to 64) - virtual uint32_t GetFilteringSampleCount() const = 0; - - //! This sets the sample count for filtering of the shadow boundary. - //! @param count Sample Count for filtering (up to 64) - virtual void SetFilteringSampleCount(uint32_t count) = 0; - - //! This gets the type of Pcf (percentage-closer filtering) to use. - virtual PcfMethod GetPcfMethod() const = 0; - - //! This sets the type of Pcf (percentage-closer filtering) to use. - //! @param method The Pcf method to use. - virtual void SetPcfMethod(PcfMethod method) = 0; - }; - - /// The EBus for requests to for setting and getting spot light component properties. - typedef AZ::EBus SpotLightRequestBus; - - class SpotLightNotifications - : public ComponentBus - { - public: - virtual ~SpotLightNotifications() = default; - - //! @brief Signals that the intensity of the light changed. - virtual void OnIntensityChanged(float intensity) { AZ_UNUSED(intensity); } - - //! @brief Signals that the color of the light changed. - virtual void OnColorChanged(const Color& color) { AZ_UNUSED(color); } - - //! @brief Signals that the cone angles of the spot light have changed. - virtual void OnConeAnglesChanged(float innerConeAngleDegrees, float outerConeAngleDegrees) { AZ_UNUSED(innerConeAngleDegrees); AZ_UNUSED(outerConeAngleDegrees); } - - //! @brief Signals that the attenuation radius has changed. - virtual void OnAttenuationRadiusChanged(float attenuationRadius) { AZ_UNUSED(attenuationRadius); } - - //! @brief Signals that the penumbra bias has changed. - virtual void OnPenumbraBiasChanged(float penumbraBias) { AZ_UNUSED(penumbraBias); } - }; - - //! The EBus for spot light notification events. - typedef AZ::EBus SpotLightNotificationBus; - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightComponentConfig.h deleted file mode 100644 index 3cde1f23a0..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightComponentConfig.h +++ /dev/null @@ -1,62 +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 -#include -#include - -namespace AZ -{ - namespace Render - { - struct SpotLightComponentConfig final - : ComponentConfig - { - AZ_RTTI(SpotLightComponentConfig, "{20C882C8-615E-4272-93A8-BE9102E6EFED}", ComponentConfig); - static void Reflect(AZ::ReflectContext* context); - - AZ::Color m_color = AZ::Color::CreateOne(); - float m_intensity = 100.0f; - PhotometricUnit m_intensityMode = PhotometricUnit::Lumen; - float m_bulbRadius = 0.075; - float m_innerConeDegrees = 45.0f; - float m_outerConeDegrees = 55.0f; - float m_attenuationRadius = 20.0f; - float m_penumbraBias = 0.0f; - LightAttenuationRadiusMode m_attenuationRadiusMode = LightAttenuationRadiusMode::Automatic; - bool m_enabledShadow = false; - ShadowmapSize m_shadowmapSize = MaxShadowmapImageSize; - ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; - PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; - float m_boundaryWidthInDegrees = 0.25f; - uint16_t m_predictionSampleCount = 4; - uint16_t m_filteringSampleCount = 32; - - // The following functions provide information to an EditContext... - - //! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic - bool IsAttenuationRadiusModeAutomatic() const; - - //! Returns characters for a suffix for the light type including a space. " lm" for lumens for example. - const char* GetIntensitySuffix() const; - - float GetConeDegrees() const; - bool IsShadowFilteringDisabled() const; - bool IsShadowPcfDisabled() const; - bool IsPcfBoundarySearchDisabled() const; - }; - } -} diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 4312418f19..2afa6514cd 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -21,7 +21,8 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(3) + ->Version(5) // ATOM-14637 + ->Field("LightType", &AreaLightComponentConfig::m_lightType) ->Field("Color", &AreaLightComponentConfig::m_color) ->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode) ->Field("Intensity", &AreaLightComponentConfig::m_intensity) @@ -29,25 +30,89 @@ namespace AZ ->Field("AttenuationRadius", &AreaLightComponentConfig::m_attenuationRadius) ->Field("LightEmitsBothDirections", &AreaLightComponentConfig::m_lightEmitsBothDirections) ->Field("UseFastApproximation", &AreaLightComponentConfig::m_useFastApproximation) + // Shutters + ->Field("EnableShutters", &AreaLightComponentConfig::m_enableShutters) + ->Field("InnerShutterAngleDegrees", &AreaLightComponentConfig::m_innerShutterAngleDegrees) + ->Field("OuterShutterAngleDegrees", &AreaLightComponentConfig::m_outerShutterAngleDegrees) + // Shadows + ->Field("Enable Shadow", &AreaLightComponentConfig::m_enableShadow) + ->Field("Shadowmap Max Size", &AreaLightComponentConfig::m_shadowmapMaxSize) + ->Field("Shadow Filter Method", &AreaLightComponentConfig::m_shadowFilterMethod) + ->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees) + ->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount) + ->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount) + ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod); ; } } + + AZStd::vector> AreaLightComponentConfig::GetValidPhotometricUnits() const + { + AZStd::vector> enumValues = + { + // Candela & lumen always supported. + Edit::EnumConstant(PhotometricUnit::Candela, "Candela"), + Edit::EnumConstant(PhotometricUnit::Lumen, "Lumen"), + }; + + if (RequiresShapeComponent()) + { + // Lights with surface area also support nits and ev100. + enumValues.push_back(Edit::EnumConstant(PhotometricUnit::Nit, "Nit")); + enumValues.push_back(Edit::EnumConstant(PhotometricUnit::Ev100Luminance, "Ev100")); + } + return enumValues; + } + + bool AreaLightComponentConfig::RequiresShapeComponent() const + { + return m_lightType == LightType::Sphere + || m_lightType == LightType::SpotDisk + || m_lightType == LightType::Capsule + || m_lightType == LightType::Quad + || m_lightType == LightType::Polygon; + } bool AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic() const { return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic; } - bool AreaLightComponentConfig::Is2DSurface() const + bool AreaLightComponentConfig::SupportsBothDirections() const { - return m_shapeType == AZ_CRC_CE("DiskShape") - || m_shapeType == AZ_CRC_CE("QuadShape") - || m_shapeType == AZ_CRC_CE("PolygonPrism"); + return m_lightType == LightType::Quad + || m_lightType == LightType::Polygon; } bool AreaLightComponentConfig::SupportsFastApproximation() const { - return m_shapeType == AZ_CRC_CE("QuadShape"); + return m_lightType == LightType::Quad; + } + + bool AreaLightComponentConfig::SupportsShutters() const + { + return m_lightType == LightType::SimpleSpot + || m_lightType == LightType::SpotDisk; + } + + bool AreaLightComponentConfig::ShuttersMustBeEnabled() const + { + return m_lightType == LightType::SpotDisk; + } + + bool AreaLightComponentConfig::ShuttersDisabled() const + { + return m_lightType == LightType::SpotDisk && !m_enableShutters; + } + + bool AreaLightComponentConfig::SupportsShadows() const + { + return m_shapeType == AZ_CRC_CE("DiskShape"); + } + + bool AreaLightComponentConfig::ShadowsDisabled() const + { + return !m_enableShadow; } const char* AreaLightComponentConfig::GetIntensitySuffix() const @@ -109,6 +174,26 @@ namespace AZ } return 0.0f; } + + bool AreaLightComponentConfig::IsShadowFilteringDisabled() const + { + return (m_shadowFilterMethod == ShadowFilterMethod::None); + } + bool AreaLightComponentConfig::IsShadowPcfDisabled() const + { + return !(m_shadowFilterMethod == ShadowFilterMethod::Pcf || + m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); + } + + bool AreaLightComponentConfig::IsPcfBoundarySearchDisabled() const + { + if (IsShadowPcfDisabled()) + { + return true; + } + + return m_pcfMethod != PcfMethod::BoundarySearch; + } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 51bfdd514e..1bbc2a411e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -31,297 +33,593 @@ #include #include -namespace AZ +namespace AZ::Render { - namespace Render + void AreaLightComponentController::Reflect(ReflectContext* context) { - void AreaLightComponentController::Reflect(ReflectContext* context) + AreaLightComponentConfig::Reflect(context); + + if (auto* serializeContext = azrtti_cast(context)) { - AreaLightComponentConfig::Reflect(context); + serializeContext->Class() + ->Version(1) + ->Field("Configuration", &AreaLightComponentController::m_configuration); + } - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(0) - ->Field("Configuration", &AreaLightComponentController::m_configuration); - } + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AreaLightRequestBus") + ->Event("GetAttenuationRadius", &AreaLightRequestBus::Events::GetAttenuationRadius) + ->Event("SetAttenuationRadius", &AreaLightRequestBus::Events::SetAttenuationRadius) + ->Event("SetAttenuationRadiusMode", &AreaLightRequestBus::Events::SetAttenuationRadiusMode) + ->Event("GetColor", &AreaLightRequestBus::Events::GetColor) + ->Event("SetColor", &AreaLightRequestBus::Events::SetColor) + ->Event("GetEmitsLightBothDirections", &AreaLightRequestBus::Events::GetLightEmitsBothDirections) + ->Event("SetEmitsLightBothDirections", &AreaLightRequestBus::Events::SetLightEmitsBothDirections) + ->Event("GetUseFastApproximation", &AreaLightRequestBus::Events::GetUseFastApproximation) + ->Event("SetUseFastApproximation", &AreaLightRequestBus::Events::SetUseFastApproximation) + ->Event("GetIntensity", &AreaLightRequestBus::Events::GetIntensity) + ->Event("SetIntensity", static_cast(&AreaLightRequestBus::Events::SetIntensity)) + ->Event("GetIntensityMode", &AreaLightRequestBus::Events::GetIntensityMode) + ->Event("ConvertToIntensityMode", &AreaLightRequestBus::Events::ConvertToIntensityMode) - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + ->Event("GetEnableShutters", &AreaLightRequestBus::Events::GetEnableShutters) + ->Event("SetEnableShutters", &AreaLightRequestBus::Events::SetEnableShutters) + ->Event("GetInnerShutterAngle", &AreaLightRequestBus::Events::GetInnerShutterAngle) + ->Event("SetInnerShutterAngle", &AreaLightRequestBus::Events::SetInnerShutterAngle) + ->Event("GetOuterShutterAngle", &AreaLightRequestBus::Events::GetOuterShutterAngle) + ->Event("SetOuterShutterAngle", &AreaLightRequestBus::Events::SetOuterShutterAngle) + + ->Event("GetEnableShadow", &AreaLightRequestBus::Events::GetEnableShadow) + ->Event("SetEnableShadow", &AreaLightRequestBus::Events::SetEnableShadow) + ->Event("GetShadowmapMaxSize", &AreaLightRequestBus::Events::GetShadowmapMaxSize) + ->Event("SetShadowmapMaxSize", &AreaLightRequestBus::Events::SetShadowmapMaxSize) + ->Event("GetShadowFilterMethod", &AreaLightRequestBus::Events::GetShadowFilterMethod) + ->Event("SetShadowFilterMethod", &AreaLightRequestBus::Events::SetShadowFilterMethod) + ->Event("GetSofteningBoundaryWidthAngle", &AreaLightRequestBus::Events::GetSofteningBoundaryWidthAngle) + ->Event("SetSofteningBoundaryWidthAngle", &AreaLightRequestBus::Events::SetSofteningBoundaryWidthAngle) + ->Event("GetPredictionSampleCount", &AreaLightRequestBus::Events::GetPredictionSampleCount) + ->Event("SetPredictionSampleCount", &AreaLightRequestBus::Events::SetPredictionSampleCount) + ->Event("GetFilteringSampleCount", &AreaLightRequestBus::Events::GetFilteringSampleCount) + ->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount) + ->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod) + ->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod) + + ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") + ->VirtualProperty("Color", "GetColor", "SetColor") + ->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections") + ->VirtualProperty("UseFastApproximation", "GetUseFastApproximation", "SetUseFastApproximation") + ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") + + ->VirtualProperty("ShuttersEnabled", "GetEnableShutters", "SetEnableShutters") + ->VirtualProperty("InnerShutterAngle", "GetInnerShutterAngle", "SetInnerShutterAngle") + ->VirtualProperty("OuterShutterAngle", "GetOuterShutterAngle", "SetOuterShutterAngle") + + ->VirtualProperty("ShadowsEnabled", "GetEnableShadow", "SetEnableShadow") + ->VirtualProperty("ShadowmapMaxSize", "GetShadowmapMaxSize", "SetShadowmapMaxSize") + ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") + ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") + ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") + ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") + ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); + ; + } + } + + void AreaLightComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AreaLightService")); + } + + void AreaLightComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AreaLightService")); + } + + void AreaLightComponentController::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + dependent.push_back(AZ_CRC_CE("ShapeService")); + } + + AreaLightComponentController::AreaLightComponentController(const AreaLightComponentConfig& config) + : m_configuration(config) + { + } + + void AreaLightComponentController::Activate(EntityId entityId) + { + m_entityId = entityId; + + // Used to determine which features are supported. + m_configuration.m_shapeType = 0; + LmbrCentral::ShapeComponentRequestsBus::EventResult(m_configuration.m_shapeType, m_entityId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetShapeType); + + VerifyLightTypeAndShapeComponent(); + CreateLightShapeDelegate(); + + if (m_configuration.RequiresShapeComponent() && m_lightShapeDelegate == nullptr) + { + AZ_Error("AreaLightComponentController", false, "AreaLightComponentController activated without having required shape component."); + } + + AreaLightRequestBus::Handler::BusConnect(m_entityId); + + ConfigurationChanged(); + } + + void AreaLightComponentController::Deactivate() + { + AreaLightRequestBus::Handler::BusDisconnect(m_entityId); + m_lightShapeDelegate.reset(); + } + + void AreaLightComponentController::SetConfiguration(const AreaLightComponentConfig& config) + { + m_configuration = config; + VerifyLightTypeAndShapeComponent(); + ConfigurationChanged(); + } + + const AreaLightComponentConfig& AreaLightComponentController::GetConfiguration() const + { + return m_configuration; + } + + void AreaLightComponentController::SetVisibiliy(bool isVisible) + { + m_isVisible = isVisible; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetVisibility(m_isVisible); + if (m_isVisible) { - behaviorContext->EBus("AreaLightRequestBus") - ->Event("GetAttenuationRadius", &AreaLightRequestBus::Events::GetAttenuationRadius) - ->Event("SetAttenuationRadius", &AreaLightRequestBus::Events::SetAttenuationRadius) - ->Event("SetAttenuationRadiusMode", &AreaLightRequestBus::Events::SetAttenuationRadiusMode) - ->Event("GetColor", &AreaLightRequestBus::Events::GetColor) - ->Event("SetColor", &AreaLightRequestBus::Events::SetColor) - ->Event("GetEmitsLightBothDirections", &AreaLightRequestBus::Events::GetLightEmitsBothDirections) - ->Event("SetEmitsLightBothDirections", &AreaLightRequestBus::Events::SetLightEmitsBothDirections) - ->Event("GetUseFastApproximation", &AreaLightRequestBus::Events::GetUseFastApproximation) - ->Event("SetUseFastApproximation", &AreaLightRequestBus::Events::SetUseFastApproximation) - ->Event("GetIntensity", &AreaLightRequestBus::Events::GetIntensity) - ->Event("SetIntensity", static_cast(&AreaLightRequestBus::Events::SetIntensity)) - ->Event("GetIntensityMode", &AreaLightRequestBus::Events::GetIntensityMode) - ->Event("ConvertToIntensityMode", &AreaLightRequestBus::Events::ConvertToIntensityMode) - ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") - ->VirtualProperty("Color", "GetColor", "SetColor") - ->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections") - ->VirtualProperty("UseFastApproximation", "GetUseFastApproximation", "SetUseFastApproximation") - ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") - ; + // If the light is made visible, make sure to apply the configuration so all properties as set correctly. + ConfigurationChanged(); } } + } + + void AreaLightComponentController::VerifyLightTypeAndShapeComponent() + { + constexpr Crc32 SphereShapeTypeId = AZ_CRC_CE("Sphere"); + constexpr Crc32 DiskShapeTypeId = AZ_CRC_CE("DiskShape"); + constexpr Crc32 CapsuleShapeTypeId = AZ_CRC_CE("Capsule"); + constexpr Crc32 QuadShapeTypeId = AZ_CRC_CE("QuadShape"); + constexpr Crc32 PoylgonShapeTypeId = AZ_CRC_CE("PolygonPrism"); - void AreaLightComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + if (m_configuration.m_lightType == AreaLightComponentConfig::LightType::Unknown) { - provided.push_back(AZ_CRC_CE("AreaLightService")); - } - - void AreaLightComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC_CE("AreaLightService")); - } - - void AreaLightComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC_CE("AreaLightShapeService")); - } - - AreaLightComponentController::AreaLightComponentController(const AreaLightComponentConfig& config) - : m_configuration(config) - { - } - - void AreaLightComponentController::Activate(EntityId entityId) - { - m_entityId = entityId; - - CreateLightShapeDelegate(); - AZ_Warning("AreaLightComponentController", m_lightShapeDelegate, "AreaLightComponentController activated without having required component."); - - // Used to determine if the shape can be double-sided. - LmbrCentral::ShapeComponentRequestsBus::EventResult(m_configuration.m_shapeType, m_entityId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetShapeType); - - AreaLightRequestBus::Handler::BusConnect(m_entityId); - - ConfigurationChanged(); - } - - void AreaLightComponentController::Deactivate() - { - AreaLightRequestBus::Handler::BusDisconnect(m_entityId); - m_lightShapeDelegate.reset(); - } - - void AreaLightComponentController::SetConfiguration(const AreaLightComponentConfig& config) - { - m_configuration = config; - ConfigurationChanged(); - } - - const AreaLightComponentConfig& AreaLightComponentController::GetConfiguration() const - { - return m_configuration; - } - - void AreaLightComponentController::SetVisibiliy(bool isVisible) - { - m_isVisible = isVisible; - if (m_lightShapeDelegate) + // Light type is unknown, see if it can be determined from a shape component. + switch (m_configuration.m_shapeType) { - m_lightShapeDelegate->SetVisibility(m_isVisible); + case SphereShapeTypeId: + m_configuration.m_lightType = AreaLightComponentConfig::LightType::Sphere; + break; + case DiskShapeTypeId: + m_configuration.m_lightType = AreaLightComponentConfig::LightType::SpotDisk; + break; + case CapsuleShapeTypeId: + m_configuration.m_lightType = AreaLightComponentConfig::LightType::Capsule; + break; + case QuadShapeTypeId: + m_configuration.m_lightType = AreaLightComponentConfig::LightType::Quad; + break; + case PoylgonShapeTypeId: + m_configuration.m_lightType = AreaLightComponentConfig::LightType::Polygon; + break; + default: + break; // Light type can't be deduced. } } - - void AreaLightComponentController::ConfigurationChanged() + else if (m_configuration.m_shapeType == Crc32(0)) { - ChromaChanged(); - IntensityChanged(); - AttenuationRadiusChanged(); + AZ_Error("AreaLightComponentController", !m_configuration.RequiresShapeComponent(), "The light type used on this area light requires a corresponding shape component"); + } + else + { + // Validate the the light type matches up with shape type if the light type is an area light. + AZ_Error("AreaLightComponentController", + !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Sphere && m_configuration.m_shapeType != SphereShapeTypeId), + "The light type is a sphere, but the shape component is not."); + AZ_Error("AreaLightComponentController", + !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::SpotDisk && m_configuration.m_shapeType != DiskShapeTypeId), + "The light type is a disk, but the shape component is not."); + AZ_Error("AreaLightComponentController", + !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Capsule && m_configuration.m_shapeType != CapsuleShapeTypeId), + "The light type is a capsule, but the shape component is not."); + AZ_Error("AreaLightComponentController", + !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Quad && m_configuration.m_shapeType != QuadShapeTypeId), + "The light type is a quad, but the shape component is not."); + AZ_Error("AreaLightComponentController", + !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Polygon && m_configuration.m_shapeType != PoylgonShapeTypeId), + "The light type is a polygon, but the shape component is not."); + } + } - if (m_lightShapeDelegate) + void AreaLightComponentController::ConfigurationChanged() + { + ChromaChanged(); + IntensityChanged(); + AttenuationRadiusChanged(); + ShuttersChanged(); + ShadowsChanged(); + + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetLightEmitsBothDirections(m_configuration.m_lightEmitsBothDirections); + m_lightShapeDelegate->SetUseFastApproximation(m_configuration.m_useFastApproximation); + } + } + + void AreaLightComponentController::IntensityChanged() + { + AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnColorOrIntensityChanged, m_configuration.m_color, m_configuration.m_intensity); + + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetPhotometricUnit(m_configuration.m_intensityMode); + m_lightShapeDelegate->SetIntensity(m_configuration.m_intensity); + } + } + + void AreaLightComponentController::ChromaChanged() + { + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetChroma(m_configuration.m_color); + } + } + + void AreaLightComponentController::AttenuationRadiusChanged() + { + if (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) + { + AutoCalculateAttenuationRadius(); + } + AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnAttenutationRadiusChanged, m_configuration.m_attenuationRadius); + + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetAttenuationRadius(m_configuration.m_attenuationRadius); + } + } + + void AreaLightComponentController::ShuttersChanged() + { + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetEnableShutters(m_configuration.m_enableShutters); + if (m_configuration.m_enableShutters) { - m_lightShapeDelegate->SetLightEmitsBothDirections(m_configuration.m_lightEmitsBothDirections); - m_lightShapeDelegate->SetUseFastApproximation(m_configuration.m_useFastApproximation); + m_lightShapeDelegate->SetShutterAngles(m_configuration.m_innerShutterAngleDegrees, m_configuration.m_outerShutterAngleDegrees); } } + } - void AreaLightComponentController::IntensityChanged() + void AreaLightComponentController::ShadowsChanged() + { + if (m_lightShapeDelegate) { - AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnColorOrIntensityChanged, m_configuration.m_color, m_configuration.m_intensity); - - if (m_lightShapeDelegate) + m_lightShapeDelegate->SetEnableShadow(m_configuration.m_enableShadow); + if (m_configuration.m_enableShadow) { - m_lightShapeDelegate->SetPhotometricUnit(m_configuration.m_intensityMode); - m_lightShapeDelegate->SetIntensity(m_configuration.m_intensity); + m_lightShapeDelegate->SetShadowmapMaxSize(m_configuration.m_shadowmapMaxSize); + m_lightShapeDelegate->SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); + m_lightShapeDelegate->SetSofteningBoundaryWidthAngle(m_configuration.m_boundaryWidthInDegrees); + m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount); + m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount); + m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod); } } + } - void AreaLightComponentController::ChromaChanged() + void AreaLightComponentController::AutoCalculateAttenuationRadius() + { + if (m_lightShapeDelegate) { - if (m_lightShapeDelegate) - { - m_lightShapeDelegate->SetChroma(m_configuration.m_color); - } + m_configuration.m_attenuationRadius = m_lightShapeDelegate->CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity); } + } - void AreaLightComponentController::AttenuationRadiusChanged() - { - if (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) - { - AutoCalculateAttenuationRadius(); - } - AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnAttenutationRadiusChanged, m_configuration.m_attenuationRadius); + const Color& AreaLightComponentController::GetColor() const + { + return m_configuration.m_color; + } - if (m_lightShapeDelegate) - { - m_lightShapeDelegate->SetAttenuationRadius(m_configuration.m_attenuationRadius); - } - } + void AreaLightComponentController::SetColor(const Color& color) + { + m_configuration.m_color = color; + AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnColorChanged, color); + ChromaChanged(); + } - void AreaLightComponentController::AutoCalculateAttenuationRadius() - { - if (m_lightShapeDelegate) - { - m_configuration.m_attenuationRadius = m_lightShapeDelegate->CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity); - } - } + bool AreaLightComponentController::GetLightEmitsBothDirections() const + { + return m_configuration.m_lightEmitsBothDirections; + } - const Color& AreaLightComponentController::GetColor() const - { - return m_configuration.m_color; - } + void AreaLightComponentController::SetLightEmitsBothDirections(bool value) + { + m_configuration.m_lightEmitsBothDirections = value; + } - void AreaLightComponentController::SetColor(const Color& color) - { - m_configuration.m_color = color; - AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnColorChanged, color); - ChromaChanged(); - } + bool AreaLightComponentController::GetUseFastApproximation() const + { + return m_configuration.m_useFastApproximation; + } - bool AreaLightComponentController::GetLightEmitsBothDirections() const - { - return m_configuration.m_lightEmitsBothDirections; - } + void AreaLightComponentController::SetUseFastApproximation(bool value) + { + m_configuration.m_useFastApproximation = value; + } - void AreaLightComponentController::SetLightEmitsBothDirections(bool value) - { - m_configuration.m_lightEmitsBothDirections = value; - } + PhotometricUnit AreaLightComponentController::GetIntensityMode() const + { + return m_configuration.m_intensityMode; + } - bool AreaLightComponentController::GetUseFastApproximation() const - { - return m_configuration.m_useFastApproximation; - } + float AreaLightComponentController::GetIntensity() const + { + return m_configuration.m_intensity; + } - void AreaLightComponentController::SetUseFastApproximation(bool value) - { - m_configuration.m_useFastApproximation = value; - } + void AreaLightComponentController::SetIntensity(float intensity, PhotometricUnit intensityMode) + { + m_configuration.m_intensityMode = intensityMode; + m_configuration.m_intensity = intensity; - PhotometricUnit AreaLightComponentController::GetIntensityMode() const - { - return m_configuration.m_intensityMode; - } + AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnIntensityChanged, intensity, intensityMode); + IntensityChanged(); + } - float AreaLightComponentController::GetIntensity() const - { - return m_configuration.m_intensity; - } + void AreaLightComponentController::SetIntensity(float intensity) + { + m_configuration.m_intensity = intensity; - void AreaLightComponentController::SetIntensity(float intensity, PhotometricUnit intensityMode) + AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnIntensityChanged, intensity, m_configuration.m_intensityMode); + IntensityChanged(); + } + + float AreaLightComponentController::GetAttenuationRadius() const + { + return m_configuration.m_attenuationRadius; + } + + void AreaLightComponentController::SetAttenuationRadius(float radius) + { + m_configuration.m_attenuationRadius = radius; + m_configuration.m_attenuationRadiusMode = LightAttenuationRadiusMode::Explicit; + AttenuationRadiusChanged(); + } + + void AreaLightComponentController::SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) + { + m_configuration.m_attenuationRadiusMode = attenuationRadiusMode; + AttenuationRadiusChanged(); + } + + void AreaLightComponentController::ConvertToIntensityMode(PhotometricUnit intensityMode) + { + if (m_lightShapeDelegate && m_lightShapeDelegate->GetPhotometricValue().GetType() != intensityMode) { m_configuration.m_intensityMode = intensityMode; - m_configuration.m_intensity = intensity; - - AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnIntensityChanged, intensity, intensityMode); - IntensityChanged(); + m_configuration.m_intensity = m_lightShapeDelegate->SetPhotometricUnit(intensityMode); } + } + + bool AreaLightComponentController::GetEnableShutters() const + { + return m_configuration.m_enableShutters; + } - void AreaLightComponentController::SetIntensity(float intensity) + void AreaLightComponentController::SetEnableShutters(bool enabled) + { + m_configuration.m_enableShutters = enabled && m_configuration.SupportsShutters(); + if (m_lightShapeDelegate) { - m_configuration.m_intensity = intensity; - - AreaLightNotificationBus::Event(m_entityId, &AreaLightNotifications::OnIntensityChanged, intensity, m_configuration.m_intensityMode); - IntensityChanged(); + m_lightShapeDelegate->SetEnableShutters(enabled); } + } - float AreaLightComponentController::GetAttenuationRadius() const + float AreaLightComponentController::GetInnerShutterAngle() const + { + return m_configuration.m_innerShutterAngleDegrees; + } + + void AreaLightComponentController::SetInnerShutterAngle(float degrees) + { + m_configuration.m_innerShutterAngleDegrees = degrees; + if (m_lightShapeDelegate) { - return m_configuration.m_attenuationRadius; + m_lightShapeDelegate->SetShutterAngles(m_configuration.m_innerShutterAngleDegrees, m_configuration.m_outerShutterAngleDegrees); } + } - void AreaLightComponentController::SetAttenuationRadius(float radius) + float AreaLightComponentController::GetOuterShutterAngle() const + { + return m_configuration.m_outerShutterAngleDegrees; + } + + void AreaLightComponentController::SetOuterShutterAngle(float degrees) + { + m_configuration.m_outerShutterAngleDegrees = degrees; + if (m_lightShapeDelegate) { - m_configuration.m_attenuationRadius = radius; - m_configuration.m_attenuationRadiusMode = LightAttenuationRadiusMode::Explicit; - AttenuationRadiusChanged(); + m_lightShapeDelegate->SetShutterAngles(m_configuration.m_innerShutterAngleDegrees, m_configuration.m_outerShutterAngleDegrees); } + } - void AreaLightComponentController::SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) + bool AreaLightComponentController::GetEnableShadow() const + { + return m_configuration.m_enableShadow; + } + + void AreaLightComponentController::SetEnableShadow(bool enabled) + { + m_configuration.m_enableShadow = enabled && m_configuration.SupportsShadows(); + if (m_lightShapeDelegate) { - m_configuration.m_attenuationRadiusMode = attenuationRadiusMode; - AttenuationRadiusChanged(); + m_lightShapeDelegate->SetEnableShadow(enabled); } + } - void AreaLightComponentController::ConvertToIntensityMode(PhotometricUnit intensityMode) + ShadowmapSize AreaLightComponentController::GetShadowmapMaxSize() const + { + return m_configuration.m_shadowmapMaxSize; + } + + void AreaLightComponentController::SetShadowmapMaxSize(ShadowmapSize size) + { + m_configuration.m_shadowmapMaxSize = size; + if (m_lightShapeDelegate) { - if (m_lightShapeDelegate && m_lightShapeDelegate->GetPhotometricValue().GetType() != intensityMode) - { - m_configuration.m_intensityMode = intensityMode; - m_configuration.m_intensity = m_lightShapeDelegate->SetPhotometricUnit(intensityMode); - } + m_lightShapeDelegate->SetShadowmapMaxSize(size); } + } - void AreaLightComponentController::HandleDisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay, - bool isSelected) + ShadowFilterMethod AreaLightComponentController::GetShadowFilterMethod() const + { + return m_configuration.m_shadowFilterMethod; + } + + void AreaLightComponentController::SetShadowFilterMethod(ShadowFilterMethod method) + { + m_configuration.m_shadowFilterMethod = method; + if (m_lightShapeDelegate) { - Transform transform = Transform::CreateIdentity(); - TransformBus::EventResult(transform, m_entityId, &TransformBus::Events::GetWorldTM); - if (m_lightShapeDelegate) - { - m_lightShapeDelegate->DrawDebugDisplay(transform, m_configuration.m_color, debugDisplay, isSelected); - } + m_lightShapeDelegate->SetShadowFilterMethod(method); } + } - void AreaLightComponentController::CreateLightShapeDelegate() + float AreaLightComponentController::GetSofteningBoundaryWidthAngle() const + { + return m_configuration.m_boundaryWidthInDegrees; + } + + void AreaLightComponentController::SetSofteningBoundaryWidthAngle(float width) + { + m_configuration.m_boundaryWidthInDegrees = width; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetSofteningBoundaryWidthAngle(width); + } + } + + uint32_t AreaLightComponentController::GetPredictionSampleCount() const + { + return m_configuration.m_predictionSampleCount; + } + + void AreaLightComponentController::SetPredictionSampleCount(uint32_t count) + { + m_configuration.m_predictionSampleCount = count; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetPredictionSampleCount(count); + } + } + + uint32_t AreaLightComponentController::GetFilteringSampleCount() const + { + return m_configuration.m_filteringSampleCount; + } + + void AreaLightComponentController::SetFilteringSampleCount(uint32_t count) + { + m_configuration.m_filteringSampleCount = count; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetFilteringSampleCount(count); + } + } + + void AreaLightComponentController::HandleDisplayEntityViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay, + bool isSelected) + { + Transform transform = Transform::CreateIdentity(); + TransformBus::EventResult(transform, m_entityId, &TransformBus::Events::GetWorldTM); + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->DrawDebugDisplay(transform, m_configuration.m_color, debugDisplay, isSelected); + } + } + + PcfMethod AreaLightComponentController::GetPcfMethod() const + { + return m_configuration.m_pcfMethod; + } + + void AreaLightComponentController::SetPcfMethod(PcfMethod method) + { + m_configuration.m_pcfMethod = method; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetPcfMethod(method); + } + } + + void AreaLightComponentController::CreateLightShapeDelegate() + { + switch (m_configuration.m_lightType) + { + + // Simple types + case AreaLightComponentConfig::LightType::SimplePoint: + m_lightShapeDelegate = AZStd::make_unique(m_entityId, m_isVisible); + break; + case AreaLightComponentConfig::LightType::SimpleSpot: + m_lightShapeDelegate = AZStd::make_unique(m_entityId, m_isVisible); + break; + + // Area light types + case AreaLightComponentConfig::LightType::Sphere: { LmbrCentral::SphereShapeComponentRequests* sphereShapeInterface = LmbrCentral::SphereShapeComponentRequestsBus::FindFirstHandler(m_entityId); if (sphereShapeInterface) { m_lightShapeDelegate = AZStd::make_unique(sphereShapeInterface, m_entityId, m_isVisible); - return; } - + break; + } + case AreaLightComponentConfig::LightType::SpotDisk: + { LmbrCentral::DiskShapeComponentRequests* diskShapeInterface = LmbrCentral::DiskShapeComponentRequestBus::FindFirstHandler(m_entityId); if (diskShapeInterface) { m_lightShapeDelegate = AZStd::make_unique(diskShapeInterface, m_entityId, m_isVisible); - return; } - + break; + } + case AreaLightComponentConfig::LightType::Capsule: + { LmbrCentral::CapsuleShapeComponentRequests* capsuleShapeInterface = LmbrCentral::CapsuleShapeComponentRequestsBus::FindFirstHandler(m_entityId); if (capsuleShapeInterface) { m_lightShapeDelegate = AZStd::make_unique(capsuleShapeInterface, m_entityId, m_isVisible); - return; } - + break; + } + case AreaLightComponentConfig::LightType::Quad: + { LmbrCentral::QuadShapeComponentRequests* quadShapeInterface = LmbrCentral::QuadShapeComponentRequestBus::FindFirstHandler(m_entityId); if (quadShapeInterface) { m_lightShapeDelegate = AZStd::make_unique(quadShapeInterface, m_entityId, m_isVisible); - return; } - + break; + } + case AreaLightComponentConfig::LightType::Polygon: + { LmbrCentral::PolygonPrismShapeComponentRequests* polyPrismShapeInterface = LmbrCentral::PolygonPrismShapeComponentRequestBus::FindFirstHandler(m_entityId); if (polyPrismShapeInterface) { m_lightShapeDelegate = AZStd::make_unique(polyPrismShapeInterface, m_entityId, m_isVisible); - return; } + break; } + } + } - } // namespace Render -} // namespace AZ +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index 253cd9d670..b5f342a522 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -38,7 +38,7 @@ namespace AZ static void Reflect(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); AreaLightComponentController() = default; AreaLightComponentController(const AreaLightComponentConfig& config); @@ -71,15 +71,41 @@ namespace AZ void SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) override; void ConvertToIntensityMode(PhotometricUnit intensityMode) override; + bool GetEnableShutters() const override; + void SetEnableShutters(bool enabled) override; + float GetInnerShutterAngle() const override; + void SetInnerShutterAngle(float degrees) override; + float GetOuterShutterAngle() const override; + void SetOuterShutterAngle(float degrees) override; + + bool GetEnableShadow() const override; + void SetEnableShadow(bool enabled) override; + ShadowmapSize GetShadowmapMaxSize() const override; + void SetShadowmapMaxSize(ShadowmapSize size) override; + ShadowFilterMethod GetShadowFilterMethod() const override; + void SetShadowFilterMethod(ShadowFilterMethod method) override; + float GetSofteningBoundaryWidthAngle() const override; + void SetSofteningBoundaryWidthAngle(float width) override; + uint32_t GetPredictionSampleCount() const override; + void SetPredictionSampleCount(uint32_t count) override; + uint32_t GetFilteringSampleCount() const override; + void SetFilteringSampleCount(uint32_t count) override; + PcfMethod GetPcfMethod() const override; + void SetPcfMethod(PcfMethod method) override; + void HandleDisplayEntityViewport( const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected); + void VerifyLightTypeAndShapeComponent(); + void ConfigurationChanged(); void IntensityChanged(); void ChromaChanged(); void AttenuationRadiusChanged(); + void ShuttersChanged(); + void ShadowsChanged(); //! Handles calculating the attenuation radius when LightAttenuationRadiusMode is auto void AutoCalculateAttenuationRadius(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp index 8d35e9da6c..5bce0e3e80 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp @@ -24,7 +24,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(6) + ->Version(7) ->Field("Color", &DirectionalLightComponentConfig::m_color) ->Field("IntensityMode", &DirectionalLightComponentConfig::m_intensityMode) ->Field("Intensity", &DirectionalLightComponentConfig::m_intensity) @@ -43,7 +43,8 @@ namespace AZ ->Field("SofteningBoundaryWidth", &DirectionalLightComponentConfig::m_boundaryWidth) ->Field("PcfPredictionSampleCount", &DirectionalLightComponentConfig::m_predictionSampleCount) ->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount) - ; + ->Field("Pcf Method", &DirectionalLightComponentConfig::m_pcfMethod) + ; } } @@ -126,5 +127,15 @@ namespace AZ m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); } + bool DirectionalLightComponentConfig::IsPcfBoundarySearchDisabled() const + { + if (IsShadowPcfDisabled()) + { + return true; + } + + return m_pcfMethod != PcfMethod::BoundarySearch; + } + } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp index 1a2f0876c3..c7d459c596 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp @@ -87,6 +87,8 @@ namespace AZ ->Event("SetPredictionSampleCount", &DirectionalLightRequestBus::Events::SetPredictionSampleCount) ->Event("GetFilteringSampleCount", &DirectionalLightRequestBus::Events::GetFilteringSampleCount) ->Event("SetFilteringSampleCount", &DirectionalLightRequestBus::Events::SetFilteringSampleCount) + ->Event("GetPcfMethod", &DirectionalLightRequestBus::Events::GetPcfMethod) + ->Event("SetPcfMethod", &DirectionalLightRequestBus::Events::SetPcfMethod) ->VirtualProperty("Color", "GetColor", "SetColor") ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") ->VirtualProperty("AngularDiameter", "GetAngularDiameter", "SetAngularDiameter") @@ -103,7 +105,8 @@ namespace AZ ->VirtualProperty("SofteningBoundaryWidth", "GetSofteningBoundaryWidth", "SetSofteningBoundaryWidth") ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ; + ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); + ; } } @@ -534,6 +537,7 @@ namespace AZ SetSofteningBoundaryWidth(m_configuration.m_boundaryWidth); SetPredictionSampleCount(m_configuration.m_predictionSampleCount); SetFilteringSampleCount(m_configuration.m_filteringSampleCount); + SetPcfMethod(m_configuration.m_pcfMethod); // [GFX TODO][ATOM-1726] share config for multiple light (e.g., light ID). // [GFX TODO][ATOM-2416] adapt to multiple viewports. @@ -620,6 +624,16 @@ namespace AZ } } + PcfMethod DirectionalLightComponentController::GetPcfMethod() const + { + return m_configuration.m_pcfMethod; + } + + void DirectionalLightComponentController::SetPcfMethod(PcfMethod method) + { + m_configuration.m_pcfMethod = method; + m_featureProcessor->SetPcfMethod(m_lightHandle, method); + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h index df72372cb5..b8e1d00b73 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h @@ -86,6 +86,8 @@ namespace AZ void SetPredictionSampleCount(uint32_t count) override; uint32_t GetFilteringSampleCount() const override; void SetFilteringSampleCount(uint32_t count) override; + PcfMethod GetPcfMethod() const override; + void SetPcfMethod(PcfMethod method) override; private: friend class EditorDirectionalLightComponent; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 2bf4dd4159..32b6a9f0b7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -14,62 +14,121 @@ #include #include -namespace AZ +namespace AZ::Render { - namespace Render + DiskLightDelegate::DiskLightDelegate(LmbrCentral::DiskShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible) + : LightDelegateBase(entityId, isVisible) + , m_shapeBus(shapeBus) { - DiskLightDelegate::DiskLightDelegate(LmbrCentral::DiskShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible) - : LightDelegateBase(entityId, isVisible) - , m_shapeBus(shapeBus) - { - InitBase(entityId); - } - - void DiskLightDelegate::SetLightEmitsBothDirections(bool lightEmitsBothDirections) - { - if (GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetLightEmitsBothDirections(GetLightHandle(), lightEmitsBothDirections); - } - } + InitBase(entityId); + } - float DiskLightDelegate::CalculateAttenuationRadius(float lightThreshold) const - { - // Calculate the radius at which the irradiance will be equal to cutoffIntensity. - float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); - return sqrt(intensity / lightThreshold); - } + float DiskLightDelegate::CalculateAttenuationRadius(float lightThreshold) const + { + // Calculate the radius at which the irradiance will be equal to cutoffIntensity. + float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); + return sqrt(intensity / lightThreshold); + } - void DiskLightDelegate::HandleShapeChanged() + void DiskLightDelegate::HandleShapeChanged() + { + if (GetLightHandle().IsValid()) { - if (GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); - GetFeatureProcessor()->SetDirection(GetLightHandle(), m_shapeBus->GetNormal()); - GetFeatureProcessor()->SetDiskRadius(GetLightHandle(), GetRadius()); - } + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + GetFeatureProcessor()->SetDirection(GetLightHandle(), m_shapeBus->GetNormal()); + GetFeatureProcessor()->SetDiskRadius(GetLightHandle(), GetRadius()); } + } - float DiskLightDelegate::GetSurfaceArea() const + float DiskLightDelegate::GetSurfaceArea() const + { + float radius = GetRadius(); + return Constants::Pi * radius * radius; + } + + float DiskLightDelegate::GetRadius() const + { + return m_shapeBus->GetRadius() * GetTransform().GetScale().GetMaxElement(); + } + + void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + { + if (isSelected) { - float radius = GetRadius(); - return Constants::Pi * radius * radius; - } + debugDisplay.SetColor(color); - float DiskLightDelegate::GetRadius() const + // Draw a disk for the attenuation radius + debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity)); + } + } + + void DiskLightDelegate::SetEnableShutters(bool enabled) + { + Base::SetEnableShutters(enabled); + GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true); + } + + void DiskLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) + { + if (GetShuttersEnabled()) { - return m_shapeBus->GetRadius() * GetTransform().GetScale().GetMaxElement(); + GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); } + } - void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + void DiskLightDelegate::SetEnableShadow(bool enabled) + { + Base::SetEnableShadow(enabled); + GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled); + } + + void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) + { + if (GetShadowsEnabled()) { - if (isSelected) - { - debugDisplay.SetColor(color); - - // Draw a disk for the attenuation radius - debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity)); - } + GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size); } - } // namespace Render -} // namespace AZ + } + + void DiskLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method) + { + if (GetShadowsEnabled()) + { + GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method); + } + } + + void DiskLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees) + { + if (GetShadowsEnabled()) + { + GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees)); + } + } + + void DiskLightDelegate::SetPredictionSampleCount(uint32_t count) + { + if (GetShadowsEnabled()) + { + GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); + } + } + + void DiskLightDelegate::SetFilteringSampleCount(uint32_t count) + { + if (GetShadowsEnabled()) + { + GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); + } + } + + void DiskLightDelegate::SetPcfMethod(PcfMethod method) + { + if (GetShadowsEnabled()) + { + GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); + } + } + + +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 4dd3d2b3a6..5511b435d4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -30,16 +30,28 @@ namespace AZ class DiskLightDelegate final : public LightDelegateBase { + using Base = LightDelegateBase; + public: DiskLightDelegate(LmbrCentral::DiskShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible); // LightDelegateBase overrides... - void SetLightEmitsBothDirections(bool lightEmitsBothDirections) override; float GetSurfaceArea() const override; float GetEffectiveSolidAngle() const override { return PhotometricValue::DirectionalEffectiveSteradians; } float CalculateAttenuationRadius(float lightThreshold) const override; void DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const override; + void SetEnableShutters(bool enabled) override; + void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; + + void SetEnableShadow(bool enabled) override; + void SetShadowmapMaxSize(ShadowmapSize size) override; + void SetShadowFilterMethod(ShadowFilterMethod method) override; + void SetSofteningBoundaryWidthAngle(float widthInDegrees) override; + void SetPredictionSampleCount(uint32_t count) override; + void SetFilteringSampleCount(uint32_t count) override; + void SetPcfMethod(PcfMethod method) override; + private: // LightDelegateBase overrides... diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 4081317890..bdff97b48e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -13,10 +13,17 @@ #include #include +#include +#include #include #include #include +#include +#include +#include +#include +#include namespace AZ { @@ -27,65 +34,145 @@ namespace AZ { } - void EditorAreaLightComponent::Reflect(AZ::ReflectContext* context) + void EditorAreaLightComponent::Reflect(ReflectContext* context) { BaseClass::Reflect(context); - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + if (SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(1, ConvertToEditorRenderComponentAdapter<1>); - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + if (EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Area Light", "An Area light emits light emits light from a goemetric shape.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Atom") - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-area-light.html") + "Light", "A light which emits from a point or goemetric shape.") + ->ClassElement(Edit::ClassElements::EditorData, "") + ->Attribute(Edit::Attributes::Category, "Atom") + ->Attribute(Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") + ->Attribute(Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") + ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-light.html") ; editContext->Class( "AreaLightComponentController", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &AreaLightComponentController::m_configuration, "Configuration", "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->ClassElement(Edit::ClassElements::EditorData, "") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentController::m_configuration, "Configuration", "") + ->Attribute(Edit::Attributes::Visibility, Edit::PropertyVisibility::ShowChildrenOnly) ; editContext->Class( "AreaLightComponentConfig", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->DataElement(AZ::Edit::UIHandlers::Color, &AreaLightComponentConfig::m_color, "Color", "Color of the light") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute("ColorEditorConfiguration", AZ::RPI::ColorUtils::GetLinearRgbEditorConfig()) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying which photometric unit to work in.") - ->EnumAttribute(PhotometricUnit::Candela, "Candela") - ->EnumAttribute(PhotometricUnit::Lumen, "Lumen") - ->EnumAttribute(PhotometricUnit::Nit, "Nit") - ->EnumAttribute(PhotometricUnit::Ev100Luminance, "Ev100") + ->ClassElement(Edit::ClassElements::EditorData, "") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light Type", "Which type of light this component represents.") + ->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a Light Type") + ->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (Sphere)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (Simple)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (Disk)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (Simple)") + ->EnumAttribute(AreaLightComponentConfig::LightType::Capsule, "Capsule") + ->EnumAttribute(AreaLightComponentConfig::LightType::Quad, "Quad") + ->EnumAttribute(AreaLightComponentConfig::LightType::Polygon, "Polygon") + ->DataElement(Edit::UIHandlers::Color, &AreaLightComponentConfig::m_color, "Color", "Color of the light") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute("ColorEditorConfiguration", RPI::ColorUtils::GetLinearRgbEditorConfig()) + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying which photometric unit to work in.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &AreaLightComponentConfig::GetValidPhotometricUnits) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_intensity, "Intensity", "Intensity of the light in the set photometric unit.") ->Attribute(Edit::Attributes::Min, &AreaLightComponentConfig::GetIntensityMin) ->Attribute(Edit::Attributes::Max, &AreaLightComponentConfig::GetIntensityMax) ->Attribute(Edit::Attributes::SoftMin, &AreaLightComponentConfig::GetIntensitySoftMin) ->Attribute(Edit::Attributes::SoftMax, &AreaLightComponentConfig::GetIntensitySoftMax) ->Attribute(Edit::Attributes::Suffix, &AreaLightComponentConfig::GetIntensitySuffix) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both Directions", "Whether light should emit from both sides of the surface or just the front") - ->Attribute(AZ::Edit::Attributes::Visibility, &AreaLightComponentConfig::Is2DSurface) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast Approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") - ->Attribute(AZ::Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsFastApproximation) - ->ClassElement(AZ::Edit::ClassElements::Group, "Attenuation Radius") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.") + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both Directions", "Whether light should emit from both sides of the surface or just the front") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsBothDirections) + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast Approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsFastApproximation) + ->ClassElement(Edit::ClassElements::Group, "Attenuation Radius") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.") ->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic") ->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) - ->DataElement(AZ::Edit::UIHandlers::Default, &AreaLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.") - ->Attribute(AZ::Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.") + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic) + + ->ClassElement(Edit::ClassElements::Group, "Shutters") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable Shutters", "Restrict the light to a specific beam angle depending on shape.") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner Angle", "The inner angle of the shutters where the light beam begins to be occluded.") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 180.0f) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer Angle", "The outer angle of the shutters where the light beam is completely occluded.") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 180.0f) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) + + ->ClassElement(Edit::ClassElements::Group, "Shadows") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable Shadow", "Enable shadow for the light") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap Size", "Width/Height of shadowmap") + ->EnumAttribute(ShadowmapSize::Size256, " 256") + ->EnumAttribute(ShadowmapSize::Size512, " 512") + ->EnumAttribute(ShadowmapSize::Size1024, "1024") + ->EnumAttribute(ShadowmapSize::Size2048, "2048") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow Filter Method", + "Filtering method of edge-softening of shadows.\n" + " None: no filtering\n" + " PCF: Percentage-Closer Filtering\n" + " ESM: Exponential Shadow Maps\n" + " ESM+PCF: ESM with a PCF fallback\n" + "For BehaviorContext (or TrackView), None=0, PCF=1, ESM=2, ESM+PCF=3") + ->EnumAttribute(ShadowFilterMethod::None, "None") + ->EnumAttribute(ShadowFilterMethod::Pcf, "PCF") + ->EnumAttribute(ShadowFilterMethod::Esm, "ESM") + ->EnumAttribute(ShadowFilterMethod::EsmPcf, "ESM+PCF") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening Boundary Width", + "Width of the boundary between shadowed area and lit one. " + "Units are in degrees. " + "If this is 0, softening edge is disabled.") + ->Attribute(Edit::Attributes::Min, 0.f) + ->Attribute(Edit::Attributes::Max, 1.f) + ->Attribute(Edit::Attributes::Suffix, " deg") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count", + "Sample Count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.") + ->Attribute(Edit::Attributes::Min, 4) + ->Attribute(Edit::Attributes::Max, 16) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count", + "It is used only when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.") + ->Attribute(Edit::Attributes::Min, 4) + ->Attribute(Edit::Attributes::Max, 64) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) + ->DataElement( + Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf Method", + "Type of Pcf to use.\n" + " Boundary search: do several taps to first determine if we are on a shadow boundary\n" + " Bicubic: a smooth, fixed-size kernel \n") + ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search") + ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled); ; } } @@ -95,8 +182,8 @@ namespace AZ behaviorContext->Class()->RequestBus("AreaLightRequestBus"); behaviorContext->ConstantProperty("EditorAreaLightComponentTypeId", BehaviorConstant(Uuid(EditorAreaLightComponentTypeId))) - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); + ->Attribute(Script::Attributes::Module, "render") + ->Attribute(Script::Attributes::Scope, Script::Attributes::ScopeFlags::Automation); } } @@ -119,14 +206,139 @@ namespace AZ BaseClass::Deactivate(); } - AZ::u32 EditorAreaLightComponent::OnConfigurationChanged() + bool EditorAreaLightComponent::HandleLightTypeChange() { + if (m_lightType == AreaLightComponentConfig::LightType::Unknown) + { + // Light type is unknown, see if it can be determined from a shape component. + Crc32 shapeType = Crc32(0); + LmbrCentral::ShapeComponentRequestsBus::EventResult(shapeType, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetShapeType); + + constexpr Crc32 SphereShapeTypeId = AZ_CRC_CE("Sphere"); + constexpr Crc32 DiskShapeTypeId = AZ_CRC_CE("DiskShape"); + constexpr Crc32 CapsuleShapeTypeId = AZ_CRC_CE("Capsule"); + constexpr Crc32 QuadShapeTypeId = AZ_CRC_CE("QuadShape"); + constexpr Crc32 PoylgonShapeTypeId = AZ_CRC_CE("PolygonPrism"); + + switch (shapeType) + { + case SphereShapeTypeId: + m_lightType = AreaLightComponentConfig::LightType::Sphere; + break; + case DiskShapeTypeId: + m_lightType = AreaLightComponentConfig::LightType::SpotDisk; + break; + case CapsuleShapeTypeId: + m_lightType = AreaLightComponentConfig::LightType::Capsule; + break; + case QuadShapeTypeId: + m_lightType = AreaLightComponentConfig::LightType::Quad; + break; + case PoylgonShapeTypeId: + m_lightType = AreaLightComponentConfig::LightType::Polygon; + break; + default: + break; // Light type can't be deduced. + } + } + + if (m_lightType == m_controller.m_configuration.m_lightType) + { + // No change, nothing to do + return false; + } + + // Update the cached light type. + m_lightType = m_controller.m_configuration.m_lightType; + + // componets may be removed or added here, so deactivate now and reactivate the entity when everything is done shifting around. + GetEntity()->Deactivate(); + + // Check if there is already a shape components and remove it. + for (Component* component : GetEntity()->GetComponents()) + { + ComponentDescriptor::DependencyArrayType provided; + ComponentDescriptor* componentDescriptor = nullptr; + EBUS_EVENT_ID_RESULT(componentDescriptor, component->RTTI_GetType(), ComponentDescriptorBus, GetDescriptor); + AZ_Assert(componentDescriptor, "Component class %s descriptor is not created! It must be before you can use it!", component->RTTI_GetTypeName()); + componentDescriptor->GetProvidedServices(provided, component); + auto providedItr = AZStd::find(provided.begin(), provided.end(), AZ_CRC_CE("ShapeService")); + if (providedItr != provided.end()) + { + AZStd::vector componentsToRemove = { component }; + AzToolsFramework::EntityCompositionRequests::RemoveComponentsOutcome outcome = + AZ::Failure(AZStd::string("Failed to remove old shape component.")); + AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(outcome, &AzToolsFramework::EntityCompositionRequests::RemoveComponents, componentsToRemove); + break; + } + } + + // Add a new shape component for light types that require it. + + auto addComponentOfType = [&](AZ::Uuid type) + { + AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome outcome = + AZ::Failure(AZStd::string("Failed to add shape component for light type")); + + const AZStd::vector entityList = { GetEntityId() }; + + AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(outcome, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, + entityList, ComponentTypeList({ type })); + }; + + switch (m_lightType) + { + case AreaLightComponentConfig::LightType::Sphere: + addComponentOfType(LmbrCentral::EditorSphereShapeComponentTypeId); + break; + case AreaLightComponentConfig::LightType::SpotDisk: + addComponentOfType(LmbrCentral::EditorDiskShapeComponentTypeId); + break; + case AreaLightComponentConfig::LightType::Capsule: + addComponentOfType(LmbrCentral::EditorCapsuleShapeComponentTypeId); + break; + case AreaLightComponentConfig::LightType::Quad: + addComponentOfType(LmbrCentral::EditorQuadShapeComponentTypeId); + break; + case AreaLightComponentConfig::LightType::Polygon: + addComponentOfType(LmbrCentral::EditorPolygonPrismShapeComponentTypeId); + break; + default: + // Some light types don't require a shape, this is ok. + break; + } + + GetEntity()->Activate(); + + // Set more reasonable default values for certain shapes. + switch (m_lightType) + { + case AreaLightComponentConfig::LightType::Sphere: + LmbrCentral::SphereShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::SphereShapeComponentRequests::SetRadius, 0.05f); + break; + case AreaLightComponentConfig::LightType::SpotDisk: + LmbrCentral::DiskShapeComponentRequestBus::Event(GetEntityId(), &LmbrCentral::DiskShapeComponentRequests::SetRadius, 0.05f); + break; + } + + return true; + } + + u32 EditorAreaLightComponent::OnConfigurationChanged() + { + bool needsFullRefresh = HandleLightTypeChange(); + LmbrCentral::EditorShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::EditorShapeComponentRequests::SetShapeColor, m_controller.m_configuration.m_color); // If photometric unit changes, convert the intensities so the actual intensity doesn't change. m_controller.ConvertToIntensityMode(m_controller.m_configuration.m_intensityMode); BaseClass::OnConfigurationChanged(); + + if (needsFullRefresh) + { + return Edit::PropertyRefreshLevels::EntireTree; + } return Edit::PropertyRefreshLevels::AttributesAndValues; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.h index f7d8157ecb..cb520b55db 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.h @@ -52,7 +52,11 @@ namespace AZ // EditorRenderComponentAdapter overrides... bool ShouldActivateController() const override; - AZ::u32 OnConfigurationChanged() override; + bool HandleLightTypeChange(); + + u32 OnConfigurationChanged() override; + + AreaLightComponentConfig::LightType m_lightType; // Used to detect when the configuration's light type changes. }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp index d2ca747e83..c484db5e1e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp @@ -145,14 +145,14 @@ namespace AZ ->Attribute(Edit::Attributes::Max, 0.1f) ->Attribute(Edit::Attributes::Suffix, " m") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowFilteringDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsPcfBoundarySearchDisabled) ->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count", "Sample Count for prediction of whether the pixel is on the boundary. " "Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 16) ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsPcfBoundarySearchDisabled) ->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count", "It is used only when the pixel is predicted as on the boundary. " "Specific to PCF and ESM+PCF.") @@ -160,7 +160,17 @@ namespace AZ ->Attribute(Edit::Attributes::Max, 64) ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled) - ; + ->DataElement( + Edit::UIHandlers::ComboBox, &DirectionalLightComponentConfig::m_pcfMethod, "Pcf Method", + "Type of Pcf to use.\n" + " Boundary search: do several taps to first determine if we are on a shadow boundary\n" + " Bicubic: a smooth, fixed-size kernel \n") + ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search") + ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled); + ; + } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.cpp deleted file mode 100644 index f9be9a8a7a..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.cpp +++ /dev/null @@ -1,206 +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 - -#include -#include -#include - -namespace AZ -{ - namespace Render - { - EditorPointLightComponent::EditorPointLightComponent(const PointLightComponentConfig& config) - : BaseClass(config) - { - } - - void EditorPointLightComponent::Reflect(AZ::ReflectContext* context) - { - BaseClass::Reflect(context); - - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1, ConvertToEditorRenderComponentAdapter<1>); - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class( - "Point Light", "A point light emits light in all directions from a single point in space.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Atom") - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-point-light.html") - ; - - editContext->Class( - "PointLightComponentController", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &PointLightComponentController::m_configuration, "Configuration", "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - - editContext->Class( - "PointLightComponentConfig", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->DataElement(AZ::Edit::UIHandlers::Color, &PointLightComponentConfig::m_color, "Color", "Color of the light") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute("ColorEditorConfiguration", AZ::RPI::ColorUtils::GetLinearRgbEditorConfig()) - ->DataElement(Edit::UIHandlers::ComboBox, &PointLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying light values in candelas or lumens") - ->EnumAttribute(PhotometricUnit::Candela, "Candela") - ->EnumAttribute(PhotometricUnit::Lumen, "Lumen") - ->EnumAttribute(PhotometricUnit::Nit, "Nit") - ->EnumAttribute(PhotometricUnit::Ev100Luminance, "Ev100") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) - ->DataElement(AZ::Edit::UIHandlers::Default, &PointLightComponentConfig::m_intensity, "Intensity", "Intensity of the light") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Suffix, &PointLightComponentConfig::GetIntensitySuffix) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(AZ::Edit::UIHandlers::Slider, &PointLightComponentConfig::m_bulbRadius, "Bulb Radius", "The size of the bulb in meters") - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::Max, 100000.0f) - ->Attribute(AZ::Edit::Attributes::SoftMin, 0.01f) - ->Attribute(AZ::Edit::Attributes::SoftMax, 1.0f) - ->Attribute(AZ::Edit::Attributes::Suffix, " m") - ->ClassElement(AZ::Edit::ClassElements::Group, "Attenuation Radius") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &PointLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.") - ->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic") - ->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) - ->DataElement(AZ::Edit::UIHandlers::Default, &PointLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.") - ->Attribute(AZ::Edit::Attributes::ReadOnly, &PointLightComponentConfig::IsAttenuationRadiusModeAutomatic) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("PointLightRequestBus"); - - behaviorContext->ConstantProperty("EditorPointLightComponentTypeId", BehaviorConstant(Uuid(EditorPointLightComponentTypeId))) - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); - } - } - - void EditorPointLightComponent::Activate() - { - BaseClass::Activate(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); - TransformNotificationBus::Handler::BusConnect(GetEntityId()); - AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId()); - } - - void EditorPointLightComponent::Deactivate() - { - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - BaseClass::Deactivate(); - } - - AZStd::tuple EditorPointLightComponent::GetRadiusAndPosition() const - { - Vector3 position = Vector3::CreateZero(); - AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); - return AZStd::tuple(m_controller.GetBulbRadius(), position); - } - - AZStd::tuple EditorPointLightComponent::GetViewportRadiusAndPosition(const AzFramework::ViewportInfo& viewportInfo) const - { - const auto [radius, position] = GetRadiusAndPosition(); - - constexpr float PixelRadius = 10.0f; - const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId); - const float distance = cameraState.m_position.GetDistance(position); - const float screenScale = (distance * cameraState.m_fovOrZoom) / cameraState.m_viewportSize.GetX(); - - return AZStd::tuple(AZ::GetMax(radius, screenScale * PixelRadius), position); - } - - void EditorPointLightComponent::DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - debugDisplay.SetColor(m_controller.GetColor()); - - // Draw a sphere for the light itself. - auto [sphereSize, position] = GetViewportRadiusAndPosition(viewportInfo); - debugDisplay.DrawWireSphere(position, sphereSize); - - // Don't draw extra visualization unless selected. - if (!IsSelected()) - { - return; - } - - // Draw a sphere for the attenuation radius - debugDisplay.DrawWireSphere(position, m_controller.GetAttenuationRadius()); - } - - AZ::Aabb EditorPointLightComponent::GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) - { - auto [radius, position] = GetViewportRadiusAndPosition(viewportInfo); - return Aabb::CreateCenterRadius(position, radius); - } - - bool EditorPointLightComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) - { - auto [radius, position] = GetViewportRadiusAndPosition(viewportInfo); - return AZ::Intersect::IntersectRaySphere(src, dir, position, radius, distance) > 0; - } - - void EditorPointLightComponent::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world) - { - // Transform scale impacts the bulb radius and intensity of the light, so refresh the values. - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_Values); - } - - AZ::Aabb EditorPointLightComponent::GetWorldBounds() - { - auto [radius, position] = GetRadiusAndPosition(); - return Aabb::CreateCenterRadius(position, radius); - } - - AZ::Aabb EditorPointLightComponent::GetLocalBounds() - { - return Aabb::CreateCenterRadius(AZ::Vector3::CreateZero(), m_controller.GetBulbRadius()); - } - - u32 EditorPointLightComponent::OnConfigurationChanged() - { - // Set the intenstiy of the photometric unit in case the controller is disabled. This is needed to correctly convert between photometric units. - m_controller.m_photometricValue.SetIntensity(m_controller.m_configuration.m_intensity); - - // If the intensity mode changes in the editor, convert the photometric value and update the intensity - if (m_controller.m_configuration.m_intensityMode != m_controller.m_photometricValue.GetType()) - { - m_controller.m_photometricValue.SetArea(m_controller.m_configuration.GetArea()); - m_controller.m_photometricValue.ConvertToPhotometricUnit(m_controller.m_configuration.m_intensityMode); - m_controller.m_configuration.m_intensity = m_controller.m_photometricValue.GetIntensity(); - } - - BaseClass::OnConfigurationChanged(); - return Edit::PropertyRefreshLevels::AttributesAndValues; - } - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.h deleted file mode 100644 index 37855c9e04..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorPointLightComponent.h +++ /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. -* -*/ - -#pragma once - -#include -#include -#include -#include -#include - -namespace AZ -{ - namespace Render - { - class EditorPointLightComponent final - : public EditorRenderComponentAdapter - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private TransformNotificationBus::Handler - , public AzFramework::BoundsRequestBus::Handler - { - public: - using BaseClass = EditorRenderComponentAdapter; - AZ_EDITOR_COMPONENT(AZ::Render::EditorPointLightComponent, EditorPointLightComponentTypeId, BaseClass); - - static void Reflect(AZ::ReflectContext* context); - - EditorPointLightComponent() = default; - EditorPointLightComponent(const PointLightComponentConfig& config); - - void Activate() override; - void Deactivate() override; - - // EntityDebugDisplayEventBus overrides ... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // EditorComponentSelectionRequestsBus overrides ... - bool SupportsEditorRayIntersect() override { return true; } - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; - AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override; - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - private: - AZStd::tuple GetRadiusAndPosition() const; - - // TransformNotificationBus::Handler overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - //! Returns a radius for the light relative to the viewport, ensuring the the light will always take up at least a certain amount of - //! screen space for selection and debug drawing - AZStd::tuple GetViewportRadiusAndPosition(const AzFramework::ViewportInfo& viewportInfo) const; - - //! EditorRenderComponentAdapter overrides ... - u32 OnConfigurationChanged() override; - }; - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.cpp deleted file mode 100644 index 61a5d726c3..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.cpp +++ /dev/null @@ -1,261 +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 -#include -#include -#include - -namespace AZ -{ - namespace Render - { - EditorSpotLightComponent::EditorSpotLightComponent(const SpotLightComponentConfig& config) - : BaseClass(config) - { - } - - void EditorSpotLightComponent::Reflect(AZ::ReflectContext* context) - { - BaseClass::Reflect(context); - - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(3, ConvertToEditorRenderComponentAdapter<2>); - - if (AZ::EditContext * editContext = serializeContext->GetEditContext()) - { - editContext->Class( - "Spot Light", "A spot light emits light in a cone from a single point in space.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Atom") - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-spot-light.html") - ; - - editContext->Class( - "SpotLightComponentController", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &SpotLightComponentController::m_configuration, "Configuration", "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - - editContext->Class( - "SpotLightComponentConfig", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->DataElement(AZ::Edit::UIHandlers::Color, &SpotLightComponentConfig::m_color, "Color", "Color of the light") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute("ColorEditorConfiguration", AZ::RPI::ColorUtils::GetLinearRgbEditorConfig()) - ->DataElement(Edit::UIHandlers::ComboBox, &SpotLightComponentConfig::m_intensityMode, "Intensity Mode", - "Allows specifying light values in candelas or lumens") - ->EnumAttribute(PhotometricUnit::Candela, "Candela") - ->EnumAttribute(PhotometricUnit::Lumen, "Lumen") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) - ->DataElement(AZ::Edit::UIHandlers::Default, &SpotLightComponentConfig::m_intensity, "Intensity", "Intensity of the light") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Suffix, &SpotLightComponentConfig::GetIntensitySuffix) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(AZ::Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_bulbRadius, "Bulb Radius", - "Radius of the disk that represents the spot light bulb.") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::SoftMax, 0.25f) - ->Attribute(AZ::Edit::Attributes::Suffix, " m") - ->ClassElement(AZ::Edit::ClassElements::Group, "Cone Configuration") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_innerConeDegrees, "Inner Cone Angle", - "Angle from the direction axis at which this light starts to fall off.") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, &SpotLightComponentConfig::GetConeDegrees) - ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(AZ::Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_outerConeDegrees, "Outer Cone Angle", - "Angle from the direction axis at which this light no longer has an effect.") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, &SpotLightComponentConfig::GetConeDegrees) - ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(AZ::Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_penumbraBias, "Penumbra Bias", - "Controls biasing the fall off curve of the penumbra towards the inner or outer cone angles.") - ->Attribute(AZ::Edit::Attributes::Min, -1.0f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->ClassElement(AZ::Edit::ClassElements::Group, "Attenuation Radius") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SpotLightComponentConfig::m_attenuationRadiusMode, "Mode", - "Controls whether the attenuation radius is calculated automatically or set explicitly.") - ->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic") - ->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) - ->DataElement(AZ::Edit::UIHandlers::Default, &SpotLightComponentConfig::m_attenuationRadius, "Radius", - "The distance at which this light no longer has an affect.") - ->Attribute(AZ::Edit::Attributes::ReadOnly, &SpotLightComponentConfig::IsAttenuationRadiusModeAutomatic) - ->ClassElement(AZ::Edit::ClassElements::Group, "Shadow") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(Edit::UIHandlers::Default, &SpotLightComponentConfig::m_enabledShadow, "Enable Shadow", "Enable shadow for the light") - ->DataElement(Edit::UIHandlers::ComboBox, &SpotLightComponentConfig::m_shadowmapSize, "Shadowmap Size", "Width/Height of shadowmap") - ->EnumAttribute(ShadowmapSize::Size256, " 256") - ->EnumAttribute(ShadowmapSize::Size512, " 512") - ->EnumAttribute(ShadowmapSize::Size1024, "1024") - ->EnumAttribute(ShadowmapSize::Size2048, "2048") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(Edit::UIHandlers::ComboBox, &SpotLightComponentConfig::m_shadowFilterMethod, "Shadow Filter Method", - "Filtering method of edge-softening of shadows.\n" - " None: no filtering\n" - " PCF: Percentage-Closer Filtering\n" - " ESM: Exponential Shadow Maps\n" - " ESM+PCF: ESM with a PCF fallback\n" - "For BehaviorContext (or TrackView), None=0, PCF=1, ESM=2, ESM+PCF=3") - ->EnumAttribute(ShadowFilterMethod::None, "None") - ->EnumAttribute(ShadowFilterMethod::Pcf, "PCF") - ->EnumAttribute(ShadowFilterMethod::Esm, "ESM") - ->EnumAttribute(ShadowFilterMethod::EsmPcf, "ESM+PCF") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_boundaryWidthInDegrees, "Softening Boundary Width", - "Width of the boundary between shadowed area and lit one. " - "Units are in degrees. " - "If this is 0, softening edge is disabled.") - ->Attribute(Edit::Attributes::Min, 0.f) - ->Attribute(Edit::Attributes::Max, 1.f) - ->Attribute(Edit::Attributes::Suffix, " deg") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &SpotLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count", - "Sample Count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.") - ->Attribute(Edit::Attributes::Min, 4) - ->Attribute(Edit::Attributes::Max, 16) - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &SpotLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &SpotLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count", - "It is used only when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.") - ->Attribute(Edit::Attributes::Min, 4) - ->Attribute(Edit::Attributes::Max, 64) - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &SpotLightComponentConfig::IsShadowPcfDisabled) - ->DataElement( - Edit::UIHandlers::ComboBox, &SpotLightComponentConfig::m_pcfMethod, "Pcf Method", - "Type of Pcf to use.\n" - " Boundary search: do several taps to first determine if we are on a shadow boundary\n" - " Bicubic: a smooth, fixed-size kernel \n") - ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search") - ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &SpotLightComponentConfig::IsShadowPcfDisabled); - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("SpotLightRequestBus"); - - behaviorContext->ConstantProperty("EditorSpotLightComponentTypeId", BehaviorConstant(Uuid(EditorSpotLightComponentTypeId))) - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); - } - } - - void EditorSpotLightComponent::Activate() - { - BaseClass::Activate(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - } - - void EditorSpotLightComponent::Deactivate() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - BaseClass::Deactivate(); - } - - void EditorSpotLightComponent::DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - AZ::Transform worldTM; - AZ::TransformBus::EventResult(worldTM, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - const AZ::Vector3 position = worldTM.GetTranslation(); - - debugDisplay.SetColor(m_controller.GetColor()); - - // Draw a sphere for the light itself. - const float pixelRadius = 10.0f; - const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId); - const float distance = cameraState.m_position.GetDistance(position); - const float screenScale = (distance * cameraState.m_fovOrZoom) / cameraState.m_viewportSize.GetX(); - debugDisplay.DrawWireSphere(position, screenScale * pixelRadius); - - // Don't draw extra visualization unless selected. - if (!IsSelected()) - { - return; - } - - /* - * Draw rays to show the affected volume of the spot light. - * As well as two circle showing inner and outer cone angles. - * Note: the circles will not be drawn if cone are angles go beyond 90 degrees. - */ - worldTM.ExtractScale(); - debugDisplay.PushMatrix(worldTM); - debugDisplay.SetColor(m_controller.GetColor()); - - float outerConeHalfAngle = m_controller.GetOuterConeAngleInDegrees() * 0.5f; - float innerConeHalfAngle = m_controller.GetInnerConeAngleInDegrees() * 0.5f; - const float debugConeHeight = m_controller.GetAttenuationRadius(); - - const float debugOuterConeRadius = tanf(AZ::DegToRad(outerConeHalfAngle)) * debugConeHeight; - debugDisplay.DrawArrow(Vector3::CreateZero(), Vector3::CreateAxisY() * debugConeHeight * 0.5f, debugConeHeight * 0.2f); - - constexpr float rightAngleInDegrees = 90.0f; - if (outerConeHalfAngle < rightAngleInDegrees) - { - // outer cone - debugDisplay.DrawCircle(Vector3::CreateAxisY() * debugConeHeight, debugOuterConeRadius, 1); - } - if (innerConeHalfAngle < rightAngleInDegrees) - { - // inner cone - const float debugInnerConeRadius = tanf(AZ::DegToRad(innerConeHalfAngle)) * debugConeHeight; - debugDisplay.DrawCircle(Vector3::CreateAxisY() * debugConeHeight, debugInnerConeRadius, 1); - } - - constexpr int debugRays = 6; - for (int rayIndex = 0; rayIndex < debugRays; ++rayIndex) - { - const float angle = (AZ::Constants::TwoPi / debugRays) * rayIndex; - const Vector3 spotRay = Vector3::CreateAxisY() * debugConeHeight + debugOuterConeRadius * Vector3(sinf(angle), 0.f, cosf(angle)); - debugDisplay.DrawLine(Vector3::CreateZero(), spotRay * (outerConeHalfAngle > rightAngleInDegrees ? -1.f : 1.f)); - } - - debugDisplay.PopMatrix(); - } - - u32 EditorSpotLightComponent::OnConfigurationChanged() - { - // Set the intenstiy of the photometric unit in case the controller is disabled. This is needed to correctly convert between photometric units. - m_controller.m_photometricValue.SetIntensity(m_controller.m_configuration.m_intensity); - - // If the intensity mode changes in the editor, convert the photometric value and update the intensity - if (m_controller.m_configuration.m_intensityMode != m_controller.m_photometricValue.GetType()) - { - m_controller.m_photometricValue.ConvertToPhotometricUnit(m_controller.m_configuration.m_intensityMode); - m_controller.m_configuration.m_intensity = m_controller.m_photometricValue.GetIntensity(); - } - - BaseClass::OnConfigurationChanged(); - return Edit::PropertyRefreshLevels::AttributesAndValues; - } - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.h deleted file mode 100644 index 1070854112..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorSpotLightComponent.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 -#include - -namespace AZ -{ - namespace Render - { - class EditorSpotLightComponent final - : public EditorRenderComponentAdapter - , private AzFramework::EntityDebugDisplayEventBus::Handler - { - public: - - using BaseClass = EditorRenderComponentAdapter; - AZ_EDITOR_COMPONENT(AZ::Render::EditorSpotLightComponent, EditorSpotLightComponentTypeId, BaseClass); - - static void Reflect(AZ::ReflectContext* context); - - EditorSpotLightComponent() = default; - EditorSpotLightComponent(const SpotLightComponentConfig& config); - - void Activate() override; - void Deactivate() override; - - // AzFramework::EntityDebugDisplayEventBus::Handler overrides... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // EditorComponentAdapter overrides... - AZ::u32 OnConfigurationChanged() override; - }; - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 07c9c5160e..4cf94c1a58 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -34,20 +34,32 @@ namespace AZ class LightDelegateBase : public LightDelegateInterface , private LmbrCentral::ShapeComponentNotificationsBus::Handler + , private TransformNotificationBus::Handler { public: LightDelegateBase(EntityId entityId, bool isVisible); virtual ~LightDelegateBase(); // LightDelegateInterface overrides... - virtual void SetChroma(const AZ::Color& chroma) override; - virtual void SetIntensity(float intensity) override; - virtual float SetPhotometricUnit(PhotometricUnit unit) override; - virtual void SetAttenuationRadius(float radius) override; - virtual const PhotometricValue& GetPhotometricValue() const override { return m_photometricValue; }; - virtual void SetLightEmitsBothDirections([[maybe_unused]] bool lightEmitsBothDirections) override {}; - virtual void SetUseFastApproximation([[maybe_unused]] bool useFastApproximation) override {}; - virtual void SetVisibility(bool visibility) override; + void SetChroma(const AZ::Color& chroma) override; + void SetIntensity(float intensity) override; + float SetPhotometricUnit(PhotometricUnit unit) override; + void SetAttenuationRadius(float radius) override; + const PhotometricValue& GetPhotometricValue() const override { return m_photometricValue; }; + void SetLightEmitsBothDirections([[maybe_unused]] bool lightEmitsBothDirections) override {}; + void SetUseFastApproximation([[maybe_unused]] bool useFastApproximation) override {}; + void SetVisibility(bool visibility) override; + + void SetEnableShutters(bool enabled) override { m_shuttersEnabled = enabled; }; + void SetShutterAngles([[maybe_unused]]float innerAngleDegrees, [[maybe_unused]]float outerAngleDegrees) override {}; + + void SetEnableShadow(bool enabled) override { m_shadowsEnabled = enabled; }; + void SetShadowmapMaxSize([[maybe_unused]] ShadowmapSize size) override {}; + void SetShadowFilterMethod([[maybe_unused]] ShadowFilterMethod method) override {}; + void SetSofteningBoundaryWidthAngle([[maybe_unused]] float widthInDegrees) override {}; + void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {}; + void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {}; + void SetPcfMethod([[maybe_unused]] PcfMethod method) override {}; protected: void InitBase(EntityId entityId); @@ -56,11 +68,15 @@ namespace AZ FeatureProcessorType* GetFeatureProcessor() const { return m_featureProcessor; }; typename FeatureProcessorType::LightHandle GetLightHandle() const { return m_lightHandle; }; const AZ::Transform& GetTransform() const { return m_transform; }; - + bool GetShuttersEnabled() { return m_shuttersEnabled; }; + bool GetShadowsEnabled() { return m_shadowsEnabled; }; virtual void HandleShapeChanged() = 0; // ShapeComponentNotificationsBus::Handler overrides... void OnShapeChanged(ShapeChangeReasons changeReason) override; + + // TransformNotificationBus::Handler overrides ... + void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; private: FeatureProcessorType* m_featureProcessor = nullptr; @@ -69,6 +85,8 @@ namespace AZ LmbrCentral::ShapeComponentRequests* m_shapeBus; AZ::Transform m_transform; PhotometricValue m_photometricValue; + bool m_shuttersEnabled = false; + bool m_shadowsEnabled = false; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl index 4f2e02505c..ee4a29f1b0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl @@ -31,6 +31,7 @@ namespace AZ template LightDelegateBase::~LightDelegateBase() { + TransformNotificationBus::Handler::BusDisconnect(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); if (m_lightHandle.IsValid()) { @@ -42,10 +43,21 @@ namespace AZ void LightDelegateBase::InitBase(EntityId entityId) { m_photometricValue.SetEffectiveSolidAngle(GetEffectiveSolidAngle()); - LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(entityId); m_shapeBus = LmbrCentral::ShapeComponentRequestsBus::FindFirstHandler(entityId); TransformBus::EventResult(m_transform, entityId, &TransformBus::Events::GetWorldTM); - OnShapeChanged(ShapeChangeReasons::TransformChanged); + + if (m_shapeBus != nullptr) + { + LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(entityId); + OnShapeChanged(ShapeChangeReasons::TransformChanged); + } + else if (m_lightHandle.IsValid()) + { + // Only connect to the transform bus if there's no shape bus, otherwise the shape bus handles transforms. + TransformNotificationBus::Handler::BusConnect(entityId); + HandleShapeChanged(); + m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb()); + } } template @@ -95,6 +107,13 @@ namespace AZ } HandleShapeChanged(); } + + template + void LightDelegateBase::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) + { + m_transform = world; + HandleShapeChanged(); + } template void LightDelegateBase::SetVisibility(bool isVisible) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index 2a5ae70bd8..110a7d73ad 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -14,6 +14,7 @@ #include #include +#include namespace AzFramework { @@ -56,6 +57,31 @@ namespace AZ virtual void DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const = 0; //! Turns the visibility of this light on/off. virtual void SetVisibility(bool visibility) = 0; + + // Shutters + + // Sets if the light should be restricted to shutter angles. + virtual void SetEnableShutters(bool enabled) = 0; + // Sets the inner and outer angles of the shutters in degrees for where the light + // beam starts to attenuate (inner) to where it is completely occluded (outer). + virtual void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) = 0; + + // Shadows + + //! Sets if shadows should be enabled + virtual void SetEnableShadow(bool enabled) = 0; + //! Sets the maximum resolution of the shadow map + virtual void SetShadowmapMaxSize(ShadowmapSize size) = 0; + //! Sets the filter method for the shadow + virtual void SetShadowFilterMethod(ShadowFilterMethod method) = 0; + //! Sets the width of boundary between shadowed area and lit area in degrees. + virtual void SetSofteningBoundaryWidthAngle(float widthInDegrees) = 0; + //! Sets the sample count to predict the boundary of the shadow. Max 16, should be less than filtering sample count. + virtual void SetPredictionSampleCount(uint32_t count) = 0; + //! Sets the sample count for filtering of the shadow boundary, max 64. + virtual void SetFilteringSampleCount(uint32_t count) = 0; + //! Sets the Pcf (Percentage closer filtering) method to use. + virtual void SetPcfMethod(PcfMethod method) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.cpp deleted file mode 100644 index 98fdf47dfd..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.cpp +++ /dev/null @@ -1,44 +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 - -namespace AZ -{ - namespace Render - { - - PointLightComponent::PointLightComponent(const PointLightComponentConfig& config) - : BaseClass(config) - { - } - - void PointLightComponent::Reflect(AZ::ReflectContext* context) - { - BaseClass::Reflect(context); - - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class(); - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("PointLightRequestBus"); - - behaviorContext->ConstantProperty("PointLightComponentTypeId", BehaviorConstant(Uuid(PointLightComponentTypeId))) - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common); - } - } - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.h deleted file mode 100644 index b987a0aaf9..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponent.h +++ /dev/null @@ -1,38 +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 - { - class PointLightComponent final - : public AzFramework::Components::ComponentAdapter - { - public: - - using BaseClass = AzFramework::Components::ComponentAdapter; - AZ_COMPONENT(AZ::Render::PointLightComponent, PointLightComponentTypeId, BaseClass); - - PointLightComponent() = default; - PointLightComponent(const PointLightComponentConfig& config); - - static void Reflect(AZ::ReflectContext* context); - }; - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.cpp deleted file mode 100644 index 419ce2d5d2..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.cpp +++ /dev/null @@ -1,286 +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 - -#include -#include -#include - -#include - -namespace AZ -{ - namespace Render - { - void PointLightComponentConfig::Reflect(ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(2) - ->Field("Color", &PointLightComponentConfig::m_color) - ->Field("ColorIntensityMode", &PointLightComponentConfig::m_intensityMode) - ->Field("Intensity", &PointLightComponentConfig::m_intensity) - ->Field("AttenuationRadiusMode", &PointLightComponentConfig::m_attenuationRadiusMode) - ->Field("AttenuationRadius", &PointLightComponentConfig::m_attenuationRadius) - ->Field("BulbRadius", &PointLightComponentConfig::m_bulbRadius) - ; - } - } - - void PointLightComponentController::Reflect(ReflectContext* context) - { - PointLightComponentConfig::Reflect(context); - - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Configuration", &PointLightComponentController::m_configuration); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("PointLightRequestBus") - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Event("GetAttenuationRadius", &PointLightRequestBus::Events::GetAttenuationRadius) - ->Event("SetAttenuationRadius", &PointLightRequestBus::Events::SetAttenuationRadius) - ->Event("GetAttenuationRadiusIsAutomatic", &PointLightRequestBus::Events::GetAttenuationRadiusIsAutomatic) - ->Event("SetAttenuationRadiusIsAutomatic", &PointLightRequestBus::Events::SetAttenuationRadiusIsAutomatic) - ->Event("GetBulbRadius", &PointLightRequestBus::Events::GetBulbRadius) - ->Event("SetBulbRadius", &PointLightRequestBus::Events::SetBulbRadius) - ->Event("GetColor", &PointLightRequestBus::Events::GetColor) - ->Event("SetColor", &PointLightRequestBus::Events::SetColor) - ->Event("GetIntensity", &PointLightRequestBus::Events::GetIntensity) - ->Event("SetIntensity", static_cast(&PointLightRequestBus::Events::SetIntensity)) - ->Event("GetIntensityMode", &PointLightRequestBus::Events::GetIntensityMode) - ->Event("ConvertToIntensityMode", &PointLightRequestBus::Events::ConvertToIntensityMode) - ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") - ->VirtualProperty("AttenuationRadiusIsAutomatic", "GetAttenuationRadiusIsAutomatic", "SetAttenuationRadiusIsAutomatic") - ->VirtualProperty("BulbRadius", "GetBulbRadius", "SetBulbRadius") - ->VirtualProperty("Color", "GetColor", "SetColor") - ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") - ; - } - } - - void PointLightComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("PointLightService", 0x951d2403)); - } - - void PointLightComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("PointLightService", 0x951d2403)); - } - - PointLightComponentController::PointLightComponentController(const PointLightComponentConfig& config) - : m_configuration(config) - { - } - - void PointLightComponentController::Activate(EntityId entityId) - { - m_entityId = entityId; - m_featureProcessor = RPI::Scene::GetFeatureProcessorForEntity(entityId); - AZ_Error("PointLightComponentController", m_featureProcessor, "Could not find a PointLightFeatureProcessorInterface on the scene."); - - if (m_featureProcessor) - { - m_lightHandle = m_featureProcessor->AcquireLight(); - - AZ::Vector3 position = Vector3::CreateZero(); - AZ::TransformBus::EventResult(position, entityId, &AZ::TransformBus::Events::GetWorldTranslation); - m_featureProcessor->SetPosition(m_lightHandle, position); - - AZ::Vector3 scale = AZ::Vector3::CreateOne(); - AZ::TransformBus::EventResult(scale, entityId, &AZ::TransformBus::Events::GetWorldScale); - m_configuration.m_scale = scale.GetMaxElement(); - - TransformNotificationBus::Handler::BusConnect(m_entityId); - PointLightRequestBus::Handler::BusConnect(m_entityId); - ConfigurationChanged(); - } - } - - void PointLightComponentController::Deactivate() - { - PointLightRequestBus::Handler::BusDisconnect(m_entityId); - TransformNotificationBus::Handler::BusDisconnect(m_entityId); - - if (m_featureProcessor) - { - m_featureProcessor->ReleaseLight(m_lightHandle); - } - m_entityId.SetInvalid(); - } - - void PointLightComponentController::SetConfiguration(const PointLightComponentConfig& config) - { - m_configuration = config; - ConfigurationChanged(); - } - - const PointLightComponentConfig& PointLightComponentController::GetConfiguration() const - { - return m_configuration; - } - - void PointLightComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_featureProcessor->SetPosition(m_lightHandle, world.GetTranslation()); - if (m_configuration.m_scale != world.GetScale().GetMaxElement()) - { - m_configuration.UpdateScale(world.GetScale().GetMaxElement()); - BulbRadiusChanged(); - ColorIntensityChanged(); - } - } - - void PointLightComponentController::ConfigurationChanged() - { - m_configuration.UpdateUnscaledIntensity(); - m_configuration.UpdateUnscaledBulbRadius(); - - m_photometricValue = PhotometricValue(m_configuration.m_intensity, m_configuration.m_color, m_configuration.m_intensityMode); - m_photometricValue.SetArea(m_configuration.GetArea()); - - ColorIntensityChanged(); - AttenuationRadiusChanged(); - BulbRadiusChanged(); - } - - void PointLightComponentController::ColorIntensityChanged() - { - PointLightNotificationBus::Event(m_entityId, &PointLightNotifications::OnColorOrIntensityChanged, m_configuration.m_color, m_configuration.m_intensity); - - m_photometricValue.SetChroma(m_configuration.m_color); - m_photometricValue.SetIntensity(m_configuration.m_intensity); - m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb()); - } - - void PointLightComponentController::AttenuationRadiusChanged() - { - if (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) - { - AutoCalculateAttenuationRadius(); - } - PointLightNotificationBus::Event(m_entityId, &PointLightNotifications::OnAttenutationRadiusChanged, m_configuration.m_attenuationRadius); - m_featureProcessor->SetAttenuationRadius(m_lightHandle, m_configuration.m_attenuationRadius); - } - - void PointLightComponentController::BulbRadiusChanged() - { - m_photometricValue.SetArea(m_configuration.GetArea()); - PointLightNotificationBus::Event(m_entityId, &PointLightNotifications::OnBulbRadiusChanged, m_configuration.m_bulbRadius); - m_featureProcessor->SetBulbRadius(m_lightHandle, m_configuration.m_bulbRadius); - } - - void PointLightComponentController::AutoCalculateAttenuationRadius() - { - // Get combined intensity luma from m_photometricValue, then calculate the radius at which the irradiance will be equal to cutoffIntensity. - static const float CutoffIntensity = 0.1f; // Make this configurable later. - - float intensity = m_photometricValue.GetCombinedIntensity(PhotometricUnit::Lumen); - m_configuration.m_attenuationRadius = sqrt(intensity / CutoffIntensity); - } - - const Color& PointLightComponentController::GetColor() const - { - return m_configuration.m_color; - } - - void PointLightComponentController::SetColor(const Color& color) - { - m_configuration.m_color = color; - - PointLightNotificationBus::Event(m_entityId, &PointLightNotifications::OnColorChanged, color); - ColorIntensityChanged(); - } - - float PointLightComponentController::GetIntensity() const - { - return m_configuration.m_intensity; - } - - void PointLightComponentController::SetIntensity(float intensity) - { - m_configuration.m_intensity = intensity; - m_configuration.UpdateUnscaledIntensity(); - - PointLightNotificationBus::Event(m_entityId, &PointLightNotifications::OnIntensityChanged, intensity); - ColorIntensityChanged(); - } - - void PointLightComponentController::SetIntensity(float intensity, PhotometricUnit intensityMode) - { - m_configuration.m_intensityMode = intensityMode; - SetIntensity(intensity); - } - - PhotometricUnit PointLightComponentController::GetIntensityMode() const - { - return m_configuration.m_intensityMode; - } - - void PointLightComponentController::ConvertToIntensityMode(PhotometricUnit intensityMode) - { - if (m_configuration.m_intensityMode != intensityMode) - { - m_configuration.m_intensityMode = intensityMode; - m_photometricValue.ConvertToPhotometricUnit(intensityMode); - m_configuration.m_intensity = m_photometricValue.GetIntensity(); - m_configuration.UpdateUnscaledIntensity(); - } - } - - float PointLightComponentController::GetAttenuationRadius() const - { - return m_configuration.m_attenuationRadius; - } - - void PointLightComponentController::SetAttenuationRadius(float radius) - { - m_configuration.m_attenuationRadius = radius; - AttenuationRadiusChanged(); - } - - float PointLightComponentController::GetBulbRadius() const - { - return m_configuration.m_bulbRadius; - } - - void PointLightComponentController::SetBulbRadius(float bulbRadius) - { - m_configuration.m_bulbRadius = bulbRadius; - m_configuration.UpdateUnscaledBulbRadius(); - BulbRadiusChanged(); - } - - bool PointLightComponentController::GetAttenuationRadiusIsAutomatic() const - { - return (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic); - } - - void PointLightComponentController::SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) - { - m_configuration.m_attenuationRadiusMode = attenuationRadiusMode; - if (attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) - { - AutoCalculateAttenuationRadius(); - } - } - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.h deleted file mode 100644 index f249fd4595..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/PointLightComponentController.h +++ /dev/null @@ -1,87 +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 - -#include -#include - -#include -#include - -namespace AZ -{ - namespace Render - { - class PointLightComponentController final - : private TransformNotificationBus::Handler - , public PointLightRequestBus::Handler - { - public: - friend class EditorPointLightComponent; - - AZ_TYPE_INFO(AZ::Render::PointLightComponentController, "{23F82E30-2E1F-45FE-A9A7-B15632ED9EBD}"); - static void Reflect(AZ::ReflectContext* context); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - PointLightComponentController() = default; - PointLightComponentController(const PointLightComponentConfig& config); - - void Activate(EntityId entityId); - void Deactivate(); - void SetConfiguration(const PointLightComponentConfig& config); - const PointLightComponentConfig& GetConfiguration() const; - - private: - - AZ_DISABLE_COPY(PointLightComponentController); - - // TransformNotificationBus::Handler overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // PointLightRequestBus::Handler overrides ... - const Color& GetColor() const override; - void SetColor(const Color& color) override; - float GetIntensity() const override; - PhotometricUnit GetIntensityMode() const override; - void SetIntensity(float intensity) override; - void SetIntensity(float intensity, PhotometricUnit intensityMode) override; - - float GetAttenuationRadius() const override; - void SetAttenuationRadius(float radius) override; - bool GetAttenuationRadiusIsAutomatic() const override; - void SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) override; - float GetBulbRadius() const override; - void SetBulbRadius(float bulbRadius) override; - void ConvertToIntensityMode(PhotometricUnit intensityMode) override; - - void ConfigurationChanged(); - void ColorIntensityChanged(); - void AttenuationRadiusChanged(); - void BulbRadiusChanged(); - - void AutoCalculateAttenuationRadius(); - - PointLightComponentConfig m_configuration; - PhotometricValue m_photometricValue; - PointLightFeatureProcessorInterface* m_featureProcessor = nullptr; - PointLightFeatureProcessorInterface::LightHandle m_lightHandle; - EntityId m_entityId; - }; - - } // namespace Render -} // AZ namespace diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp new file mode 100644 index 0000000000..a2a24c3055 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.cpp @@ -0,0 +1,56 @@ +/* +* 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 + +namespace AZ +{ + namespace Render + { + SimplePointLightDelegate::SimplePointLightDelegate(EntityId entityId, bool isVisible) + : LightDelegateBase(entityId, isVisible) + { + InitBase(entityId); + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + } + float SimplePointLightDelegate::CalculateAttenuationRadius(float lightThreshold) const + { + // Calculate the radius at which the irradiance will be equal to cutoffIntensity. + float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); + return sqrt(intensity / lightThreshold); + } + + float SimplePointLightDelegate::GetSurfaceArea() const + { + return 0.0f; + } + + void SimplePointLightDelegate::HandleShapeChanged() + { + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + } + + void SimplePointLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + { + if (isSelected) + { + debugDisplay.SetColor(color); + + // Draw a sphere for the attenuation radius + debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity)); + } + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h new file mode 100644 index 0000000000..57f8539d84 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.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 + +#include +#include + +#include +#include + +namespace AZ +{ + namespace Render + { + class SimplePointLightDelegate final + : public LightDelegateBase + { + public: + SimplePointLightDelegate(EntityId entityId, bool isVisible); + + // LightDelegateBase overrides... + float CalculateAttenuationRadius(float lightThreshold) const override; + void DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const override; + float GetSurfaceArea() const override; + float GetEffectiveSolidAngle() const override { return PhotometricValue::OmnidirectionalSteradians; } + + private: + virtual void HandleShapeChanged(); + + }; + + } // namespace Render +} // namespace AZ + diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp new file mode 100644 index 0000000000..255f527557 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp @@ -0,0 +1,58 @@ +/* +* 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 + +namespace AZ::Render +{ + SimpleSpotLightDelegate::SimpleSpotLightDelegate(EntityId entityId, bool isVisible) + : LightDelegateBase(entityId, isVisible) + { + InitBase(entityId); + } + + void SimpleSpotLightDelegate::HandleShapeChanged() + { + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + GetFeatureProcessor()->SetDirection(GetLightHandle(), GetTransform().GetBasisZ()); + } + + float SimpleSpotLightDelegate::CalculateAttenuationRadius(float lightThreshold) const + { + // Calculate the radius at which the irradiance will be equal to cutoffIntensity. + float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); + return sqrt(intensity / lightThreshold); + } + + float SimpleSpotLightDelegate::GetSurfaceArea() const + { + return 0.0f; + } + + void SimpleSpotLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) + { + GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); + } + + void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + { + if (isSelected) + { + debugDisplay.SetColor(color); + + // Draw a cone for the cone angle and attenuation radius + debugDisplay.DrawCone(transform.GetTranslation(), transform.GetBasisX(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity), false); + } + } +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h new file mode 100644 index 0000000000..66569fc27c --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.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 + +#include +#include + +#include +#include + +namespace AZ +{ + namespace Render + { + class SimpleSpotLightDelegate final + : public LightDelegateBase + { + public: + SimpleSpotLightDelegate(EntityId entityId, bool isVisible); + + // LightDelegateBase overrides... + float CalculateAttenuationRadius(float lightThreshold) const override; + void DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const override; + float GetSurfaceArea() const override; + float GetEffectiveSolidAngle() const override { return PhotometricValue::DirectionalEffectiveSteradians; } + void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; + private: + virtual void HandleShapeChanged(); + + }; + + } // namespace Render +} // namespace AZ + diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.cpp deleted file mode 100644 index 812ba53f3f..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.cpp +++ /dev/null @@ -1,44 +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 - -namespace AZ -{ - namespace Render - { - - SpotLightComponent::SpotLightComponent(const SpotLightComponentConfig& config) - : BaseClass(config) - { - } - - void SpotLightComponent::Reflect(AZ::ReflectContext* context) - { - BaseClass::Reflect(context); - - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class(); - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("SpotLightRequestBus"); - - behaviorContext->ConstantProperty("SpotLightComponentTypeId", BehaviorConstant(Uuid(SpotLightComponentTypeId))) - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common); - } - } - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.h deleted file mode 100644 index cf4f93ba02..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponent.h +++ /dev/null @@ -1,37 +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 - { - class SpotLightComponent final - : public AzFramework::Components::ComponentAdapter - { - public: - - using BaseClass = AzFramework::Components::ComponentAdapter; - AZ_COMPONENT(AZ::Render::SpotLightComponent, SpotLightComponentTypeId, BaseClass); - - SpotLightComponent() = default; - SpotLightComponent(const SpotLightComponentConfig& config); - - static void Reflect(AZ::ReflectContext* context); - }; - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentConfig.cpp deleted file mode 100644 index c68b505c57..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentConfig.cpp +++ /dev/null @@ -1,83 +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 -#include -#include - -namespace AZ -{ - namespace Render - { - void SpotLightComponentConfig::Reflect(ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(4) - ->Field("Color", &SpotLightComponentConfig::m_color) - ->Field("Intensity", &SpotLightComponentConfig::m_intensity) - ->Field("IntensityMode", &SpotLightComponentConfig::m_intensityMode) - ->Field("Bulb Radius", &SpotLightComponentConfig::m_bulbRadius) - ->Field("Inner Cone Angle", &SpotLightComponentConfig::m_innerConeDegrees) - ->Field("Outer Cone Angle", &SpotLightComponentConfig::m_outerConeDegrees) - ->Field("Attenuation Radius", &SpotLightComponentConfig::m_attenuationRadius) - ->Field("Attenuation Radius Mode", &SpotLightComponentConfig::m_attenuationRadiusMode) - ->Field("Penumbra Bias", &SpotLightComponentConfig::m_penumbraBias) - ->Field("Enabled Shadow", &SpotLightComponentConfig::m_enabledShadow) - ->Field("Shadowmap Size", &SpotLightComponentConfig::m_shadowmapSize) - ->Field("Shadow Filter Method", &SpotLightComponentConfig::m_shadowFilterMethod) - ->Field("Softening Boundary Width", &SpotLightComponentConfig::m_boundaryWidthInDegrees) - ->Field("Prediction Sample Count", &SpotLightComponentConfig::m_predictionSampleCount) - ->Field("Filtering Sample Count", &SpotLightComponentConfig::m_filteringSampleCount) - ->Field("Pcf Method", &SpotLightComponentConfig::m_pcfMethod); - } - } - - bool SpotLightComponentConfig::IsAttenuationRadiusModeAutomatic() const - { - return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic; - } - - const char* SpotLightComponentConfig::GetIntensitySuffix() const - { - return PhotometricValue::GetTypeSuffix(m_intensityMode); - } - - float SpotLightComponentConfig::GetConeDegrees() const - { - return (m_enabledShadow && m_shadowmapSize != ShadowmapSize::None) ? MaxSpotLightConeAngleDegreeWithShadow : MaxSpotLightConeAngleDegree; - } - - bool SpotLightComponentConfig::IsShadowFilteringDisabled() const - { - return (m_shadowFilterMethod == ShadowFilterMethod::None); - } - - bool SpotLightComponentConfig::IsShadowPcfDisabled() const - { - return !(m_shadowFilterMethod == ShadowFilterMethod::Pcf || - m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); - } - - bool SpotLightComponentConfig::IsPcfBoundarySearchDisabled() const - { - if (IsShadowPcfDisabled()) - { - return true; - } - - return m_pcfMethod != PcfMethod::BoundarySearch; - } - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.cpp deleted file mode 100644 index 42230bbf3e..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.cpp +++ /dev/null @@ -1,434 +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 - -#include -#include - -#include - -namespace AZ -{ - namespace Render - { - void SpotLightComponentController::Reflect(ReflectContext* context) - { - SpotLightComponentConfig::Reflect(context); - - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(3) - ->Field("Configuration", &SpotLightComponentController::m_configuration); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext - ->Enum(ShadowFilterMethod::None)>("ShadowFilterMethod_None") - ->Enum(ShadowFilterMethod::Pcf)>("ShadowFilterMethod_PCF") - ->Enum(ShadowFilterMethod::Esm)>("ShadowFilterMethod_ESM") - ->Enum(ShadowFilterMethod::EsmPcf)>("ShadowFilterMethod_ESM_PCF") - ->Enum(ShadowmapSize::None)>("ShadowmapSize_None") - ->Enum(ShadowmapSize::Size256)>("ShadowmapSize_256") - ->Enum(ShadowmapSize::Size512)>("ShadowmapSize_512") - ->Enum(ShadowmapSize::Size1024)>("ShadowmapSize_1024") - ->Enum(ShadowmapSize::Size2048)>("ShadowmapSize_2045") - ; - - behaviorContext->EBus("SpotLightRequestBus") - ->Attribute(AZ::Script::Attributes::Module, "render") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Event("GetAttenuationRadius", &SpotLightRequestBus::Events::GetAttenuationRadius) - ->Event("SetAttenuationRadius", &SpotLightRequestBus::Events::SetAttenuationRadius) - ->Event("GetAttenuationRadiusIsAutomatic", &SpotLightRequestBus::Events::GetAttenuationRadiusIsAutomatic) - ->Event("SetAttenuationRadiusIsAutomatic", &SpotLightRequestBus::Events::SetAttenuationRadiusIsAutomatic) - ->Event("GetColor", &SpotLightRequestBus::Events::GetColor) - ->Event("SetColor", &SpotLightRequestBus::Events::SetColor) - ->Event("GetIntensity", &SpotLightRequestBus::Events::GetIntensity) - ->Event("SetIntensity", &SpotLightRequestBus::Events::SetIntensity) - ->Event("GetBulbRadius", &SpotLightRequestBus::Events::GetBulbRadius) - ->Event("SetBulbRadius", &SpotLightRequestBus::Events::SetBulbRadius) - ->Event("GetInnerConeAngleInDegrees", &SpotLightRequestBus::Events::GetInnerConeAngleInDegrees) - ->Event("SetInnerConeAngleInDegrees", &SpotLightRequestBus::Events::SetInnerConeAngleInDegrees) - ->Event("GetOuterConeAngleInDegrees", &SpotLightRequestBus::Events::GetOuterConeAngleInDegrees) - ->Event("SetOuterConeAngleInDegrees", &SpotLightRequestBus::Events::SetOuterConeAngleInDegrees) - ->Event("GetPenumbraBias", &SpotLightRequestBus::Events::GetPenumbraBias) - ->Event("SetPenumbraBias", &SpotLightRequestBus::Events::SetPenumbraBias) - ->Event("GetEnableShadow", &SpotLightRequestBus::Events::GetEnableShadow) - ->Event("SetEnableShadow", &SpotLightRequestBus::Events::SetEnableShadow) - ->Event("GetShadowmapSize", &SpotLightRequestBus::Events::GetShadowmapSize) - ->Event("SetShadowmapSize", &SpotLightRequestBus::Events::SetShadowmapSize) - ->Event("GetShadowFilterMethod", &SpotLightRequestBus::Events::GetShadowFilterMethod) - ->Event("SetShadowFilterMethod", &SpotLightRequestBus::Events::SetShadowFilterMethod) - ->Event("GetSofteningBoundaryWidthAngle", &SpotLightRequestBus::Events::GetSofteningBoundaryWidthAngle) - ->Event("SetSofteningBoundaryWidthAngle", &SpotLightRequestBus::Events::SetSofteningBoundaryWidthAngle) - ->Event("GetPredictionSampleCount", &SpotLightRequestBus::Events::GetPredictionSampleCount) - ->Event("SetPredictionSampleCount", &SpotLightRequestBus::Events::SetPredictionSampleCount) - ->Event("GetFilteringSampleCount", &SpotLightRequestBus::Events::GetFilteringSampleCount) - ->Event("SetFilteringSampleCount", &SpotLightRequestBus::Events::SetFilteringSampleCount) - ->Event("GetPcfMethod", &SpotLightRequestBus::Events::GetPcfMethod) - ->Event("SetPcfMethod", &SpotLightRequestBus::Events::SetPcfMethod) - ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") - ->VirtualProperty("AttenuationRadiusIsAutomatic", "GetAttenuationRadiusIsAutomatic", "SetAttenuationRadiusIsAutomatic") - ->VirtualProperty("Color", "GetColor", "SetColor") - ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") - ->VirtualProperty("InnerConeAngleInDegrees", "GetInnerConeAngleInDegrees", "SetInnerConeAngleInDegrees") - ->VirtualProperty("OuterConeAngleInDegrees", "GetOuterConeAngleInDegrees", "SetOuterConeAngleInDegrees") - ->VirtualProperty("PenumbraBias", "GetPenumbraBias", "SetPenumbraBias") - ->VirtualProperty("EnableShadow", "GetEnableShadow", "SetEnableShadow") - ->VirtualProperty("ShadowmapSize", "GetShadowmapSize", "SetShadowmapSize") - ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") - ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") - ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") - ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); - } - } - - void SpotLightComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("SpotLightService", 0x3ae7d498)); - } - - void SpotLightComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("SpotLightService", 0x3ae7d498)); - } - - SpotLightComponentController::SpotLightComponentController(const SpotLightComponentConfig& config) - : m_configuration(config) - { - } - - void SpotLightComponentController::Activate(EntityId entityId) - { - m_entityId = entityId; - m_featureProcessor = RPI::Scene::GetFeatureProcessorForEntity(entityId); - AZ_Error("SpotLightComponentController", m_featureProcessor, "Could not find a SpotLightFeatureProcessorInterface on the scene."); - - if (m_featureProcessor) - { - m_lightHandle = m_featureProcessor->AcquireLight(); - - TransformNotificationBus::Handler::BusConnect(m_entityId); - SpotLightRequestBus::Handler::BusConnect(m_entityId); - ConfigurationChanged(); - } - } - - void SpotLightComponentController::Deactivate() - { - SpotLightRequestBus::Handler::BusDisconnect(m_entityId); - TransformNotificationBus::Handler::BusDisconnect(m_entityId); - - if (m_featureProcessor) - { - m_featureProcessor->ReleaseLight(m_lightHandle); - } - m_entityId.SetInvalid(); - } - - void SpotLightComponentController::SetConfiguration(const SpotLightComponentConfig& config) - { - m_configuration = config; - ConfigurationChanged(); - } - - const SpotLightComponentConfig& SpotLightComponentController::GetConfiguration() const - { - return m_configuration; - } - - void SpotLightComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_featureProcessor->SetPosition(m_lightHandle, world.GetTranslation()); - - const Vector3 forward = Vector3::CreateAxisY(); - const Vector3 lightDirection = world.TransformVector(forward); - m_featureProcessor->SetDirection(m_lightHandle, lightDirection); - } - - void SpotLightComponentController::ConfigurationChanged() - { - m_photometricValue = PhotometricValue(m_configuration.m_intensity, m_configuration.m_color, m_configuration.m_intensityMode); - m_photometricValue.SetEffectiveSolidAngle(PhotometricValue::DirectionalEffectiveSteradians); - - AZ::Transform worldTM; - AZ::TransformBus::EventResult(worldTM, m_entityId, &AZ::TransformBus::Events::GetWorldTM); - OnTransformChanged({}, worldTM); - - ColorIntensityChanged(); - AttenuationRadiusChanged(); - ConeAnglesChanged(); - PenumbraBiasChanged(); - SetBulbRadius(m_configuration.m_bulbRadius); - SetEnableShadow(m_configuration.m_enabledShadow); - SetShadowmapSize(m_configuration.m_shadowmapSize); - SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); - SetSofteningBoundaryWidthAngle(m_configuration.m_boundaryWidthInDegrees); - SetPredictionSampleCount(m_configuration.m_predictionSampleCount); - SetFilteringSampleCount(m_configuration.m_filteringSampleCount); - SetPcfMethod(m_configuration.m_pcfMethod); - } - - void SpotLightComponentController::ColorIntensityChanged() - { - SpotLightNotificationBus::Event(m_entityId, &SpotLightNotifications::OnIntensityChanged, m_configuration.m_intensity); - SpotLightNotificationBus::Event(m_entityId, &SpotLightNotifications::OnColorChanged, m_configuration.m_color); - - m_photometricValue.SetChroma(m_configuration.m_color); - m_photometricValue.SetIntensity(m_configuration.m_intensity); - m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb()); - } - - void SpotLightComponentController::ConeAnglesChanged() - { - if (m_configuration.m_innerConeDegrees > m_configuration.m_outerConeDegrees) - { - m_configuration.m_innerConeDegrees = m_configuration.m_outerConeDegrees; - } - - SpotLightNotificationBus::Event(m_entityId, &SpotLightNotifications::OnConeAnglesChanged, m_configuration.m_innerConeDegrees, m_configuration.m_outerConeDegrees); - m_featureProcessor->SetConeAngles(m_lightHandle, m_configuration.m_innerConeDegrees, m_configuration.m_outerConeDegrees); - } - - void SpotLightComponentController::AttenuationRadiusChanged() - { - if (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) - { - AutoCalculateAttenuationRadius(); - } - - SpotLightNotificationBus::Event(m_entityId, &SpotLightNotifications::OnAttenuationRadiusChanged, m_configuration.m_attenuationRadius); - m_featureProcessor->SetAttenuationRadius(m_lightHandle, m_configuration.m_attenuationRadius); - } - - void SpotLightComponentController::PenumbraBiasChanged() - { - SpotLightNotificationBus::Event(m_entityId, &SpotLightNotifications::OnPenumbraBiasChanged, m_configuration.m_penumbraBias); - m_featureProcessor->SetPenumbraBias(m_lightHandle, m_configuration.m_penumbraBias); - } - - void SpotLightComponentController::AutoCalculateAttenuationRadius() - { - // Get combined intensity luma from m_photometricValue, then calculate the radius at which the irradiance will be equal to cutoffIntensity. - static const float CutoffIntensity = 0.1f; // Make this configurable later. - - float intensity = m_photometricValue.GetCombinedIntensity(PhotometricUnit::Lumen); - m_configuration.m_attenuationRadius = sqrt(intensity / CutoffIntensity); - } - - const Color& SpotLightComponentController::GetColor() const - { - return m_configuration.m_color; - } - - void SpotLightComponentController::SetColor(const Color& color) - { - m_configuration.m_color = color; - ColorIntensityChanged(); - } - - float SpotLightComponentController::GetIntensity() const - { - return m_configuration.m_intensity; - } - - void SpotLightComponentController::SetIntensity(float intensity) - { - m_configuration.m_intensity = intensity; - ColorIntensityChanged(); - } - - float SpotLightComponentController::GetBulbRadius() const - { - return m_configuration.m_bulbRadius; - } - - void SpotLightComponentController::SetBulbRadius(float bulbRadius) - { - m_configuration.m_bulbRadius = bulbRadius; - m_featureProcessor->SetBulbRadius(m_lightHandle, bulbRadius); - } - - float SpotLightComponentController::GetInnerConeAngleInDegrees() const - { - return m_configuration.m_innerConeDegrees; - } - - void SpotLightComponentController::SetInnerConeAngleInDegrees(float degrees) - { - m_configuration.m_innerConeDegrees = degrees; - ConeAnglesChanged(); - } - - float SpotLightComponentController::GetOuterConeAngleInDegrees() const - { - return m_configuration.m_outerConeDegrees; - } - - void SpotLightComponentController::SetOuterConeAngleInDegrees(float degrees) - { - m_configuration.m_outerConeDegrees = degrees; - ConeAnglesChanged(); - } - - float SpotLightComponentController::GetPenumbraBias() const - { - return m_configuration.m_penumbraBias; - } - - void SpotLightComponentController::SetPenumbraBias(float penumbraBias) - { - m_configuration.m_penumbraBias = penumbraBias; - PenumbraBiasChanged(); - } - - float SpotLightComponentController::GetAttenuationRadius() const - { - return m_configuration.m_attenuationRadius; - } - - void SpotLightComponentController::SetAttenuationRadius(float radius) - { - m_configuration.m_attenuationRadius = radius; - AttenuationRadiusChanged(); - } - - LightAttenuationRadiusMode SpotLightComponentController::GetAttenuationRadiusMode() const - { - return m_configuration.m_attenuationRadiusMode; - } - - void SpotLightComponentController::SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) - { - m_configuration.m_attenuationRadiusMode = attenuationRadiusMode; - if (attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) - { - AutoCalculateAttenuationRadius(); - } - } - - bool SpotLightComponentController::GetEnableShadow() const - { - return m_configuration.m_enabledShadow; - } - - void SpotLightComponentController::SetEnableShadow(bool enabled) - { - m_configuration.m_enabledShadow = enabled; - - m_featureProcessor->SetShadowmapSize( - m_lightHandle, - m_configuration.m_enabledShadow ? - m_configuration.m_shadowmapSize : - ShadowmapSize::None); - } - - ShadowmapSize SpotLightComponentController::GetShadowmapSize() const - { - return m_configuration.m_shadowmapSize; - } - - void SpotLightComponentController::SetShadowmapSize(ShadowmapSize size) - { - // The minimum valid ShadowmapSize is 256 and maximum one is 2048. - const uint32_t sizeInt = aznumeric_cast(size); - if (sizeInt < aznumeric_cast(ShadowmapSize::Size512)) - { - size = ShadowmapSize::Size256; - } - else if (sizeInt < aznumeric_cast(ShadowmapSize::Size1024)) - { - size = ShadowmapSize::Size512; - } - else if (sizeInt < aznumeric_cast(ShadowmapSize::Size2048)) - { - size = ShadowmapSize::Size1024; - } - else - { - size = ShadowmapSize::Size2048; - } - - m_configuration.m_shadowmapSize = size; - m_featureProcessor->SetShadowmapSize( - m_lightHandle, - m_configuration.m_enabledShadow ? - m_configuration.m_shadowmapSize : - ShadowmapSize::None); - } - - ShadowFilterMethod SpotLightComponentController::GetShadowFilterMethod() const - { - return m_configuration.m_shadowFilterMethod; - } - - void SpotLightComponentController::SetShadowFilterMethod(ShadowFilterMethod method) - { - m_configuration.m_shadowFilterMethod = method; - - m_featureProcessor->SetShadowFilterMethod(m_lightHandle, method); - } - - float SpotLightComponentController::GetSofteningBoundaryWidthAngle() const - { - return m_configuration.m_boundaryWidthInDegrees; - } - - void SpotLightComponentController::SetSofteningBoundaryWidthAngle(float width) - { - m_configuration.m_boundaryWidthInDegrees = width; - - m_featureProcessor->SetShadowBoundaryWidthAngle(m_lightHandle, width); - } - - uint32_t SpotLightComponentController::GetPredictionSampleCount() const - { - return m_configuration.m_predictionSampleCount; - } - - void SpotLightComponentController::SetPredictionSampleCount(uint32_t count) - { - m_configuration.m_predictionSampleCount = count; - - m_featureProcessor->SetPredictionSampleCount(m_lightHandle, count); - } - - uint32_t SpotLightComponentController::GetFilteringSampleCount() const - { - return m_configuration.m_filteringSampleCount; - } - - void SpotLightComponentController::SetFilteringSampleCount(uint32_t count) - { - m_configuration.m_filteringSampleCount = count; - - m_featureProcessor->SetFilteringSampleCount(m_lightHandle, count); - } - - PcfMethod SpotLightComponentController::GetPcfMethod() const - { - return m_configuration.m_pcfMethod; - } - - void SpotLightComponentController::SetPcfMethod(PcfMethod method) - { - m_configuration.m_pcfMethod = method; - m_featureProcessor->SetPcfMethod(m_lightHandle, method); - } - - - } // namespace Render -} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.h deleted file mode 100644 index 8cb124cddf..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SpotLightComponentController.h +++ /dev/null @@ -1,102 +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 - -#include -#include -#include - -namespace AZ -{ - namespace Render - { - class SpotLightComponentController final - : public TransformNotificationBus::Handler - , public SpotLightRequestBus::Handler - { - public: - friend class EditorSpotLightComponent; - - AZ_TYPE_INFO(AZ::Render::SpotLightComponentController, "{2B37DC8C-BE9E-481C-A53B-FCBFFAB425E0}"); - static void Reflect(AZ::ReflectContext* context); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - SpotLightComponentController() = default; - SpotLightComponentController(const SpotLightComponentConfig& config); - - void Activate(EntityId entityId); - void Deactivate(); - void SetConfiguration(const SpotLightComponentConfig& config); - const SpotLightComponentConfig& GetConfiguration() const; - - private: - - AZ_DISABLE_COPY(SpotLightComponentController); - - // TransformNotificationBus::Handler overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // SpotLightRequestBus::Handler overrides ... - const Color& GetColor() const override; - void SetColor(const Color& color) override; - float GetIntensity() const override; - void SetIntensity(float intensity) override; - float GetBulbRadius() const override; - void SetBulbRadius(float bulbRadius) override; - float GetInnerConeAngleInDegrees() const override; - void SetInnerConeAngleInDegrees(float degrees) override; - float GetOuterConeAngleInDegrees() const override; - void SetOuterConeAngleInDegrees(float degrees) override; - float GetPenumbraBias() const override; - void SetPenumbraBias(float penumbraBias) override; - float GetAttenuationRadius() const override; - void SetAttenuationRadius(float radius) override; - LightAttenuationRadiusMode GetAttenuationRadiusMode() const override; - void SetAttenuationRadiusMode(LightAttenuationRadiusMode attenuationRadiusMode) override; - bool GetEnableShadow() const override; - void SetEnableShadow(bool enabled) override; - ShadowmapSize GetShadowmapSize() const override; - void SetShadowmapSize(ShadowmapSize size) override; - ShadowFilterMethod GetShadowFilterMethod() const override; - void SetShadowFilterMethod(ShadowFilterMethod method) override; - float GetSofteningBoundaryWidthAngle() const override; - void SetSofteningBoundaryWidthAngle(float width) override; - uint32_t GetPredictionSampleCount() const override; - void SetPredictionSampleCount(uint32_t count) override; - uint32_t GetFilteringSampleCount() const override; - void SetFilteringSampleCount(uint32_t count) override; - PcfMethod GetPcfMethod() const override; - void SetPcfMethod(PcfMethod method) override; - - void ConfigurationChanged(); - void ColorIntensityChanged(); - void ConeAnglesChanged(); - void AttenuationRadiusChanged(); - void PenumbraBiasChanged(); - - void AutoCalculateAttenuationRadius(); - - SpotLightComponentConfig m_configuration; - PhotometricValue m_photometricValue; - SpotLightFeatureProcessorInterface* m_featureProcessor = nullptr; - SpotLightFeatureProcessorInterface::LightHandle m_lightHandle; - EntityId m_entityId; - }; - - } // namespace Render -} // AZ namespace diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index 65a09db94c..b8d1b1df28 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -175,19 +175,19 @@ namespace AZ tableWidget->setCellWidget(row, OverwriteFileColumn, overwriteCheckBoxContainer); // Whenever the selection is updated, automatically apply the change to the export item - QObject::connect(materialSlotCheckBox, &QCheckBox::stateChanged, materialSlotCheckBox, [&]([[maybe_unused]] int state) { + QObject::connect(materialSlotCheckBox, &QCheckBox::stateChanged, materialSlotCheckBox, [&exportItem, materialFileWidget, materialSlotCheckBox, overwriteCheckBox]([[maybe_unused]] int state) { exportItem.m_enabled = materialSlotCheckBox->isChecked(); materialFileWidget->setEnabled(exportItem.m_enabled); overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists); }); // Whenever the overwrite check box is updated, automatically apply the change to the export item - QObject::connect(overwriteCheckBox, &QCheckBox::stateChanged, overwriteCheckBox, [&]([[maybe_unused]] int state) { + QObject::connect(overwriteCheckBox, &QCheckBox::stateChanged, overwriteCheckBox, [&exportItem, overwriteCheckBox]([[maybe_unused]] int state) { exportItem.m_overwrite = overwriteCheckBox->isChecked(); }); // Whenever the browse button is clicked, open a save file dialog in the same location as the current export file setting - QObject::connect(materialFileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, materialFileWidget, [&]() { + QObject::connect(materialFileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, materialFileWidget, [&dialog, &exportItem, materialFileWidget, overwriteCheckBox]() { QFileInfo fileInfo = QFileDialog::getSaveFileName(&dialog, QString("Select Material Filename"), exportItem.m_exportPath.c_str(), @@ -201,7 +201,7 @@ namespace AZ exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData(); exportItem.m_exists = fileInfo.exists(); exportItem.m_overwrite = fileInfo.exists(); -\ + // Update the controls to display the new state materialFileWidget->setText(fileInfo.fileName()); overwriteCheckBox->setChecked(exportItem.m_overwrite); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp index 4b125ca8e0..b33dd7f165 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include #include @@ -47,8 +45,6 @@ #include #include #include -#include -#include #include #include #include @@ -106,10 +102,8 @@ namespace AZ MaterialComponent::CreateDescriptor(), MeshComponent::CreateDescriptor(), PhysicalSkyComponent::CreateDescriptor(), - PointLightComponent::CreateDescriptor(), PostFxLayerComponent::CreateDescriptor(), ReflectionProbeComponent::CreateDescriptor(), - SpotLightComponent::CreateDescriptor(), RadiusWeightModifierComponent::CreateDescriptor(), ShapeWeightModifierComponent::CreateDescriptor(), EntityReferenceComponent::CreateDescriptor(), @@ -138,10 +132,8 @@ namespace AZ EditorMeshSystemComponent::CreateDescriptor(), EditorMeshComponent::CreateDescriptor(), EditorPhysicalSkyComponent::CreateDescriptor(), - EditorPointLightComponent::CreateDescriptor(), EditorPostFxLayerComponent::CreateDescriptor(), EditorReflectionProbeComponent::CreateDescriptor(), - EditorSpotLightComponent::CreateDescriptor(), EditorRadiusWeightModifierComponent::CreateDescriptor(), EditorShapeWeightModifierComponent::CreateDescriptor(), EditorEntityReferenceComponent::CreateDescriptor(), diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index 5db34a764b..f77b175cd7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -19,10 +19,6 @@ set(FILES Source/CoreLights/EditorAreaLightComponent.cpp Source/CoreLights/EditorDirectionalLightComponent.h Source/CoreLights/EditorDirectionalLightComponent.cpp - Source/CoreLights/EditorPointLightComponent.h - Source/CoreLights/EditorPointLightComponent.cpp - Source/CoreLights/EditorSpotLightComponent.h - Source/CoreLights/EditorSpotLightComponent.cpp Source/Decals/EditorDecalComponent.h Source/Decals/EditorDecalComponent.cpp Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.h diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake index 28d56ba5e5..b26ebc60a6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake @@ -27,21 +27,16 @@ set(FILES Source/CoreLights/LightDelegateBase.h Source/CoreLights/LightDelegateBase.inl Source/CoreLights/LightDelegateInterface.h - Source/CoreLights/PointLightComponent.h - Source/CoreLights/PointLightComponent.cpp - Source/CoreLights/PointLightComponentController.h - Source/CoreLights/PointLightComponentController.cpp Source/CoreLights/PolygonLightDelegate.h Source/CoreLights/PolygonLightDelegate.cpp Source/CoreLights/QuadLightDelegate.h Source/CoreLights/QuadLightDelegate.cpp + Source/CoreLights/SimplePointLightDelegate.h + Source/CoreLights/SimplePointLightDelegate.cpp + Source/CoreLights/SimpleSpotLightDelegate.h + Source/CoreLights/SimpleSpotLightDelegate.cpp Source/CoreLights/SphereLightDelegate.h Source/CoreLights/SphereLightDelegate.cpp - Source/CoreLights/SpotLightComponent.h - Source/CoreLights/SpotLightComponent.cpp - Source/CoreLights/SpotLightComponentConfig.cpp - Source/CoreLights/SpotLightComponentController.h - Source/CoreLights/SpotLightComponentController.cpp Source/Decals/DecalComponent.h Source/Decals/DecalComponent.cpp Source/Decals/DecalComponentController.h diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake index 06724fd506..7b8d0a6e21 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake @@ -15,10 +15,6 @@ set(FILES Include/AtomLyIntegration/CommonFeatures/CoreLights/CoreLightsConstants.h Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h - Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightBus.h - Include/AtomLyIntegration/CommonFeatures/CoreLights/PointLightComponentConfig.h - Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightBus.h - Include/AtomLyIntegration/CommonFeatures/CoreLights/SpotLightComponentConfig.h Include/AtomLyIntegration/CommonFeatures/Decals/DecalBus.h Include/AtomLyIntegration/CommonFeatures/Decals/DecalComponentConfig.h Include/AtomLyIntegration/CommonFeatures/Decals/DecalConstants.h diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt index d2a1e5abf0..dc969d61d3 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt @@ -17,8 +17,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore @@ -40,8 +38,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore @@ -58,8 +54,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index 9d1e4443dd..14a685a065 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -211,41 +211,44 @@ namespace AZ const uint32_t* sourceOriginalVertex = static_cast(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_ORGVTXNUMBERS)); const uint32_t vertexCount = subMesh->GetNumVertices(); const uint32_t vertexStart = subMesh->GetStartVertex(); - for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) + if (sourceSkinningInfo) { - const uint32_t originalVertex = sourceOriginalVertex[vertexIndex + vertexStart]; - const uint32_t influenceCount = AZStd::GetMin(MaxSupportedSkinInfluences, sourceSkinningInfo->GetNumInfluences(originalVertex)); - uint32_t influenceIndex = 0; - float weightError = 1.0f; - - AZStd::vector localIndices; - for (; influenceIndex < influenceCount; ++influenceIndex) + for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { - EMotionFX::SkinInfluence* influence = sourceSkinningInfo->GetInfluence(originalVertex, influenceIndex); - localIndices.push_back(static_cast(influence->GetNodeNr())); - blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex] = influence->GetWeight(); - weightError -= blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex]; - } + const uint32_t originalVertex = sourceOriginalVertex[vertexIndex + vertexStart]; + const uint32_t influenceCount = AZStd::GetMin(MaxSupportedSkinInfluences, sourceSkinningInfo->GetNumInfluences(originalVertex)); + uint32_t influenceIndex = 0; + float weightError = 1.0f; - // Zero out any unused ids/weights - for (; influenceIndex < MaxSupportedSkinInfluences; ++influenceIndex) - { - localIndices.push_back(0); - blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex] = 0.0f; - } - - // Now that we have the 16-bit indices, pack them into 32-bit uints - for (size_t i = 0; i < localIndices.size(); ++i) - { - if (i % 2 == 0) + AZStd::vector localIndices; + for (; influenceIndex < influenceCount; ++influenceIndex) { - // Put the first/even ids in the most significant bits - blendIndexBufferData[atomVertexBufferOffset + vertexIndex][i/2] = localIndices[i] << 16; + EMotionFX::SkinInfluence* influence = sourceSkinningInfo->GetInfluence(originalVertex, influenceIndex); + localIndices.push_back(static_cast(influence->GetNodeNr())); + blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex] = influence->GetWeight(); + weightError -= blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex]; } - else + + // Zero out any unused ids/weights + for (; influenceIndex < MaxSupportedSkinInfluences; ++influenceIndex) { - // Put the next/odd ids in the least significant bits - blendIndexBufferData[atomVertexBufferOffset + vertexIndex][i / 2] |= localIndices[i]; + localIndices.push_back(0); + blendWeightBufferData[atomVertexBufferOffset + vertexIndex][influenceIndex] = 0.0f; + } + + // Now that we have the 16-bit indices, pack them into 32-bit uints + for (size_t i = 0; i < localIndices.size(); ++i) + { + if (i % 2 == 0) + { + // Put the first/even ids in the most significant bits + blendIndexBufferData[atomVertexBufferOffset + vertexIndex][i / 2] = localIndices[i] << 16; + } + else + { + // Put the next/odd ids in the least significant bits + blendIndexBufferData[atomVertexBufferOffset + vertexIndex][i / 2] |= localIndices[i]; + } } } } @@ -268,7 +271,9 @@ namespace AZ // Static triangles are the ones that all its vertices won't move during simulation and // therefore its weights won't be altered so they are controlled by GPU. // This additional simplification has been disabled in ClothComponentMesh.cpp for now. - if (hasClothData) + + // If there is no skinning info, default to 0 weights and display an error + if (hasClothData || !sourceSkinningInfo) { for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { @@ -471,41 +476,44 @@ namespace AZ } // for all submeshes } // for all meshes - // Now that the data has been prepped, create the actual buffers + // Now that the data has been prepped, set the actual buffers + skinnedMeshLod.SetModelLodAsset(modelLodAsset); - // Create read-only buffers and views for input buffers that are shared across all instances + // Set read-only buffers and views for input buffers that are shared across all instances AZStd::string lodString = AZStd::string::format("_Lod%zu", lodIndex); skinnedMeshLod.SetSkinningInputBufferAsset(mesh0.GetSemanticBufferAssetView(Name{ "POSITION" })->GetBufferAsset(), SkinnedMeshInputVertexStreams::Position); skinnedMeshLod.SetSkinningInputBufferAsset(mesh0.GetSemanticBufferAssetView(Name{ "NORMAL" })->GetBufferAsset(), SkinnedMeshInputVertexStreams::Normal); skinnedMeshLod.SetSkinningInputBufferAsset(mesh0.GetSemanticBufferAssetView(Name{ "TANGENT" })->GetBufferAsset(), SkinnedMeshInputVertexStreams::Tangent); skinnedMeshLod.SetSkinningInputBufferAsset(mesh0.GetSemanticBufferAssetView(Name{ "BITANGENT" })->GetBufferAsset(), SkinnedMeshInputVertexStreams::BiTangent); - - Data::Asset jointIndicesBufferAsset = mesh0.GetSemanticBufferAssetView(Name{ "SKIN_JOINTINDICES" })->GetBufferAsset(); - skinnedMeshLod.SetSkinningInputBufferAsset(jointIndicesBufferAsset, SkinnedMeshInputVertexStreams::BlendIndices); - Data::Asset skinWeightsBufferAsset = mesh0.GetSemanticBufferAssetView(Name{ "SKIN_WEIGHTS" })->GetBufferAsset(); - skinnedMeshLod.SetSkinningInputBufferAsset(skinWeightsBufferAsset, SkinnedMeshInputVertexStreams::BlendWeights); - // We're using the indices/weights buffers directly from the model. - // However, EMFX has done some re-mapping of the id's, so we need to update the GPU buffer for it to have the correct data. - size_t remappedJointIndexBufferSizeInBytes = blendIndexBufferData.size() * sizeof(blendIndexBufferData[0]); - size_t remappedSkinWeightsBufferSizeInBytes = blendWeightBufferData.size() * sizeof(blendWeightBufferData[0]); + if (!mesh0.GetSemanticBufferAssetView(Name{ "SKIN_JOINTINDICES" }) || !mesh0.GetSemanticBufferAssetView(Name{ "SKIN_WEIGHTS" })) + { + AZ_Error("ProcessSkinInfluences", false, "Actor '%s' lod '%zu' has no skin influences, and will be stuck in bind pose.", fullFileName.c_str(), lodIndex); + } + else + { + Data::Asset jointIndicesBufferAsset = mesh0.GetSemanticBufferAssetView(Name{ "SKIN_JOINTINDICES" })->GetBufferAsset(); + skinnedMeshLod.SetSkinningInputBufferAsset(jointIndicesBufferAsset, SkinnedMeshInputVertexStreams::BlendIndices); + Data::Asset skinWeightsBufferAsset = mesh0.GetSemanticBufferAssetView(Name{ "SKIN_WEIGHTS" })->GetBufferAsset(); + skinnedMeshLod.SetSkinningInputBufferAsset(skinWeightsBufferAsset, SkinnedMeshInputVertexStreams::BlendWeights); - AZ_Assert(jointIndicesBufferAsset->GetBufferDescriptor().m_byteCount == remappedJointIndexBufferSizeInBytes, "Joint indices data from EMotionFX is not the same size as the buffer from the model in '%s', lod '%d'", fullFileName.c_str(), lodIndex); - AZ_Assert(skinWeightsBufferAsset->GetBufferDescriptor().m_byteCount == remappedSkinWeightsBufferSizeInBytes, "Skin weights data from EMotionFX is not the same size as the buffer from the model in '%s', lod '%d'", fullFileName.c_str(), lodIndex); + // We're using the indices/weights buffers directly from the model. + // However, EMFX has done some re-mapping of the id's, so we need to update the GPU buffer for it to have the correct data. + size_t remappedJointIndexBufferSizeInBytes = blendIndexBufferData.size() * sizeof(blendIndexBufferData[0]); + size_t remappedSkinWeightsBufferSizeInBytes = blendWeightBufferData.size() * sizeof(blendWeightBufferData[0]); - Data::Instance jointIndicesBuffer = RPI::Buffer::FindOrCreate(jointIndicesBufferAsset); - jointIndicesBuffer->UpdateData(blendIndexBufferData.data(), remappedJointIndexBufferSizeInBytes); - Data::Instance skinWeightsBuffer = RPI::Buffer::FindOrCreate(skinWeightsBufferAsset); - skinWeightsBuffer->UpdateData(blendWeightBufferData.data(), remappedSkinWeightsBufferSizeInBytes); - + AZ_Assert(jointIndicesBufferAsset->GetBufferDescriptor().m_byteCount == remappedJointIndexBufferSizeInBytes, "Joint indices data from EMotionFX is not the same size as the buffer from the model in '%s', lod '%d'", fullFileName.c_str(), lodIndex); + AZ_Assert(skinWeightsBufferAsset->GetBufferDescriptor().m_byteCount == remappedSkinWeightsBufferSizeInBytes, "Skin weights data from EMotionFX is not the same size as the buffer from the model in '%s', lod '%d'", fullFileName.c_str(), lodIndex); + + Data::Instance jointIndicesBuffer = RPI::Buffer::FindOrCreate(jointIndicesBufferAsset); + jointIndicesBuffer->UpdateData(blendIndexBufferData.data(), remappedJointIndexBufferSizeInBytes); + Data::Instance skinWeightsBuffer = RPI::Buffer::FindOrCreate(skinWeightsBufferAsset); + skinWeightsBuffer->UpdateData(blendWeightBufferData.data(), remappedSkinWeightsBufferSizeInBytes); + } // Create read-only input assembly buffers that are not modified during skinning and shared across all instances - skinnedMeshLod.SetIndexBuffer(mesh0.GetIndexBufferAssetView().GetBufferAsset()); - skinnedMeshLod.CreateStaticBuffer(uvBufferData.data(), SkinnedMeshStaticVertexStreams::UV_0, fullFileName + lodString + "_SkinnedMeshStaticUVs"); - - // Set the data that needs to be tracked on a per-sub-mesh basis - // and create the common, shared sub-mesh buffer views - skinnedMeshLod.SetSubMeshProperties(subMeshes); + skinnedMeshLod.SetIndexBufferAsset(mesh0.GetIndexBufferAssetView().GetBufferAsset()); + skinnedMeshLod.SetStaticBufferAsset(mesh0.GetSemanticBufferAssetView(Name{ "UV" })->GetBufferAsset(), SkinnedMeshStaticVertexStreams::UV_0); const RPI::BufferAssetView* morphBufferAssetView = mesh0.GetSemanticBufferAssetView(Name{ "MORPHTARGET_VERTEXDELTAS" }); if (morphBufferAssetView) @@ -513,6 +521,28 @@ namespace AZ ProcessMorphsForLod(actor, morphBufferAssetView->GetBufferAsset(), lodIndex, fullFileName, skinnedMeshLod); } + // Set colors after morphs are set, so that we know whether or not they are dynamic (if they exist) + const RPI::BufferAssetView* colorView = mesh0.GetSemanticBufferAssetView(Name{ "COLOR" }); + if (colorView) + { + if (skinnedMeshLod.HasDynamicColors()) + { + // If colors are being morphed, + // add them as input to the skinning compute shader, which will apply the morph + skinnedMeshLod.SetSkinningInputBufferAsset(colorView->GetBufferAsset(), SkinnedMeshInputVertexStreams::Color); + } + else + { + // If colors exist but are not modified dynamically, + // add them to the static streams that are shared by all instances of the same skinned mesh + skinnedMeshLod.SetStaticBufferAsset(colorView->GetBufferAsset(), SkinnedMeshStaticVertexStreams::Color); + } + } + + // Set the data that needs to be tracked on a per-sub-mesh basis + // and create the common, shared sub-mesh buffer views + skinnedMeshLod.SetSubMeshProperties(subMeshes); + skinnedMeshInputBuffers->SetLod(lodIndex, skinnedMeshLod); } // for all lods diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 95272772d8..0a17a6444d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -173,7 +173,12 @@ namespace AZ MaterialAssignmentMap AtomActorInstance::GetMaterialAssignments() const { - return GetMaterialAssignmentsFromModel(m_skinnedMeshInstance->m_model); + if (m_skinnedMeshInstance && m_skinnedMeshInstance->m_model) + { + return GetMaterialAssignmentsFromModel(m_skinnedMeshInstance->m_model); + } + + return MaterialAssignmentMap{}; } AZStd::unordered_set AtomActorInstance::GetModelUvNames() const diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/CMakeLists.txt b/Gems/AtomLyIntegration/ImguiAtom/Code/CMakeLists.txt index 14a64f1133..d9f9aac569 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/CMakeLists.txt @@ -17,8 +17,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC AZ::AtomCore @@ -35,8 +33,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzFramework diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp index 4e137f5854..49ed813ed8 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp @@ -12,6 +12,8 @@ #include +#if defined(IMGUI_ENABLED) + #include #include #include @@ -322,8 +324,8 @@ namespace AZ // Draw the debug console in a closeable, moveable, and resizeable IMGUI window. bool continueShowing = true; - ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("Debug Console", &continueShowing)) + ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_Once); + if (!ImGui::Begin("Debug Console", &continueShowing, ImGuiWindowFlags_NoCollapse)) { ImGui::End(); return false; @@ -367,6 +369,10 @@ namespace AZ } // Focus on the text input field. + if (ImGui::IsWindowAppearing()) + { + ImGui::SetKeyboardFocusHere(-1); + } ImGui::SetItemDefaultFocus(); // Show a button to clear the debug log. @@ -437,3 +443,5 @@ namespace AZ } } } + +#endif // defined(IMGUI_ENABLED) diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h index 4a12e00259..29b2bfc4b5 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h @@ -31,14 +31,10 @@ struct ImGuiInputTextCallbackData; //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AZ { - //////////////////////////////////////////////////////////////////////////////////////////////// - //! The default maximum number of entries to display in the debug log. - constexpr int DefaultMaxEntriesToDisplay = 1028; - - //////////////////////////////////////////////////////////////////////////////////////////////// - //! The default maximum number of input history items to retain. - constexpr int DefaultMaxInputHistorySize = 512; - +#if !defined(IMGUI_ENABLED) + class DebugConsole {}; +#else +#endif // defined(IMGUI_ENABLED) //////////////////////////////////////////////////////////////////////////////////////////////// //! A debug console used to enter debug console commands and display debug log messages. //! @@ -49,6 +45,14 @@ namespace AZ class DebugConsole : public AzFramework::InputChannelEventListener , public AZ::RPI::ViewportContextNotificationBus::Handler { + //////////////////////////////////////////////////////////////////////////////////////////// + //! The default maximum number of entries to display in the debug log. + static constexpr int DefaultMaxEntriesToDisplay = 1028; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! The default maximum number of input history items to retain. + static constexpr int DefaultMaxInputHistorySize = 512; + public: //////////////////////////////////////////////////////////////////////////////////////////// // Allocator diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.h b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.h index 60753883b4..e4b3dd0ca6 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.h +++ b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.h @@ -20,9 +20,9 @@ namespace Audio { - //! Wwise file IO device that access the Lumberyard file system through standard blocking file IO calls. Wwise will still + //! Wwise file IO device that access the Open 3D Engine file system through standard blocking file IO calls. Wwise will still //! run these in separate threads so it won't be blocking the audio playback, but it will interfere with the internal - //! file IO scheduling of Lumberyard. This class can also write, so it's intended use is for one-off file reads and + //! file IO scheduling of Open 3D Engine. This class can also write, so it's intended use is for one-off file reads and //! for tools to be able to write files. class CBlockingDevice_wwise : public AK::StreamMgr::IAkIOHookBlocking diff --git a/Gems/Blast/Code/Include/Blast/BlastMaterial.h b/Gems/Blast/Code/Include/Blast/BlastMaterial.h index f2d48cc5b5..0f713c774e 100644 --- a/Gems/Blast/Code/Include/Blast/BlastMaterial.h +++ b/Gems/Blast/Code/Include/Blast/BlastMaterial.h @@ -133,7 +133,7 @@ namespace Blast BlastMaterialId m_id; }; - //! An asset that holds a list of materials to be edited and assigned in Lumberyard Editor + //! An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor //! Use Asset Editor to create a BlastMaterialLibraryAsset and add materials to it. //! Please note, BlastMaterialLibraryAsset is used only to provide a way to edit materials in the //! Editor, if you need to create materials at runtime (for example, from custom configuration files) diff --git a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h index 1207f1c056..aeeb9b3f6f 100644 --- a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h +++ b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h @@ -15,7 +15,7 @@ #include -namespace Lumberyard +namespace O3de { class GameCrashUploader : public CrashUploader { diff --git a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp index ef76182914..d5d7855df2 100644 --- a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp +++ b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp @@ -21,7 +21,7 @@ #pragma warning(disable : 4996) -namespace Lumberyard +namespace O3de { bool GameCrashUploader::CheckConfirmation(const crashpad::CrashReportDatabase::Report& report) diff --git a/Gems/CrashReporting/Code/Platform/Windows/main_windows.cpp b/Gems/CrashReporting/Code/Platform/Windows/main_windows.cpp index 32ac52fb3e..a04bcafec0 100644 --- a/Gems/CrashReporting/Code/Platform/Windows/main_windows.cpp +++ b/Gems/CrashReporting/Code/Platform/Windows/main_windows.cpp @@ -22,10 +22,10 @@ namespace { int HandlerMain(int argc, char* argv[]) { - Lumberyard::InstallCrashUploader(argc, argv); + O3de::InstallCrashUploader(argc, argv); LOG(ERROR) << "Initializing windows game crash uploader logging"; - int resultCode = crashpad::HandlerMain(argc, argv, Lumberyard::CrashUploader::GetCrashUploader()->GetUserStreamSources()); + int resultCode = crashpad::HandlerMain(argc, argv, O3de::CrashUploader::GetCrashUploader()->GetUserStreamSources()); return resultCode; } diff --git a/Gems/CrashReporting/Code/Source/GameCrashUploader.cpp b/Gems/CrashReporting/Code/Source/GameCrashUploader.cpp index e846c5dd4a..41968faed6 100644 --- a/Gems/CrashReporting/Code/Source/GameCrashUploader.cpp +++ b/Gems/CrashReporting/Code/Source/GameCrashUploader.cpp @@ -14,11 +14,11 @@ #include #include -namespace Lumberyard +namespace O3de { void InstallCrashUploader(int& argc, char* argv[]) { - Lumberyard::CrashUploader::SetCrashUploader(std::make_shared(argc, argv)); + O3de::CrashUploader::SetCrashUploader(std::make_shared(argc, argv)); } std::string GameCrashUploader::GetRootFolder() diff --git a/Gems/CustomAssetExample/Code/CMakeLists.txt b/Gems/CustomAssetExample/Code/CMakeLists.txt index 7bad2611ca..661b1950ce 100644 --- a/Gems/CustomAssetExample/Code/CMakeLists.txt +++ b/Gems/CustomAssetExample/Code/CMakeLists.txt @@ -17,8 +17,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore @@ -34,8 +32,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index b68db062f2..d46c67fafb 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -70,11 +70,11 @@ ly_add_target( if (PAL_TRAIT_BUILD_HOST_TOOLS) find_package(OpenGL QUIET REQUIRED) - # Imported targets (like OpenGL::GL) are scoped to a directory. Add an interface library to make a target with + # Imported targets (like OpenGL::GL) are scoped to a directory. Add a # a global scope - add_library(OpenGLInterface INTERFACE) - target_link_libraries(OpenGLInterface INTERFACE OpenGL::GL) - + add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) + target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) + ly_add_target( NAME EMotionFX.Editor.Static STATIC NAMESPACE Gem @@ -112,7 +112,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) AZ::SceneUI AZ::AzToolsFramework Legacy::Editor.Headers - OpenGLInterface + 3rdParty::OpenGLInterface COMPILE_DEFINITIONS PUBLIC EMFX_EMSTUDIOLYEMBEDDED diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 948bdf6186..2b99f823ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -3031,6 +3031,9 @@ namespace EMotionFX { MorphTargetStandard* morphTarget = static_cast(morphSetup->GetMorphTarget(mtIndex)); + // Remove all previously added deform datas for the given joint as we set a new mesh. + morphTarget->RemoveAllDeformDatasFor(meshJoint); + const AZStd::vector& metaDatas = m_morphTargetMetaAsset->GetMorphTargets(); for (const auto& metaData : metaDatas) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp index 017f120581..b9399fb350 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp @@ -353,7 +353,7 @@ namespace EMotionFX mAssetSourceFolder = assetSourcePath; // Add an ending slash in case there is none yet. - // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Lumberyard does. + // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Open 3D Engine does. if (mAssetSourceFolder.empty() == false) { const char lastChar = AzFramework::StringFunc::LastCharacter(mAssetSourceFolder.c_str()); @@ -378,7 +378,7 @@ namespace EMotionFX mAssetCacheFolder = assetCachePath; // Add an ending slash in case there is none yet. - // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Lumberyard does. + // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Open 3D Engine does. if (mAssetCacheFolder.empty() == false) { const char lastChar = AzFramework::StringFunc::LastCharacter(mAssetCacheFolder.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp index f9d42eef6e..dd0990271d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -38,7 +39,7 @@ namespace EMStudio void LayoutManager::SaveDialogAccepted() { - const AZStd::string filename = AZStd::string::format("%sLayouts/%s.layout", MysticQt::GetDataDir().c_str(), m_inputDialog->GetText().toUtf8().data()); + const auto filename = AZ::IO::Path(MysticQt::GetDataDir()) / AZStd::string::format("Layouts/%s.layout", m_inputDialog->GetText().toUtf8().data()); // If the file already exists, ask to overwrite or not. if (QFile::exists(filename.c_str())) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index c57dbc2d8a..5adec5e0a4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -50,6 +50,7 @@ // include MCore related #include #include +#include #include #include #include @@ -1808,8 +1809,7 @@ namespace EMStudio mLayoutsMenu->clear(); // generate the layouts path - QString layoutsPath = MysticQt::GetDataDir().c_str(); - layoutsPath += "Layouts/"; + QDir layoutsPath = QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Layouts"); // open the dir QDir dir(layoutsPath); @@ -1911,8 +1911,7 @@ namespace EMStudio SavePreferences(); // generate the filename - AZStd::string filename; - filename = AZStd::string::format("%sLayouts/%s.layout", MysticQt::GetDataDir().c_str(), FromQtString(text).c_str()); + const auto filename = AZ::IO::Path(MysticQt::GetDataDir()) / AZStd::string::format("Layouts/%s.layout", FromQtString(text).c_str()); // try to load it if (GetLayoutManager()->LoadLayout(filename.c_str()) == false) @@ -1970,7 +1969,7 @@ namespace EMStudio { // generate the filename QAction* action = qobject_cast(sender()); - m_layoutFileBeingRemoved = QString(MysticQt::GetDataDir().c_str()) + "Layouts/" + action->text() + ".layout"; + m_layoutFileBeingRemoved = QDir(MysticQt::GetDataDir().c_str()).filePath(QString("Layouts/") + action->text() + ".layout"); m_removeLayoutNameText = action->text(); // make sure we really want to remove it @@ -1998,8 +1997,7 @@ namespace EMStudio SavePreferences(); // generate the filename - AZStd::string filename; - filename = AZStd::string::format("%sLayouts/%s.layout", MysticQt::GetDataDir().c_str(), FromQtString(action->text()).c_str()); + const auto filename = AZ::IO::Path(MysticQt::GetDataDir()) / AZStd::string::format("Layouts/%s.layout", FromQtString(action->text()).c_str()); // try to load it if (GetLayoutManager()->LoadLayout(filename.c_str())) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index ecb2fd632e..47b88b1fa2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -695,8 +696,9 @@ namespace EMStudio bool RenderPlugin::Init() { // load the cursors - mZoomInCursor = new QCursor(QPixmap(AZStd::string(MysticQt::GetDataDir() + "Images/Rendering/ZoomInCursor.png").c_str()).scaled(32, 32)); - mZoomOutCursor = new QCursor(QPixmap(AZStd::string(MysticQt::GetDataDir() + "Images/Rendering/ZoomOutCursor.png").c_str()).scaled(32, 32)); + QDir dataDir{ QString(MysticQt::GetDataDir().c_str()) }; + mZoomInCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); + mZoomOutCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); mCurrentSelection = &GetCommandManager()->GetCurrentSelection(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp index 35edb3873d..99f203d6e7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp @@ -22,6 +22,7 @@ #include #include +#include namespace EMStudio { @@ -59,7 +60,7 @@ namespace EMStudio } // get the absolute directory path where all the shaders will be located - const AZStd::string shaderPath = MysticQt::GetDataDir() + "Shaders/"; + const auto shaderPath = AZ::IO::Path(MysticQt::GetDataDir()) / "Shaders"; // create graphics manager and initialize it mGraphicsManager = new RenderGL::GraphicsManager(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp index 85c07a306a..3c3b5ca65d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp @@ -166,8 +166,8 @@ namespace EMStudio connect(mPresetNameLineEdit, &QLineEdit::textEdited, this, &GameControllerWindow::OnPresetNameEdited); connect(mPresetNameLineEdit, &QLineEdit::returnPressed, this, &GameControllerWindow::OnPresetNameChanged); - EMStudioManager::MakeTransparentButton(mAddPresetButton, "/Images/Icons/Plus.svg", "Add a game controller preset"); - EMStudioManager::MakeTransparentButton(mRemovePresetButton, "/Images/Icons/Remove.svg", "Remove a game controller preset"); + EMStudioManager::MakeTransparentButton(mAddPresetButton, "Images/Icons/Plus.svg", "Add a game controller preset"); + EMStudioManager::MakeTransparentButton(mRemovePresetButton, "Images/Icons/Remove.svg", "Remove a game controller preset"); QHBoxLayout* buttonsLayout = new QHBoxLayout(); buttonsLayout->addWidget(mAddPresetButton); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp index 99c8eeafac..f139a6d802 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp @@ -86,9 +86,9 @@ namespace EMStudio mAddNodesButton = new QToolButton(); mRemoveNodesButton = new QToolButton(); - EMStudioManager::MakeTransparentButton(mSelectNodesButton, "/Images/Icons/Plus.svg", "Select nodes and replace the current selection"); - EMStudioManager::MakeTransparentButton(mAddNodesButton, "/Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); - EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "/Images/Icons/Minus.svg", "Remove selected nodes from the list"); + EMStudioManager::MakeTransparentButton(mSelectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); + EMStudioManager::MakeTransparentButton(mAddNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); + EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); @@ -403,4 +403,4 @@ namespace EMStudio } } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp index 9357a18c11..6722dc5512 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp @@ -130,11 +130,11 @@ namespace EMStudio mClearButton = new QToolButton(); mCancelSelectionButton = new QToolButton(); - EMStudioManager::MakeTransparentButton(mOpenAttachmentButton, "/Images/Icons/Open.svg", "Open actor from file and add it as regular attachment"); - EMStudioManager::MakeTransparentButton(mOpenDeformableAttachmentButton, "/Images/Icons/Open.svg", "Open actor from file and add it as skin attachment"); - EMStudioManager::MakeTransparentButton(mRemoveButton, "/Images/Icons/Minus.svg", "Remove selected attachments"); - EMStudioManager::MakeTransparentButton(mClearButton, "/Images/Icons/Clear.svg", "Remove all attachments"); - EMStudioManager::MakeTransparentButton(mCancelSelectionButton, "/Images/Icons/Remove.svg", "Cancel attachment selection"); + EMStudioManager::MakeTransparentButton(mOpenAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as regular attachment"); + EMStudioManager::MakeTransparentButton(mOpenDeformableAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as skin attachment"); + EMStudioManager::MakeTransparentButton(mRemoveButton, "Images/Icons/Minus.svg", "Remove selected attachments"); + EMStudioManager::MakeTransparentButton(mClearButton, "Images/Icons/Clear.svg", "Remove all attachments"); + EMStudioManager::MakeTransparentButton(mCancelSelectionButton, "Images/Icons/Remove.svg", "Cancel attachment selection"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); @@ -939,4 +939,4 @@ namespace EMStudio } } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp index 71f19f6817..5dc6aa8bb5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp @@ -17,6 +17,7 @@ #include "../MotionWindow/MotionListWindow.h" #include #include +#include #include #include #include @@ -87,8 +88,9 @@ namespace EMStudio m_toggleLockSelectionCallback = new CommandToggleLockSelectionCallback(false); GetCommandManager()->RegisterCommandCallback("ToggleLockSelection", m_toggleLockSelectionCallback); - m_lockEnabledIcon = new QIcon(AZStd::string(MysticQt::GetDataDir() + "/Images/Icons/LockEnabled.svg").c_str()); - m_lockDisabledIcon = new QIcon(AZStd::string(MysticQt::GetDataDir() + "/Images/Icons/LockDisabled.svg").c_str()); + QDir dataDir{ QString(MysticQt::GetDataDir().c_str()) }; + m_lockEnabledIcon = new QIcon(dataDir.filePath("Images/Icons/LockEnabled.svg")); + m_lockDisabledIcon = new QIcon(dataDir.filePath("Images/Icons/LockDisabled.svg")); m_commandEdit = new QLineEdit(); m_commandEdit->setPlaceholderText("Enter command"); @@ -108,7 +110,7 @@ namespace EMStudio connect(m_globalSimSpeedSlider, &AzQtComponents::SliderDouble::valueChanged, this, &CommandBarPlugin::OnGlobalSimSpeedChanged); m_globalSimSpeedSliderAction = mBar->addWidget(m_globalSimSpeedSlider); - m_globalSimSpeedResetAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Reset.svg"), + m_globalSimSpeedResetAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), tr("Reset the global simulation speed factor to its normal speed"), this, &CommandBarPlugin::ResetGlobalSimSpeed); @@ -127,7 +129,7 @@ namespace EMStudio m_progressBarAction = mBar->addWidget(m_progressBar); m_progressBarAction->setVisible(false); - m_lockSelectionAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Reset.svg"), + m_lockSelectionAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), tr("Lock or unlock the selection of actor instances"), this, &CommandBarPlugin::OnLockSelectionButton); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp index 5e61c282b7..50e6069774 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp @@ -175,11 +175,11 @@ namespace EMStudio mRemovePhonemesButtonArrow = new QPushButton(""); mClearPhonemesButton = new QPushButton(""); - EMStudioManager::MakeTransparentButton(mAddPhonemesButtonArrow, "/Images/Icons/PlayForward.svg", "Assign the selected phonemes to the morph target."); - EMStudioManager::MakeTransparentButton(mRemovePhonemesButtonArrow, "/Images/Icons/PlayBackward.svg", "Unassign the selected phonemes from the morph target."); - EMStudioManager::MakeTransparentButton(mAddPhonemesButton, "/Images/Icons/Plus.svg", "Assign the selected phonemes to the morph target."); - EMStudioManager::MakeTransparentButton(mRemovePhonemesButton, "/Images/Icons/Minus.svg", "Unassign the selected phonemes from the morph target."); - EMStudioManager::MakeTransparentButton(mClearPhonemesButton, "/Images/Icons/Clear.svg", "Unassign all phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(mAddPhonemesButtonArrow, "Images/Icons/PlayForward.svg", "Assign the selected phonemes to the morph target."); + EMStudioManager::MakeTransparentButton(mRemovePhonemesButtonArrow, "Images/Icons/PlayBackward.svg", "Unassign the selected phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(mAddPhonemesButton, "Images/Icons/Plus.svg", "Assign the selected phonemes to the morph target."); + EMStudioManager::MakeTransparentButton(mRemovePhonemesButton, "Images/Icons/Minus.svg", "Unassign the selected phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(mClearPhonemesButton, "Images/Icons/Clear.svg", "Unassign all phonemes from the morph target."); // init the visime tables mPossiblePhonemeSetsTable = new DragTableWidget(0, 1); @@ -644,4 +644,4 @@ namespace EMStudio } } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp index a628233200..82887f09ef 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp @@ -68,16 +68,16 @@ namespace EMStudio QToolBar* toolBar = new QToolBar(this); - m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg"), + m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Add new motion event preset"), this, &MotionEventPresetsWidget::AddMotionEventPreset); - m_loadAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Open.svg"), + m_loadAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Open.svg"), tr("Load motion event preset config file"), this, [=]() { LoadPresets(); /* use lambda so that we get the default value for the showDialog parameter */ }); m_saveMenuAction = toolBar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Save.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Save.svg"), tr("Save motion event preset config")); { QToolButton* toolButton = qobject_cast(toolBar->widgetForAction(m_saveMenuAction)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp index fc4700b462..4ccf5d8937 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp @@ -279,17 +279,17 @@ namespace EMStudio QToolBar* toolBar = new QToolBar(this); toolBar->setObjectName("MotionSetManagementWindow.ToolBar"); - m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg"), + m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Add new motion set"), this, &MotionSetManagementWindow::OnCreateMotionSet); m_addAction->setObjectName("MotionSetManagementWindow.ToolBar.AddNewMotionSet"); - m_openAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Open.svg"), + m_openAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Open.svg"), tr("Load motion set from a file"), this, &MotionSetManagementWindow::OnOpen); m_saveMenuAction = toolBar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Save.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Save.svg"), tr("Save selected root motion set")); { QToolButton* toolButton = qobject_cast(toolBar->widgetForAction(m_saveMenuAction)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp index eb3106e324..bb943e3476 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp @@ -231,16 +231,16 @@ namespace EMStudio QToolBar* toolBar = new QToolBar(this); toolBar->setObjectName("MotionSetWindow.ToolBar"); - m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg"), + m_addAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Add a new entry"), this, &MotionSetWindow::OnAddNewEntry); m_addAction->setObjectName("MotionSetWindow.ToolBar.AddANewEntry"); - m_loadAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Open.svg"), + m_loadAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Open.svg"), tr("Add entries by selecting motions."), this, &MotionSetWindow::OnLoadEntries); - m_editAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Edit.svg"), + m_editAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Edit.svg"), tr("Batch edit selected motion IDs"), this, &MotionSetWindow::OnEditButton); @@ -554,7 +554,7 @@ namespace EMStudio QTableWidgetItem* exclamationTableItem = new QTableWidgetItem(""); exclamationTableItem->setFlags(Qt::NoItemFlags); - exclamationTableItem->setIcon(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/ExclamationMark.svg")); + exclamationTableItem->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/ExclamationMark.svg")); exclamationTableItem->setToolTip(tooltipText.c_str()); tableWidget->setItem(rowIndex, 0, exclamationTableItem); } @@ -779,7 +779,7 @@ namespace EMStudio QTableWidgetItem* exclamationTableItem = new QTableWidgetItem(""); exclamationTableItem->setFlags(Qt::NoItemFlags); - exclamationTableItem->setIcon(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/ExclamationMark.svg")); + exclamationTableItem->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/ExclamationMark.svg")); exclamationTableItem->setToolTip(tooltipText.c_str()); tableWidget->setItem(row, 0, exclamationTableItem); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp index d0bdb6253b..f1136843b2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp @@ -206,8 +206,8 @@ namespace EMStudio // reinitialize the motion table entries ReInit(); - mAddMotionsAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg"), tr("Load motions"), this, &MotionWindowPlugin::OnAddMotions); - mSaveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Menu/FileSave.svg"), tr("Save selected motions"), this, &MotionWindowPlugin::OnSave); + mAddMotionsAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Load motions"), this, &MotionWindowPlugin::OnAddMotions); + mSaveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Menu/FileSave.svg"), tr("Save selected motions"), this, &MotionWindowPlugin::OnSave); toolBar->addSeparator(); AzQtComponents::FilteredSearchWidget* searchWidget = new AzQtComponents::FilteredSearchWidget(toolBar); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp index 008fc84ed9..dbd12544f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp @@ -204,9 +204,9 @@ namespace EMStudio mRemoveButton = new QPushButton(); mClearButton = new QPushButton(); - EMStudioManager::MakeTransparentButton(mAddButton, "/Images/Icons/Plus.svg", "Add a new node group"); - EMStudioManager::MakeTransparentButton(mRemoveButton, "/Images/Icons/Minus.svg", "Remove selected node groups"); - EMStudioManager::MakeTransparentButton(mClearButton, "/Images/Icons/Clear.svg", "Remove all node groups"); + EMStudioManager::MakeTransparentButton(mAddButton, "Images/Icons/Plus.svg", "Add a new node group"); + EMStudioManager::MakeTransparentButton(mRemoveButton, "Images/Icons/Minus.svg", "Remove selected node groups"); + EMStudioManager::MakeTransparentButton(mClearButton, "Images/Icons/Clear.svg", "Remove all node groups"); // add the buttons to the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); @@ -696,4 +696,4 @@ namespace EMStudio } } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 9431a2c7dc..9d6cc4f502 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -92,9 +92,9 @@ namespace EMStudio mAddNodesButton = new QPushButton(); mRemoveNodesButton = new QPushButton(); - EMStudioManager::MakeTransparentButton(mSelectNodesButton, "/Images/Icons/Plus.svg", "Select nodes and replace the current selection"); - EMStudioManager::MakeTransparentButton(mAddNodesButton, "/Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); - EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "/Images/Icons/Minus.svg", "Remove selected nodes from the list"); + EMStudioManager::MakeTransparentButton(mSelectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); + EMStudioManager::MakeTransparentButton(mAddNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); + EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); @@ -428,4 +428,4 @@ namespace EMStudio } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp index a02f58868e..1e78adefd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp @@ -75,7 +75,7 @@ namespace EMStudio // Open actors { QAction* menuAction = toolBar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Open.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Open.svg"), tr("Load actor from asset")); QToolButton* toolButton = qobject_cast(toolBar->widgetForAction(menuAction)); @@ -90,11 +90,11 @@ namespace EMStudio menuAction->setMenu(contextMenu); } - m_createInstanceAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg"), + m_createInstanceAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Create a new instance of the selected actors"), this, &ActorsWindow::OnCreateInstanceButtonClicked); - m_saveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Save.svg"), + m_saveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Save.svg"), tr("Save selected actors"), GetMainWindow(), &MainWindow::OnFileSaveSelectedActors); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp index 29ed0f32a8..6b020fd85a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp @@ -13,6 +13,7 @@ #include "MirrorSetupWindow.h" #include #include +#include #include #include #include @@ -55,11 +56,11 @@ namespace EMStudio setMinimumHeight(600); // load some icons - const AZStd::string dataDir = MysticQt::GetDataDir().c_str(); - mBoneIcon = new QIcon(AZStd::string(dataDir + "Images/Icons/Bone.svg").c_str()); - mNodeIcon = new QIcon(AZStd::string(dataDir + "Images/Icons/Node.svg").c_str()); - mMeshIcon = new QIcon(AZStd::string(dataDir + "Images/Icons/Mesh.svg").c_str()); - mMappedIcon = new QIcon(AZStd::string(dataDir + "Images/Icons/Confirm.svg").c_str()); + const QDir dataDir{ QString(MysticQt::GetDataDir().c_str()) }; + mBoneIcon = new QIcon(dataDir.filePath("Images/Icons/Bone.svg")); + mNodeIcon = new QIcon(dataDir.filePath("Images/Icons/Node.svg")); + mMeshIcon = new QIcon(dataDir.filePath("Images/Icons/Mesh.svg")); + mMappedIcon = new QIcon(dataDir.filePath("Images/Icons/Confirm.svg")); // create the main layout QVBoxLayout* mainLayout = new QVBoxLayout(); @@ -76,17 +77,17 @@ namespace EMStudio toolBarLayout->setSpacing(0); mainLayout->addLayout(toolBarLayout); mButtonOpen = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonOpen, "/Images/Icons/Open.svg", "Load and apply a mapping template."); + EMStudioManager::MakeTransparentButton(mButtonOpen, "Images/Icons/Open.svg", "Load and apply a mapping template."); connect(mButtonOpen, &QPushButton::clicked, this, &MirrorSetupWindow::OnLoadMapping); mButtonSave = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonSave, "/Images/Menu/FileSave.svg", "Save the currently setup mapping as template."); + EMStudioManager::MakeTransparentButton(mButtonSave, "Images/Menu/FileSave.svg", "Save the currently setup mapping as template."); connect(mButtonSave, &QPushButton::clicked, this, &MirrorSetupWindow::OnSaveMapping); mButtonClear = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonClear, "/Images/Icons/Clear.svg", "Clear the currently setup mapping entirely."); + EMStudioManager::MakeTransparentButton(mButtonClear, "Images/Icons/Clear.svg", "Clear the currently setup mapping entirely."); connect(mButtonClear, &QPushButton::clicked, this, &MirrorSetupWindow::OnClearMapping); mButtonGuess = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonGuess, "/Images/Icons/Character.svg", "Perform name based mapping."); + EMStudioManager::MakeTransparentButton(mButtonGuess, "Images/Icons/Character.svg", "Perform name based mapping."); connect(mButtonGuess, &QPushButton::clicked, this, &MirrorSetupWindow::OnBestGuess); toolBarLayout->addWidget(mButtonOpen, 0, Qt::AlignLeft); @@ -195,7 +196,7 @@ namespace EMStudio sourceLabel->setTextFormat(Qt::RichText); sourceSearchLayout->addWidget(sourceLabel); //QPushButton* loadSourceButton = new QPushButton(); - //EMStudioManager::MakeTransparentButton( loadSourceButton, "/Images/Icons/Open.svg", "Load a source actor" ); + //EMStudioManager::MakeTransparentButton( loadSourceButton, "Images/Icons/Open.svg", "Load a source actor" ); //connect( loadSourceButton, SIGNAL(clicked()), this, SLOT(OnLoadSourceActor()) ); //sourceSearchLayout->addWidget( loadSourceButton, 0, Qt::AlignLeft ); spacerWidget = new QWidget(); @@ -248,7 +249,7 @@ namespace EMStudio lowerLayout->addLayout(mappingLayout); mappingLayout->addWidget(new QLabel("Mapping:"), 0, Qt::AlignLeft | Qt::AlignVCenter); //mButtonGuess = new QPushButton(); - //EMStudioManager::MakeTransparentButton( mButtonGuess, "/Images/Icons/Character.svg", "Best guess mapping" ); + //EMStudioManager::MakeTransparentButton( mButtonGuess, "Images/Icons/Character.svg", "Best guess mapping" ); //connect( mButtonGuess, SIGNAL(clicked()), this, SLOT(OnBestGuessGeometrical()) ); //mappingLayout->addWidget( mButtonGuess, 0, Qt::AlignLeft ); spacerWidget = new QWidget(); @@ -1253,4 +1254,4 @@ namespace EMStudio } // namespace EMStudio -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp index b29b62481d..6648039724 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp @@ -26,23 +26,23 @@ namespace EMStudio : QObject(toolbar) { m_skipBackwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/SkipBackward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/SkipBackward.svg"), "Skip backward", toolbar, &TimeViewToolBar::OnSkipBackwardButton); m_seekBackwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/SeekBackward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/SeekBackward.svg"), "Seek backward", toolbar, &TimeViewToolBar::OnSeekBackwardButton); m_playForwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/PlayForward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/PlayForward.svg"), "Play", toolbar, &TimeViewToolBar::OnPlayForwardButton); m_seekForwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/SeekForward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/SeekForward.svg"), "Seek forward", toolbar, &TimeViewToolBar::OnSeekForwardButton); m_skipForwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/SkipForward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/SkipForward.svg"), "Skip forward", toolbar, &TimeViewToolBar::OnSkipForwardButton); m_separatorRight = toolbar->addSeparator(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp index d8bb2ad580..b75fdf9a37 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp @@ -22,27 +22,27 @@ namespace EMStudio : QObject(toolbar) { m_loopForeverAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Loop.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Loop.svg"), "Loop forever", toolbar, &TimeViewToolBar::UpdateMotions); m_loopForeverAction->setCheckable(true); m_mirrorAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Mirror.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Mirror.svg"), "Mirror", toolbar, &TimeViewToolBar::UpdateMotions); m_mirrorAction->setCheckable(true); m_backwardAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/MoveBackward.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/MoveBackward.svg"), "Move backward", toolbar, &TimeViewToolBar::UpdateMotions); m_backwardAction->setCheckable(true); m_inPlaceAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/InPlace.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/InPlace.svg"), "In place", toolbar, &TimeViewToolBar::UpdateMotions); m_inPlaceAction->setCheckable(true); m_retargetAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Retarget.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Retarget.svg"), "Retarget", toolbar, &TimeViewToolBar::UpdateMotions); m_retargetAction->setCheckable(true); @@ -58,7 +58,7 @@ namespace EMStudio m_speedAction = toolbar->addWidget(m_speedSlider); m_speedResetAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Reset.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), tr("Reset the play speed to its normal speed."), this, &PlaybackOptionsGroup::ResetPlaySpeed); connect(m_speedResetAction, &QAction::triggered, toolbar, &TimeViewToolBar::UpdateMotions); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/RecorderGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/RecorderGroup.cpp index e75b0f0f67..c9e7a8991e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/RecorderGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/RecorderGroup.cpp @@ -27,15 +27,15 @@ namespace EMStudio : QObject(toolbar) { m_clearRecordAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Clear.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Clear.svg"), "Clear recording", toolbar, &TimeViewToolBar::OnClearRecordButton); m_recordAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/RecordButton.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/RecordButton.svg"), "Clear recording", toolbar, &TimeViewToolBar::OnRecordButton); m_recordOptionsAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Settings.svg"), ""); + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Settings.svg"), ""); { QMenu* recordOptionsMenu = new QMenu(toolbar); recordOptionsMenu->addAction(tr("Recording options"))->setEnabled(false); @@ -70,7 +70,7 @@ namespace EMStudio } m_displayOptionsAction = toolbar->addAction( - MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Visualization.svg"), + MysticQt::GetMysticQt()->FindIcon("Images/Icons/Visualization.svg"), "Show display and visual options"); { QMenu* contextMenu = new QMenu(toolbar); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index 8eb3604c4d..3368adca34 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -28,6 +28,7 @@ #include "../../../../EMStudioSDK/Source/MainWindow.h" #include +#include #include #include #include @@ -200,8 +201,8 @@ namespace EMStudio GetCommandManager()->RegisterCommandCallback("PlayMotion", m_commandCallbacks.back()); // load the cursors - mZoomInCursor = new QCursor(QPixmap(AZStd::string(MysticQt::GetDataDir() + "Images/Rendering/ZoomInCursor.png").c_str()).scaled(32, 32)); - mZoomOutCursor = new QCursor(QPixmap(AZStd::string(MysticQt::GetDataDir() + "Images/Rendering/ZoomOutCursor.png").c_str()).scaled(32, 32)); + mZoomInCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); + mZoomOutCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); // create main widget mMainWidget = new QWidget(mDock); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp index f044129510..d7f0b8c2d4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp @@ -16,6 +16,7 @@ #include "TimeInfoWidget.h" #include "TrackHeaderWidget.h" #include "TimeViewToolBar.h" +#include #include #include #include @@ -90,8 +91,8 @@ namespace EMStudio mDataFont.setPixelSize(13); // load the time handle top image - QString imageName = MysticQt::GetMysticQt()->GetDataDir().c_str(); - mTimeHandleTop = QPixmap(imageName + "Images/Icons/TimeHandleTop.png"); + QDir imageName{ QString(MysticQt::GetMysticQt()->GetDataDir().c_str()) }; + mTimeHandleTop = QPixmap(imageName.filePath("Images/Icons/TimeHandleTop.png")); setMouseTracking(true); setAcceptDrops(true); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp index 0f63c20ef9..ce592f2ff9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp @@ -62,7 +62,7 @@ namespace EMStudio mainAddWidgetLayout->addWidget(label); QToolButton* addButton = new QToolButton(); - addButton->setIcon(MysticQt::GetMysticQt()->FindIcon("/Images/Icons/Plus.svg")); + addButton->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg")); addButton->setToolTip("Add a new event track"); connect(addButton, &QToolButton::clicked, this, &TrackHeaderWidget::OnAddTrackButtonClicked); mainAddWidgetLayout->addWidget(addButton); diff --git a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake index 16a97fff5f..821e7d1f25 100644 --- a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake +++ b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake @@ -15,8 +15,8 @@ # is being avoided to prevent overriding functions declared in other targets platfrom # specific cmake files -target_compile_definitions(OpenGLInterface +target_compile_definitions(3rdParty::OpenGLInterface INTERFACE # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. GL_SILENCE_DEPRECATION -) +) \ No newline at end of file diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp index 703451d767..3408560237 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp @@ -14,7 +14,7 @@ #include "MysticQtManager.h" #include #include - +#include namespace MysticQt { @@ -48,7 +48,7 @@ namespace MysticQt MysticQtManager::IconData::IconData(const char* filename) { mFileName = filename; - mIcon = new QIcon(AZStd::string::format("%s%s", GetMysticQt()->GetDataDir().c_str(), filename).c_str()); + mIcon = new QIcon(QDir{ QString(GetMysticQt()->GetDataDir().c_str()) }.filePath(filename)); } diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp index 175b563e25..ab6a05f448 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp @@ -36,7 +36,7 @@ namespace EMotionFX hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &ActorGoalNodePicker::OnResetClicked); hLayout->addWidget(m_resetButton); @@ -196,4 +196,4 @@ namespace EMotionFX } } // namespace EMotionFX -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorJointHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorJointHandler.cpp index 6baeae904b..4ab1a790dd 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorJointHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorJointHandler.cpp @@ -40,7 +40,7 @@ namespace EMotionFX { connect(m_pickButton, &QPushButton::clicked, this, &ActorJointPicker::OnPickClicked); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &ActorJointPicker::OnResetClicked); QHBoxLayout* hLayout = new QHBoxLayout(); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorMorphTargetHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorMorphTargetHandler.cpp index f84933e613..91e6d5ca04 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorMorphTargetHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorMorphTargetHandler.cpp @@ -39,7 +39,7 @@ namespace EMotionFX hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &ActorMorphTargetPicker::OnResetClicked); hLayout->addWidget(m_resetButton); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphParameterHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphParameterHandler.cpp index 9b54a7328d..de80f5d7aa 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphParameterHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphParameterHandler.cpp @@ -52,14 +52,14 @@ namespace EMotionFX hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnResetClicked); hLayout->addWidget(m_resetButton); if (m_parameterMaskMode) { m_shrinkButton = new QPushButton(); - EMStudio::EMStudioManager::MakeTransparentButton(m_shrinkButton, "/Images/Icons/Cut.svg", "Shrink the parameter mask to the ports that are actually connected."); + EMStudio::EMStudioManager::MakeTransparentButton(m_shrinkButton, "Images/Icons/Cut.svg", "Shrink the parameter mask to the ports that are actually connected."); connect(m_shrinkButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnShrinkClicked); hLayout->addWidget(m_shrinkButton); } diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp index 9c2266b7cc..33b92c3625 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp @@ -209,7 +209,7 @@ namespace EMotionFX transitionLayout->addWidget(transitionLineEdit, row, 0); QPushButton* removeTransitionButton = new QPushButton(); - EMStudio::EMStudioManager::MakeTransparentButton(removeTransitionButton, "/Images/Icons/Trash.svg", "Remove transition from list"); + EMStudio::EMStudioManager::MakeTransparentButton(removeTransitionButton, "Images/Icons/Trash.svg", "Remove transition from list"); connect(removeTransitionButton, &QPushButton::clicked, this, [this, removeTransitionButton, id]() { m_transitionIds.erase(AZStd::remove(m_transitionIds.begin(), m_transitionIds.end(), id), m_transitionIds.end()); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp index 19b9958b7c..6472caaf68 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp @@ -494,7 +494,7 @@ namespace EMotionFX // Add motions button. QPushButton* addMotionsButton = new QPushButton(); - EMStudio::EMStudioManager::MakeTransparentButton(addMotionsButton, "/Images/Icons/Plus.svg", "Add motions to blend space"); + EMStudio::EMStudioManager::MakeTransparentButton(addMotionsButton, "Images/Icons/Plus.svg", "Add motions to blend space"); connect(addMotionsButton, &QPushButton::clicked, this, &BlendSpaceMotionContainerWidget::OnAddMotion); topRowLayout->addWidget(addMotionsButton, 0, Qt::AlignRight); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.cpp index b8607fdbb3..b1f74701b8 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.cpp @@ -304,7 +304,7 @@ namespace EMotionFX topRowLayout->addWidget(m_addMotionsLabel); m_pickButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_pickButton, "/Images/Icons/Plus.svg", "Add motions to blend space"); + EMStudio::EMStudioManager::MakeTransparentButton(m_pickButton, "Images/Icons/Plus.svg", "Add motions to blend space"); m_pickButton->setObjectName("EMFX.MotionSetMotionIdPicker.PickButton"); connect(m_pickButton, &QPushButton::clicked, this, &MotionSetMotionIdPicker::OnPickClicked); topRowLayout->addWidget(m_pickButton); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/SimulatedObjectSelectionHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/SimulatedObjectSelectionHandler.cpp index c52cafa3c7..0fe01a8d92 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/SimulatedObjectSelectionHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/SimulatedObjectSelectionHandler.cpp @@ -33,7 +33,7 @@ namespace EMotionFX hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &SimulatedObjectPicker::OnResetClicked); hLayout->addWidget(m_resetButton); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/TransitionStateFilterLocalHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/TransitionStateFilterLocalHandler.cpp index 866b796ef8..806afda68b 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/TransitionStateFilterLocalHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/TransitionStateFilterLocalHandler.cpp @@ -38,7 +38,7 @@ namespace EMotionFX hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); - EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); + EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &TransitionStateFilterPicker::OnResetClicked); hLayout->addWidget(m_resetButton); @@ -187,4 +187,4 @@ namespace EMotionFX } } // namespace EMotionFX -#include \ No newline at end of file +#include diff --git a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp index 2bbb8ec4fd..68c1146eae 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp @@ -152,8 +152,6 @@ namespace EMotionFX SimulatedJoint* joint = object->GetSimulatedRootJoint(row); return createIndex(row, column, joint); } - - return QModelIndex(); } } diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h index b0259abd96..f96f6ca3c1 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h @@ -32,7 +32,7 @@ namespace EMotionFX /** * Represents an EMotionFX actor asset. * Each asset maintains storage of the original EMotionFX binary asset (via EMotionFXAsset base class). - * Initialization of the asset constructs Lumberyard rendering objects, such as the render mesh and material, + * Initialization of the asset constructs Open 3D Engine rendering objects, such as the render mesh and material, * directly from the instantiated EMotionFX actor. * An easy future memory optimization is to wipe the EMotionFXAsset buffer after the actor, render meshes, * and materials are created, since it's technically no longer necessary. At this stage it's worth keeping @@ -68,7 +68,7 @@ namespace EMotionFX /** * Asset handler for loading and initializing actor assets. - * The OnInitAsset stage constructs Lumberyard render meshes and materials by extracting + * The OnInitAsset stage constructs Open 3D Engine render meshes and materials by extracting * said data from the EMotionFX actor. */ class ActorAssetHandler diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index 5521ac31cb..0a64c7b408 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -860,16 +861,13 @@ namespace EMotionFX using namespace AzToolsFramework; // Construct data folder that is used by the tool for loading assets (images etc.). - AZStd::string devRootPath; - AzFramework::ApplicationRequests::Bus::BroadcastResult(devRootPath, &AzFramework::ApplicationRequests::GetEngineRoot); - devRootPath += "Gems/EMotionFX/Assets/Editor/"; - AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePathKeepCase, devRootPath); + auto editorAssetsPath = (AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / "Gems/EMotionFX/Assets/Editor").LexicallyNormal(); // Re-initialize EMStudio. int argc = 0; char** argv = nullptr; - MysticQt::Initializer::Init("", devRootPath.c_str()); + MysticQt::Initializer::Init("", editorAssetsPath.c_str()); EMStudio::Initializer::Init(qApp, argc, argv); InitializeEMStudioPlugins(); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp b/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp index 6651000c1c..6701340f7d 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp @@ -66,7 +66,7 @@ namespace EMotionFX QString GetLayoutFileDirectory() const { - return QString("%1Layouts").arg(MysticQt::GetDataDir().c_str()); + return QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Layouts"); } QString GetLayoutFileName() diff --git a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.h b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.h index 53dc863f58..4be0767849 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.h @@ -18,7 +18,7 @@ namespace EditorPythonBindings { namespace PythonProxyBusManagement { - //! Creates the 'azlmbr.bus' module so that Python script can use Lumberyard buses + //! Creates the 'azlmbr.bus' module so that Python script can use Open 3D Engine buses void CreateSubmodule(pybind11::module module); } } diff --git a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp index 11b230515a..21f56e2f39 100644 --- a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp +++ b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp @@ -437,7 +437,5 @@ namespace GraphCanvas default: return QGraphicsWidget::sizeHint(which, constraint); } - - return QGraphicsWidget::sizeHint(which, constraint); } } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Parser.cpp b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Parser.cpp index 3f887a9121..319996949b 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Parser.cpp +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Parser.cpp @@ -331,8 +331,6 @@ namespace { return QColor(color); } - - return QColor(); } bool IsColorValid(const QString& value) diff --git a/Gems/ImGui/Code/Include/ImGuiContextScope.h b/Gems/ImGui/Code/Include/ImGuiContextScope.h index 275dd7dce2..8f441ce733 100644 --- a/Gems/ImGui/Code/Include/ImGuiContextScope.h +++ b/Gems/ImGui/Code/Include/ImGuiContextScope.h @@ -12,6 +12,8 @@ #pragma once +struct ImGuiContext; + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace ImGui { @@ -22,16 +24,21 @@ namespace ImGui { public: //////////////////////////////////////////////////////////////////////////////////////////// - explicit ImGuiContextScope(ImGuiContext* newContext) - : m_previousContext(ImGui::GetCurrentContext()) + explicit ImGuiContextScope([[maybe_unused]] ImGuiContext* newContext) + : m_previousContext(nullptr) { +#if defined(IMGUI_ENABLED) + m_previousContext = ImGui::GetCurrentContext(); ImGui::SetCurrentContext(newContext); +#endif } //////////////////////////////////////////////////////////////////////////////////////////// ~ImGuiContextScope() { +#if defined(IMGUI_ENABLED) ImGui::SetCurrentContext(m_previousContext); +#endif } private: diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index c47e5506e1..697cc61f86 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -142,11 +142,6 @@ namespace void ImGuiManager::Initialize() { - if (!gEnv || !gEnv->pRenderer) - { - AZ_Warning("ImGuiManager", false, "%s %s", __func__, "gEnv Invalid -- Skipping ImGui Initialization."); - return; - } // Register for Buses ImGuiManagerListenerBus::Handler::BusConnect(); @@ -223,23 +218,9 @@ void ImGuiManager::Initialize() s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LL, ImGuiNavInput_LStickLeft)); s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LR, ImGuiNavInput_LStickRight)); - // Set the Display Size - IRenderer* renderer = gEnv->pRenderer; - io.DisplaySize.x = static_cast(renderer->GetWidth()); - io.DisplaySize.y = static_cast(renderer->GetHeight()); - - // Create Font Texture - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); - ITexture* fontTexture = - renderer->Create2DTexture("ImGuiFont", width, height, 1, FT_ALPHA, pixels, eTF_A8); - - if (fontTexture) - { - m_fontTextureId = fontTexture->GetTextureID(); - io.Fonts->SetTexID(static_cast(fontTexture)); - } + // Set the initial Display Size (gets updated each frame anyway) + io.DisplaySize.x = 1920; + io.DisplaySize.y = 1080; // Broadcast ImGui Ready to Listeners ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnImGuiInitialize); @@ -273,18 +254,6 @@ void ImGuiManager::Shutdown() InputTextEventListener::Disconnect(); AzFramework::WindowNotificationBus::Handler::BusDisconnect(); - if (!AZ::Interface::Get()) - { - // Destroy ImGui Font Texture - if (gEnv->pRenderer && m_fontTextureId > 0) - { - ImGui::ImGuiContextScope contextScope(m_imguiContext); - ImGuiIO& io = ImGui::GetIO(); - io.Fonts->SetTexID(nullptr); - gEnv->pRenderer->RemoveTexture(m_fontTextureId); - } - } - // Finally, destroy the ImGui Context. ImGui::DestroyContext(m_imguiContext); } @@ -386,7 +355,6 @@ void ImGuiManager::Render() io.DeltaTime = gEnv->pTimer->GetFrameTime(); //// END FROM PREUPDATE - IRenderer* renderer = gEnv->pRenderer; TransformationMatrices backupSceneMatrices; AZ::u32 backBufferWidth = 0; @@ -397,11 +365,6 @@ void ImGuiManager::Render() backBufferWidth = m_windowSize.m_width; backBufferHeight = m_windowSize.m_height; } - else - { - backBufferWidth = renderer->GetBackBufferWidth(); - backBufferHeight = renderer->GetBackBufferHeight(); - } // Find ImGui Render Resolution. int renderRes[2]; @@ -441,25 +404,9 @@ void ImGuiManager::Render() m_lastRenderResolution.x = static_cast(renderRes[0]); m_lastRenderResolution.y = static_cast(renderRes[1]); - if (!AZ::Interface::Get()) - { - // Configure Renderer for 2D ImGui Rendering - renderer->SetCullMode(R_CULL_DISABLE); - renderer->Set2DMode(renderRes[0], renderRes[1], backupSceneMatrices); - renderer->SetColorOp(eCO_REPLACE, eCO_MODULATE, eCA_Diffuse, DEF_TEXARG0); - renderer->SetSrgbWrite(false); - renderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST); - } - // Render! RenderImGuiBuffers(scaleRects); - if (!AZ::Interface::Get()) - { - // Cleanup Renderer Settings - renderer->Unset2DMode(backupSceneMatrices); - } - // Clear the simulated backspace key if (m_simulateBackspaceKeyPressed) { @@ -793,91 +740,6 @@ void ImGuiManager::RenderImGuiBuffers(const ImVec2& scaleRects) { OtherActiveImGuiRequestBus::Broadcast(&OtherActiveImGuiRequestBus::Events::RenderImGuiBuffers, *drawData); } - else - { - IRenderer* renderer = gEnv->pRenderer; - - // Expand vertex buffer if necessary - m_vertBuffer.reserve(drawData->TotalVtxCount); - if (m_vertBuffer.size() < drawData->TotalVtxCount) - { - m_vertBuffer.insert(m_vertBuffer.end(), - drawData->TotalVtxCount - m_vertBuffer.size(), - SVF_P3F_C4B_T2F()); - } - - // Expand index buffer if necessary - m_idxBuffer.reserve(drawData->TotalIdxCount); - if (m_idxBuffer.size() < drawData->TotalIdxCount) - { - m_idxBuffer.insert(m_idxBuffer.end(), drawData->TotalIdxCount - m_idxBuffer.size(), 0); - } - - // Process each draw command list individually - for (int n = 0; n < drawData->CmdListsCount; n++) - { - const ImDrawList* cmd_list = drawData->CmdLists[n]; - - // Cache max vert count for easy access - int numVerts = cmd_list->VtxBuffer.Size; - - // Copy command list verts into buffer - for (int i = 0; i < numVerts; ++i) - { - const ImDrawVert& imguiVert = cmd_list->VtxBuffer[i]; - SVF_P3F_C4B_T2F& vert = m_vertBuffer[i]; - - vert.xyz = Vec3(imguiVert.pos.x, imguiVert.pos.y, 0.0f); - // Convert color from RGBA to ARGB - vert.color.dcolor = (imguiVert.col & 0xFF00FF00) - | ((imguiVert.col & 0xFF0000) >> 16) - | ((imguiVert.col & 0xFF) << 16); - vert.st = Vec2(imguiVert.uv.x, imguiVert.uv.y); - } - - // Copy command list indices into buffer - for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i) - { - m_idxBuffer[i] = uint16(cmd_list->IdxBuffer[i]); - } - - // Use offset pointer to step along rendering operation - uint16* idxBufferDataOffset = m_idxBuffer.data(); - - // Process each draw command individually - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - - // Defer to user rendering callback, if appropriate - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - // Otherwise render our buffers - else - { - int textureId = ((ITexture*)pcmd->TextureId)->GetTextureID(); - renderer->SetTexture(textureId); - renderer->SetScissor((int)pcmd->ClipRect.x, - (int)(pcmd->ClipRect.y), - (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), - (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); - renderer->DrawDynVB(m_vertBuffer.data(), - idxBufferDataOffset, - numVerts, - pcmd->ElemCount, - prtTriangleList); - } - - // Update offset pointer into command list's index buffer - idxBufferDataOffset += pcmd->ElemCount; - } - } - - // Reset scissor usage on renderer - renderer->SetScissor(); - } } } diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp index e74e58b854..c157189400 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp @@ -23,7 +23,7 @@ namespace ImGui { - // Resolution Widths to recommend for usage for both LumberYard Rendering and/or ImGui Rendering + // Resolution Widths to recommend for usage for both O3DE Rendering and/or ImGui Rendering static int s_renderResolutionWidths[7] = { 800, 1280, 1600, 1920, 2560, 3440, 3840 }; static int s_renderAspectRatios[4][2] = { {16,9}, {16,10}, {43,18}, {4,3} }; static const char* s_toggleTelemetryConsoleCmd = "radtm_ToggleEnabled 1"; @@ -158,8 +158,8 @@ namespace ImGui // Add some space before the first menu so it won't overlap with view control buttons ImGui::SetCursorPosX(40.f); - // Main LumberYard menu - if (ImGui::BeginMenu("LumberYard")) + // Main Open 3D Engine menu + if (ImGui::BeginMenu("Open 3D Engine")) { // Asset Explorer if (ImGui::MenuItem("Asset Explorer")) diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h index e65ac9c61c..c6d03eae54 100644 --- a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h +++ b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h @@ -50,7 +50,7 @@ namespace ImageProcessing const BuilderSettings* GetBuilderSetting(const PlatformName& platform); /** - * Attempts to translate a legacy preset name into Lumberyard preset name. + * Attempts to translate a legacy preset name into Open 3D Engine preset name. * @param legacy preset name string * @return A translated preset name. If no translation is available, returns the same value as input argument. */ diff --git a/Gems/ImageProcessing/Code/Source/Converters/Cubemap.h b/Gems/ImageProcessing/Code/Source/Converters/Cubemap.h index 0bf7b5db7a..cc036814e8 100644 --- a/Gems/ImageProcessing/Code/Source/Converters/Cubemap.h +++ b/Gems/ImageProcessing/Code/Source/Converters/Cubemap.h @@ -16,7 +16,7 @@ namespace ImageProcessing { - // note: lumberyard is right hand Z up coordinate + // note: O3DE is right hand Z up coordinate // please don't change the order of the enum since we are using it to match the face id defined in AMD's CubemapGen // and they are using left hand Y up coordinate enum CubemapFace diff --git a/Gems/InAppPurchases/Code/Source/InAppPurchasesSystemComponent.cpp b/Gems/InAppPurchases/Code/Source/InAppPurchasesSystemComponent.cpp index 02487e4869..99fbea129c 100644 --- a/Gems/InAppPurchases/Code/Source/InAppPurchasesSystemComponent.cpp +++ b/Gems/InAppPurchases/Code/Source/InAppPurchasesSystemComponent.cpp @@ -212,7 +212,7 @@ namespace InAppPurchases } else { - AZ_Warning("LumberyardInAppPurchases", false, "The JSON string provided does not contain an array named ProductIds!(Property *has* to be an array)"); + AZ_Warning("O3DEInAppPurchases", false, "The JSON string provided does not contain an array named ProductIds!(Property *has* to be an array)"); } } } diff --git a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesApple.mm b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesApple.mm index 99d59e183e..21aec6df4b 100644 --- a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesApple.mm +++ b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesApple.mm @@ -43,7 +43,7 @@ namespace if (!payload) { - AZ_TracePrintf("LumberyardInAppPurchases", "Payload is null!"); + AZ_TracePrintf("O3DEInAppPurchases", "Payload is null!"); return false; } @@ -174,12 +174,12 @@ namespace InAppPurchases } else { - AZ_TracePrintf("LumberyardInAppPurchases", "Unable to find any product ids in product_ids.plist"); + AZ_TracePrintf("O3DEInAppPurchases", "Unable to find any product ids in product_ids.plist"); } } else { - AZ_TracePrintf("LumberyardInAppPurchases", "product_ids.plist does not exist"); + AZ_TracePrintf("O3DEInAppPurchases", "product_ids.plist does not exist"); } } @@ -217,7 +217,7 @@ namespace InAppPurchases FILE* fp = fopen(receiptPath, "rb"); if (!fp) { - AZ_TracePrintf("LumberyardInAppPurchases", "Unable to open receipt!"); + AZ_TracePrintf("O3DEInAppPurchases", "Unable to open receipt!"); return; } @@ -225,7 +225,7 @@ namespace InAppPurchases fclose(fp); if (!p7) { - AZ_TracePrintf("LumberyardInAppPurchases", "PKCS7 container is null!"); + AZ_TracePrintf("O3DEInAppPurchases", "PKCS7 container is null!"); return; } diff --git a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm index 9583eafd88..0eeb4a9480 100644 --- a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm +++ b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm @@ -75,7 +75,7 @@ if (userNameLength > UINT32_MAX) { - AZ_TracePrintf("LumberyardInAppPurchases", "Username too long to hash:%s", [userName cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Username too long to hash:%s", [userName cStringUsingEncoding:NSASCIIStringEncoding]); return nil; } @@ -137,7 +137,7 @@ { for (NSString* invalidId in response.invalidProductIdentifiers) { - AZ_TracePrintf("LumberyardInAppPurchases:", "Invalid product ID:", [invalidId cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases:", "Invalid product ID:", [invalidId cStringUsingEncoding:NSASCIIStringEncoding]); } InAppPurchases::InAppPurchasesInterface::GetInstance()->GetCache()->ClearCachedProductDetails(); @@ -192,7 +192,7 @@ } else { - AZ_TracePrintf("LumberyardInAppPurchases", "Invalid product ID:%s", [productId cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Invalid product ID:%s", [productId cStringUsingEncoding:NSASCIIStringEncoding]); } } @@ -206,13 +206,13 @@ { case SKPaymentTransactionStatePurchasing: { - AZ_TracePrintf("LumberyardInAppPurchases", "Transaction in progress"); + AZ_TracePrintf("O3DEInAppPurchases", "Transaction in progress"); break; } case SKPaymentTransactionStateDeferred: { - AZ_TracePrintf("LumberyardInAppPurchases", "Transaction deferred"); + AZ_TracePrintf("O3DEInAppPurchases", "Transaction deferred"); break; } @@ -220,7 +220,7 @@ { if ([self.m_unfinishedTransactions containsObject:transaction] == false) { - AZ_TracePrintf("LumberyardInAppPurchases", "Transaction failed! Error: %s", [[transaction.error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Transaction failed! Error: %s", [[transaction.error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); InAppPurchases::PurchasedProductDetailsApple* productDetails = [self parseTransactionDetails:transaction isRestored:false]; productDetails->SetPurchaseState(InAppPurchases::PurchaseState::FAILED); [self.m_unfinishedTransactions addObject:transaction]; @@ -234,7 +234,7 @@ { if ([self.m_unfinishedTransactions containsObject:transaction] == false) { - AZ_TracePrintf("LumberyardInAppPurchases", "Transaction succeeded"); + AZ_TracePrintf("O3DEInAppPurchases", "Transaction succeeded"); InAppPurchases::PurchasedProductDetailsApple* productDetails = [self parseTransactionDetails:transaction isRestored:false]; productDetails->SetPurchaseState(InAppPurchases::PurchaseState::PURCHASED); InAppPurchases::InAppPurchasesInterface::GetInstance()->GetCache()->AddPurchasedProductDetailsToCache(productDetails); @@ -255,7 +255,7 @@ { if ([self.m_unfinishedTransactions containsObject:transaction] == false) { - AZ_TracePrintf("LumberyardInAppPurchases", "Transaction restored"); + AZ_TracePrintf("O3DEInAppPurchases", "Transaction restored"); InAppPurchases::PurchasedProductDetailsApple* productDetails = [self parseTransactionDetails:transaction isRestored:true]; productDetails->SetPurchaseState(InAppPurchases::PurchaseState::RESTORED); InAppPurchases::InAppPurchasesInterface::GetInstance()->GetCache()->AddPurchasedProductDetailsToCache(productDetails); @@ -292,7 +292,7 @@ } } - AZ_TracePrintf("LumberyardInAppPurchases", "No unfinished transaction found with ID: %s", [transactionId cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "No unfinished transaction found with ID: %s", [transactionId cStringUsingEncoding:NSASCIIStringEncoding]); } -(void) downloadAppleHostedContentAndFinishTransaction:(NSString*) transactionId @@ -320,7 +320,7 @@ } else { - AZ_TracePrintf("LumberyardInAppPurchases", "No unfinished transaction found with ID: %s", [transactionId cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "No unfinished transaction found with ID: %s", [transactionId cStringUsingEncoding:NSASCIIStringEncoding]); } } @@ -360,7 +360,7 @@ case SKDownloadStateFailed: { - AZ_TracePrintf("LumberyardInAppPurchases", "Download failed with error: %s", [[download.error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Download failed with error: %s", [[download.error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); AZStd::string transactionId = [download.transaction.transactionIdentifier cStringUsingEncoding:NSASCIIStringEncoding]; AZStd::string contentId = [download.contentIdentifier UTF8String]; EBUS_EVENT(InAppPurchases::InAppPurchasesResponseBus, HostedContentDownloadFailed, transactionId, contentId); @@ -370,7 +370,7 @@ case SKDownloadStateCancelled: { - AZ_TracePrintf("LumberyardInAppPurchases", "Download cancelled: %s", [download.contentIdentifier cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Download cancelled: %s", [download.contentIdentifier cStringUsingEncoding:NSASCIIStringEncoding]); [self.m_unfinishedDownloads removeObject:download.contentIdentifier]; } break; @@ -402,7 +402,7 @@ -(void) request:(SKRequest*) request didFailWithError:(NSError*) error { - AZ_TracePrintf("LumberyardInAppPurchases", "Request failed with error: %s", [[error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); + AZ_TracePrintf("O3DEInAppPurchases", "Request failed with error: %s", [[error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); } -(void) requestDidFinish:(SKRequest *)request diff --git a/Gems/LmbrCentral/Code/Source/Builders/CopyDependencyBuilder/XmlBuilderWorker/XmlBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/CopyDependencyBuilder/XmlBuilderWorker/XmlBuilderWorker.cpp index 1da0759275..f50526c67f 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/CopyDependencyBuilder/XmlBuilderWorker/XmlBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/CopyDependencyBuilder/XmlBuilderWorker/XmlBuilderWorker.cpp @@ -32,7 +32,7 @@ namespace CopyDependencyBuilder { if (!AzFramework::StringFunc::Path::HasExtension(fileName.c_str())) { - // Lumberyard makes use of some files without extensions, only replace the extension if there is an expected extension. + // Open 3D Engine makes use of some files without extensions, only replace the extension if there is an expected extension. if (!expectedExtension.empty()) { AzFramework::StringFunc::Path::ReplaceExtension(fileName, expectedExtension.c_str()); diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp index 9407d639cb..59cd195679 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp @@ -285,7 +285,7 @@ namespace MaterialBuilder } else if (hasExtension) { - AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s as the path is not to a supported texture format. Please make sure that textures in materials are formats supported by Lumberyard.", aliasedPath.c_str()); + AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s as the path is not to a supported texture format. Please make sure that textures in materials are formats supported by Open 3D Engine.", aliasedPath.c_str()); return false; } diff --git a/Gems/LmbrCentral/Code/Source/Shape/CapsuleShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/CapsuleShapeComponent.cpp index 1c54e81b72..46eb69dbd8 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/CapsuleShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/CapsuleShapeComponent.cpp @@ -26,14 +26,12 @@ namespace LmbrCentral { provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); provided.push_back(AZ_CRC("CapsuleShapeService", 0x9bc1122c)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void CapsuleShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); incompatible.push_back(AZ_CRC("CapsuleShapeService", 0x9bc1122c)); - incompatible.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void CapsuleShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) diff --git a/Gems/LmbrCentral/Code/Source/Shape/DiskShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/DiskShapeComponent.cpp index 50cececd88..2d0673f299 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/DiskShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/DiskShapeComponent.cpp @@ -22,14 +22,12 @@ namespace LmbrCentral { provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); provided.push_back(AZ_CRC("DiskShapeService", 0xd90c482b)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void DiskShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); incompatible.push_back(AZ_CRC("DiskShapeService", 0xd90c482b)); - incompatible.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void DiskShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorCapsuleShapeComponent.h b/Gems/LmbrCentral/Code/Source/Shape/EditorCapsuleShapeComponent.h index 897c627a7e..6bb34b1b9e 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorCapsuleShapeComponent.h +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorCapsuleShapeComponent.h @@ -38,7 +38,6 @@ namespace LmbrCentral { EditorBaseShapeComponent::GetProvidedServices(provided); provided.push_back(AZ_CRC("CapsuleShapeService", 0x9bc1122c)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } // EditorComponentBase diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorDiskShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorDiskShapeComponent.cpp index a6c4d35a88..606a26ec52 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorDiskShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorDiskShapeComponent.cpp @@ -53,7 +53,6 @@ namespace LmbrCentral { EditorBaseShapeComponent::GetProvidedServices(provided); provided.push_back(AZ_CRC("DiskShapeService", 0xd90c482b)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void EditorDiskShapeComponent::Init() diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponent.cpp index 1ffeeebc31..11fc04b1db 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponent.cpp @@ -32,7 +32,6 @@ namespace LmbrCentral provided.push_back(AZ_CRC("PolygonPrismShapeService", 0x1cbc4ed4)); provided.push_back(AZ_CRC("VariableVertexContainerService", 0x70c58740)); provided.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void EditorPolygonPrismShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) @@ -40,7 +39,6 @@ namespace LmbrCentral EditorBaseShapeComponent::GetIncompatibleServices(incompatible); incompatible.push_back(AZ_CRC("VariableVertexContainerService", 0x70c58740)); incompatible.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - incompatible.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void EditorPolygonPrismShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorQuadShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorQuadShapeComponent.cpp index 52835b68c2..e4732494bd 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorQuadShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorQuadShapeComponent.cpp @@ -53,7 +53,6 @@ namespace LmbrCentral { EditorBaseShapeComponent::GetProvidedServices(provided); provided.push_back(AZ_CRC("QuadShapeService", 0xe449b0fc)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void EditorQuadShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorSphereShapeComponent.h b/Gems/LmbrCentral/Code/Source/Shape/EditorSphereShapeComponent.h index 294b21487c..f4a80d91ed 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorSphereShapeComponent.h +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorSphereShapeComponent.h @@ -42,7 +42,6 @@ namespace LmbrCentral { EditorBaseShapeComponent::GetProvidedServices(provided); provided.push_back(AZ_CRC("SphereShapeService", 0x90c8dc80)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } private: diff --git a/Gems/LmbrCentral/Code/Source/Shape/QuadShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/QuadShapeComponent.cpp index 05b9c3c03d..653cf967f6 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/QuadShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/QuadShapeComponent.cpp @@ -22,14 +22,12 @@ namespace LmbrCentral { provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); provided.push_back(AZ_CRC("QuadShapeService", 0xe449b0fc)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void QuadShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); incompatible.push_back(AZ_CRC("QuadShapeService", 0xe449b0fc)); - incompatible.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void QuadShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) diff --git a/Gems/LmbrCentral/Code/Source/Shape/SphereShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/SphereShapeComponent.cpp index 2f4c40cfed..3bddc9b695 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/SphereShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/SphereShapeComponent.cpp @@ -23,14 +23,12 @@ namespace LmbrCentral { provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); provided.push_back(AZ_CRC("SphereShapeService", 0x90c8dc80)); - provided.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void SphereShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); incompatible.push_back(AZ_CRC("SphereShapeService", 0x90c8dc80)); - incompatible.push_back(AZ_CRC("AreaLightShapeService", 0x68ea78dc)); } void SphereShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp index 6c9090ab3d..13f4828da7 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp @@ -28,7 +28,7 @@ #include "UiAVCustomizeTrackColorsDlg.h" #include "UiAnimViewDialog.h" -#include +#include #include #include diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp index 10d7bf6887..1a26dd4744 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp @@ -13,7 +13,7 @@ #include "UiCanvasEditor_precompiled.h" #include "UiAVEventsDialog.h" -#include +#include #include "UiAnimViewUndo.h" #include "StringDlg.h" #include "UiAnimViewSequence.h" diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVSequenceProps.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVSequenceProps.cpp index 9b33bec009..afafd5d332 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVSequenceProps.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVSequenceProps.cpp @@ -22,7 +22,7 @@ #include "Objects/BaseObject.h" #include "QtUtilWin.h" -#include +#include #include diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp index 29d487693e..8c5b222c16 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp @@ -21,7 +21,7 @@ #include "UiAnimViewTrack.h" #include "AnimationContext.h" -#include +#include #include #if defined(Q_OS_WIN) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp index 65010cc0dd..7204102deb 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp @@ -1075,8 +1075,6 @@ void CUiAnimViewDialog::OnDelSequence() AZ_Error("UiAnimViewDialog", false, "Could not find sequence"); return; } - - UpdateActions(); } } @@ -1568,7 +1566,7 @@ void CUiAnimViewDialog::ReadMiscSettings() ////////////////////////////////////////////////////////////////////////// void CUiAnimViewDialog::SaveLayouts() { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("UiAnimView"); QByteArray stateData = this->saveState(); settings.setValue("layout", stateData); @@ -1583,7 +1581,7 @@ void CUiAnimViewDialog::SaveLayouts() ////////////////////////////////////////////////////////////////////////// void CUiAnimViewDialog::ReadLayouts() { - QSettings settings("Amazon", "Lumberyard"); + QSettings settings("Amazon", "O3DE"); settings.beginGroup("UiAnimView"); if (settings.contains("layout")) { diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp index 68503dcfbc..51e298605a 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp @@ -23,7 +23,7 @@ #include -#include +#include ///////////////////////////////////////////////////////////////////////////// // CUiAnimViewFindDlg dialog diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewKeyPropertiesDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewKeyPropertiesDlg.cpp index 726d920557..a202a4239d 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewKeyPropertiesDlg.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewKeyPropertiesDlg.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp index 3eec74372c..18061701b8 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp @@ -14,7 +14,7 @@ #include "UiCanvasEditor_precompiled.h" #include "UiAnimViewNewSequenceDialog.h" #include "Animation/UiAnimViewSequenceManager.h" -#include +#include #include #include "QtUtil.h" diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index 2faf3a9a6f..c5d8c8c740 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -301,7 +301,7 @@ enum EMenuItem // The 'MI' represents a Menu Item. -#include +#include ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Editor/EditorCommon.h b/Gems/LyShine/Code/Editor/EditorCommon.h index 42f77e8a08..2d2f08c3a7 100644 --- a/Gems/LyShine/Code/Editor/EditorCommon.h +++ b/Gems/LyShine/Code/Editor/EditorCommon.h @@ -166,10 +166,10 @@ enum class FusibleCommand // IMPORTANT: This is NOT the permanent location for these values. #define AZ_QCOREAPPLICATION_SETTINGS_ORGANIZATION_NAME "Amazon" -#define AZ_QCOREAPPLICATION_SETTINGS_APPLICATION_NAME "Lumberyard" +#define AZ_QCOREAPPLICATION_SETTINGS_APPLICATION_NAME "Open 3D Engine" // See: http://en.wikipedia.org/wiki/Internet_media_type#Prefix_x -#define UICANVASEDITOR_MIMETYPE "application/x-amazon-lumberyard-uicanvaseditor" +#define UICANVASEDITOR_MIMETYPE "application/x-amazon-o3de-uicanvaseditor" bool ClipboardContainsOurDataType(); diff --git a/Gems/LyShine/Code/Editor/LyShineEditorSystemComponent.cpp b/Gems/LyShine/Code/Editor/LyShineEditorSystemComponent.cpp index 13a77f7e53..c0e9b7aaac 100644 --- a/Gems/LyShine/Code/Editor/LyShineEditorSystemComponent.cpp +++ b/Gems/LyShine/Code/Editor/LyShineEditorSystemComponent.cpp @@ -165,7 +165,7 @@ namespace LyShineEditor { if (AZStd::wildcard_match("*.uicanvas", fullSourceFileName)) { - openers.push_back({ "Lumberyard_UICanvas_Editor", + openers.push_back({ "O3DE_UICanvas_Editor", "Open in UI Canvas Editor...", QIcon(), [](const char* fullSourceFileNameInCallback, const AZ::Uuid& /*sourceUUID*/) diff --git a/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp b/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp index bd0dfea301..082545ada2 100644 --- a/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp @@ -138,7 +138,7 @@ namespace return fontFamily; } - //! \brief Verify fonts that ship with Lumberyard load correctly. + //! \brief Verify fonts that ship with Open 3D Engine load correctly. //! //! This test depends on the LyShineExamples and UiBasics gems being //! included in the project. diff --git a/Gems/LyShine/Code/Source/UiCanvasFileObject.cpp b/Gems/LyShine/Code/Source/UiCanvasFileObject.cpp index ca238c3ce9..bb93bf3597 100644 --- a/Gems/LyShine/Code/Source/UiCanvasFileObject.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasFileObject.cpp @@ -101,16 +101,6 @@ UiCanvasFileObject* UiCanvasFileObject::LoadCanvasFromStream(AZ::IO::GenericStre stream.GetFilename()); } } - else if (fileFormat == FileFormat::ReallyOld) - { - // We never shipped anything to customers using this ancient serialization format - // Canvas files saved on 12/3/2015 used the newer serialization format. - // R1 FC was 12/14/2015 - // So this message is only for internal Lumberyard users who may have a REALLY old - // canvas file lying around. - AZ_Warning("UI", false, "UI canvas file: %s is in an obsolete format, use an earlier lumberyard version (prior to v1.7) to open and resave it.", - stream.GetFilename()); - } else { // This does not look like an old format canvas file so treat it as new format diff --git a/Gems/Maestro/Code/Source/MaestroSystemComponent.cpp b/Gems/Maestro/Code/Source/MaestroSystemComponent.cpp index 17321f06f4..e300607fd7 100644 --- a/Gems/Maestro/Code/Source/MaestroSystemComponent.cpp +++ b/Gems/Maestro/Code/Source/MaestroSystemComponent.cpp @@ -57,7 +57,7 @@ namespace Maestro if (AZ::EditContext* ec = serialize->GetEditContext()) { - ec->Class("Maestro", "Provides the Lumberyard Cinematics Service") + ec->Class("Maestro", "Provides the Open 3D Engine Cinematics Service") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") // ->Attribute(AZ::Edit::Attributes::Category, "") Set a category ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index f5bbbce8f2..dde5e387f6 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -21,8 +21,6 @@ ly_add_target( Source AZ::AzNetworking . - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore @@ -51,8 +49,6 @@ ly_add_target( PRIVATE Source . - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE Gem::Multiplayer.Static diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp index cfb1286496..a74001d647 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp @@ -133,7 +133,7 @@ namespace Multiplayer AZStd::vector gatheredEntries; AZ::Sphere awarenessSphere = AZ::Sphere(controlledEntityPosition, sv_ClientAwarenessRadius); - AZ::Interface::Get()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilitySystem::NodeData& nodeData) + AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size()); for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) diff --git a/Gems/MultiplayerCompression/Code/CMakeLists.txt b/Gems/MultiplayerCompression/Code/CMakeLists.txt index 96761c3b1e..58ce546543 100644 --- a/Gems/MultiplayerCompression/Code/CMakeLists.txt +++ b/Gems/MultiplayerCompression/Code/CMakeLists.txt @@ -19,8 +19,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC 3rdParty::lz4 @@ -36,8 +34,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE Gem::MultiplayerCompression.Static diff --git a/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake b/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake index 6afc02a90d..e6c7c23614 100644 --- a/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake +++ b/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake @@ -9,6 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_associate_package(PACKAGE_NAME NvCloth-1.1.6-rev1-multiplatform TARGETS NvCloth PACKAGE_HASH 05fc62634ca28644e7659a89e97f4520d791e6ddf4b66f010ac669e4e2ed4454) - set(PAL_TRAIT_NVCLOTH_USE_STUB FALSE) diff --git a/Gems/NvCloth/Code/Source/System/SystemComponent.cpp b/Gems/NvCloth/Code/Source/System/SystemComponent.cpp index 097b3bc885..b73622b883 100644 --- a/Gems/NvCloth/Code/Source/System/SystemComponent.cpp +++ b/Gems/NvCloth/Code/Source/System/SystemComponent.cpp @@ -51,7 +51,7 @@ namespace NvCloth } }; - // Implementation of the error callback interface directing nvcloth library errors to Lumberyard error output. + // Implementation of the error callback interface directing nvcloth library errors to Open 3D Engine error output. class AzClothErrorCallback : public physx::PxErrorCallback { @@ -91,7 +91,7 @@ namespace NvCloth physx::PxErrorCode::Enum m_lastError = physx::PxErrorCode::eNO_ERROR; }; - // Implementation of the assert handler interface directing nvcloth asserts to Lumberyard assertion system. + // Implementation of the assert handler interface directing nvcloth asserts to Open 3D Engine assertion system. class AzClothAssertHandler : public nv::cloth::PxAssertHandler { diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index e9a60ab903..ac5fd902c2 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -71,9 +71,6 @@ ly_add_target( if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) - ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) - ly_add_target( NAME PhysX.Editor.Static STATIC NAMESPACE Gem diff --git a/Gems/PhysX/Code/Source/System/PhysXAllocator.h b/Gems/PhysX/Code/Source/System/PhysXAllocator.h index 832b113acc..5a18c93069 100644 --- a/Gems/PhysX/Code/Source/System/PhysXAllocator.h +++ b/Gems/PhysX/Code/Source/System/PhysXAllocator.h @@ -31,7 +31,7 @@ namespace PhysX const char* GetDescription() const override { return "PhysX general memory allocator"; } }; - //! Implementation of the PhysX memory allocation callback interface using Lumberyard allocator. + //! Implementation of the PhysX memory allocation callback interface using Open 3D Engine allocator. class PxAzAllocatorCallback : public physx::PxAllocatorCallback { diff --git a/Gems/PhysX/Code/Source/System/PhysXCpuDispatcher.h b/Gems/PhysX/Code/Source/System/PhysXCpuDispatcher.h index 2505eaeba5..df94f094ab 100644 --- a/Gems/PhysX/Code/Source/System/PhysXCpuDispatcher.h +++ b/Gems/PhysX/Code/Source/System/PhysXCpuDispatcher.h @@ -16,7 +16,7 @@ namespace PhysX { - //! CPU dispatcher which directs tasks submitted by PhysX to the Lumberyard scheduling system. + //! CPU dispatcher which directs tasks submitted by PhysX to the Open 3D Engine scheduling system. class PhysXCpuDispatcher : public physx::PxCpuDispatcher { @@ -32,6 +32,6 @@ namespace PhysX physx::PxU32 getWorkerCount() const override; }; - //! Creates a CPU dispatcher which directs tasks submitted by PhysX to the Lumberyard scheduling system. + //! Creates a CPU dispatcher which directs tasks submitted by PhysX to the Open 3D Engine scheduling system. PhysXCpuDispatcher* PhysXCpuDispatcherCreate(); } // namespace PhysX diff --git a/Gems/PhysX/Code/Source/System/PhysXJob.h b/Gems/PhysX/Code/Source/System/PhysXJob.h index 244cb9b92a..ad388bb12d 100644 --- a/Gems/PhysX/Code/Source/System/PhysXJob.h +++ b/Gems/PhysX/Code/Source/System/PhysXJob.h @@ -17,7 +17,7 @@ namespace PhysX { - //! Handles PhysX tasks in the Lumberyard job scheduler. + //! Handles PhysX tasks in the Open 3D Engine job scheduler. class PhysXJob : public AZ::Job { diff --git a/Gems/PhysX/Code/Source/System/PhysXSdkCallbacks.h b/Gems/PhysX/Code/Source/System/PhysXSdkCallbacks.h index 8b2d47ec4a..c8993e9b52 100644 --- a/Gems/PhysX/Code/Source/System/PhysXSdkCallbacks.h +++ b/Gems/PhysX/Code/Source/System/PhysXSdkCallbacks.h @@ -15,7 +15,7 @@ namespace PhysX { - //! Implementation of the PhysX error callback interface directing errors to Lumberyard error output. + //! Implementation of the PhysX error callback interface directing errors to Open 3D Engine error output. class PxAzErrorCallback : public physx::PxErrorCallback { diff --git a/Gems/PhysX/Code/Source/SystemComponent.h b/Gems/PhysX/Code/Source/SystemComponent.h index 668f12e0c0..c074a2032d 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.h +++ b/Gems/PhysX/Code/Source/SystemComponent.h @@ -53,7 +53,7 @@ namespace PhysX /// System component for PhysX. /// The system component handles underlying tasks such as initialization and shutdown of PhysX, managing a - /// Lumberyard memory allocator for PhysX allocations, scheduling for PhysX jobs, and connections to the PhysX + /// Open 3D Engine memory allocator for PhysX allocations, scheduling for PhysX jobs, and connections to the PhysX /// Visual Debugger. It also owns fundamental PhysX objects which manage worlds, rigid bodies, shapes, materials, /// constraints etc., and perform cooking (processing assets such as meshes and heightfields ready for use in PhysX). class SystemComponent diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.h b/Gems/PhysXDebug/Code/Source/SystemComponent.h index 453a80e109..66f546c661 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.h +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.h @@ -161,7 +161,7 @@ namespace PhysXDebug /// Initialise the PhysX debug draw colors based on defaults. void InitPhysXColorMappings(); - /// Register debug drawing PhysX commands with Lumberyard console during game mode. + /// Register debug drawing PhysX commands with Open 3D Engine console during game mode. void RegisterCommands(); /// Draw the culling box being used by the viewport. diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp index fffe6ddfd5..2bb0d8aaf3 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp @@ -185,10 +185,13 @@ namespace UnitTest // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash // in the unit tests. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + + AZ::Data::AssetManager::Instance().RegisterHandler(&m_assetHandler, azrtti_typeid()); } void PrefabBuilderTests::TearDown() { + AZ::Data::AssetManager::Instance().UnregisterHandler(&m_assetHandler); m_testComponentDescriptor = nullptr; m_app.Stop(); diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.h b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.h index 0873ddfd6a..4a174dad5b 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.h +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.h @@ -15,13 +15,14 @@ #include #include #include +#include #include namespace UnitTest { - struct VersionChangingData : AZ::Data::AssetData + struct VersionChangingData final : AZ::Data::AssetData { - AZ_TYPE_INFO(VersionChangingData, "{E3A37E19-AE61-4C2F-809E-03B4D83261E8}"); + AZ_RTTI(VersionChangingData, "{E3A37E19-AE61-4C2F-809E-03B4D83261E8}", AZ::Data::AssetData); static void Reflect(AZ::ReflectContext* context) { @@ -34,9 +35,9 @@ namespace UnitTest inline static int m_version = 0; }; - struct TestAsset : AZ::Data::AssetData + struct TestAsset final : AZ::Data::AssetData { - AZ_TYPE_INFO(TestAsset, "{8E736462-5424-4720-A2D9-F71DFC5905E3}"); + AZ_RTTI(TestAsset, "{8E736462-5424-4720-A2D9-F71DFC5905E3}", AZ::Data::AssetData); static void Reflect(AZ::ReflectContext* context) { @@ -47,7 +48,35 @@ namespace UnitTest } }; - struct TestComponent : AZ::Component + struct TestAssetHandler final : AZ::Data::AssetHandler + { + public: + AZ::Data::AssetPtr CreateAsset( + [[maybe_unused]] const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override + { + return aznew TestAsset(); + } + + void DestroyAsset(AZ::Data::AssetPtr ptr) override + { + delete ptr; + } + + void GetHandledAssetTypes(AZStd::vector& assetTypes) override + { + assetTypes.push_back(azrtti_typeid()); + } + + AZ::Data::AssetHandler::LoadResult LoadAssetData( + [[maybe_unused]] const AZ::Data::Asset& asset, + [[maybe_unused]] AZStd::shared_ptr stream, + [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override + { + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } + }; + + struct TestComponent final : AZ::Component { AZ_COMPONENT(TestComponent, "{E3982C6A-0B01-4B04-A3E2-D95729D4B9C6}"); @@ -81,7 +110,7 @@ namespace UnitTest AZStd::vector m_bufferData; }; - struct TestPrefabBuilderComponent : AZ::Prefab::PrefabBuilderComponent + struct TestPrefabBuilderComponent final : AZ::Prefab::PrefabBuilderComponent { protected: AZStd::unique_ptr GetOutputStream(const AZ::IO::Path& path) const override; @@ -95,5 +124,6 @@ namespace UnitTest AzToolsFramework::ToolsApplication m_app; AZStd::unique_ptr m_testComponentDescriptor{}; + TestAssetHandler m_assetHandler; }; } diff --git a/Gems/PythonAssetBuilder/Code/Include/PythonAssetBuilder/PythonBuilderRequestBus.h b/Gems/PythonAssetBuilder/Code/Include/PythonAssetBuilder/PythonBuilderRequestBus.h index 2eeca4ffc8..4cf55a00a4 100644 --- a/Gems/PythonAssetBuilder/Code/Include/PythonAssetBuilder/PythonBuilderRequestBus.h +++ b/Gems/PythonAssetBuilder/Code/Include/PythonAssetBuilder/PythonBuilderRequestBus.h @@ -17,7 +17,7 @@ namespace PythonAssetBuilder { - //! A request bus to help produce Lumberyard asset data + //! A request bus to help produce Open 3D Engine asset data class PythonBuilderRequests : public AZ::EBusTraits { diff --git a/Gems/QtForPython/Code/Include/QtForPython/QtForPythonBus.h b/Gems/QtForPython/Code/Include/QtForPython/QtForPythonBus.h index 23142d38c5..32c8318fa2 100644 --- a/Gems/QtForPython/Code/Include/QtForPython/QtForPythonBus.h +++ b/Gems/QtForPython/Code/Include/QtForPython/QtForPythonBus.h @@ -30,7 +30,7 @@ namespace QtForPython //! The path of the Qt plugins such as /qtlibs/plugins AZStd::string m_qtPluginsFolder; - //! The 'winId' of the main Qt window in the Lumberyard editor + //! The 'winId' of the main Qt window in the Open 3D Engine editor AZ::u64 m_mainWindowId; }; diff --git a/Gems/SaveData/Code/Tests/SaveDataTest.cpp b/Gems/SaveData/Code/Tests/SaveDataTest.cpp index 422faa7a8e..65029c522e 100644 --- a/Gems/SaveData/Code/Tests/SaveDataTest.cpp +++ b/Gems/SaveData/Code/Tests/SaveDataTest.cpp @@ -90,7 +90,7 @@ char testSaveData[testSaveDataSize] = {'a', 'b', 'c', '1', '2', '3', 'x', 'y', ' AZStd::string GetTestSaveDataCustomDirectoryNameRelative() { - return "Amazon/Lumberyard/SaveDataTest"; + return "Amazon/O3DE/SaveDataTest"; } #if defined(AZ_PLATFORM_WINDOWS) diff --git a/Gems/SceneLoggingExample/Code/CMakeLists.txt b/Gems/SceneLoggingExample/Code/CMakeLists.txt index 56e0fdaa6a..8cd012c4c2 100644 --- a/Gems/SceneLoggingExample/Code/CMakeLists.txt +++ b/Gems/SceneLoggingExample/Code/CMakeLists.txt @@ -21,8 +21,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE . - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore @@ -38,8 +36,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE . - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE Gem::SceneLoggingExample.Static diff --git a/Gems/SceneLoggingExample/ReadMe.txt b/Gems/SceneLoggingExample/ReadMe.txt index 40c3d6c043..f7c398c78d 100644 --- a/Gems/SceneLoggingExample/ReadMe.txt +++ b/Gems/SceneLoggingExample/ReadMe.txt @@ -1,12 +1,12 @@ The Scene Logging Example demonstrates how to extend the SceneAPI by adding additional logging to the pipeline. The SceneAPI is -a collection of libraries that handle loading scene files and converting content to data that the Lumberyard engine and editor can load. +a collection of libraries that handle loading scene files and converting content to data that the Open 3D Engine and its editor can load. The following approach is used: 1. The FbxSceneBuilder and SceneData load and convert the scene file (for example, .fbx) into a graph that is stored in memory. 2. SceneCore and SceneData are used to create a manifest with instructions about how to export the file. 3. SceneData analyzes the manifest and memory graph and creates defaults. 4. Scene Settings allows updates to the manifest through a UI. - 5. The ResourceCompilerScene uses the instructions from the manifest and the data in the graph to create assets. These assets are ready for Lumberyard to use. + 5. The ResourceCompilerScene uses the instructions from the manifest and the data in the graph to create assets. These assets are ready for Open 3D Engine to use. The example gem demonstrates the following key features: - Initialization of the SceneAPI libraries. diff --git a/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp b/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp index 2521161605..bb39ea15df 100644 --- a/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp @@ -171,7 +171,7 @@ namespace AZ "Soft naming conventions", "Update the naming conventions to suit your project.") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement(AZ::Edit::UIHandlers::Default, &SceneProcessingConfigSystemComponent::m_UseCustomNormals, - "Use Custom Normals", "When enabled, Lumberyard will use the DCC assets custom or tangent space normals. When disabled, the normals will be averaged. This setting can be overridden on individual FBX asset settings.") + "Use Custom Normals", "When enabled, Open 3D Engine will use the DCC assets custom or tangent space normals. When disabled, the normals will be averaged. This setting can be overridden on individual FBX asset settings.") ->Attribute(AZ::Edit::Attributes::AutoExpand, false); } } diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index eab22ba14f..b14fd7d4c2 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -110,12 +110,12 @@ namespace ScriptCanvasEditor { static const char* GetMimeType() { - return "application/x-lumberyard-scriptcanvas"; + return "application/x-o3de-scriptcanvas"; } static const char* GetWrappedNodeGroupingMimeType() { - return "application/x-lumberyard-scriptcanvas-wrappednodegrouping"; + return "application/x-03de-scriptcanvas-wrappednodegrouping"; } } @@ -1884,7 +1884,7 @@ namespace ScriptCanvasEditor AZStd::any* userData = nullptr; GraphCanvas::NodeRequestBus::EventResult(userData, nodeId, &GraphCanvas::NodeRequests::GetUserData); AZ::EntityId scSourceNodeId = (userData && userData->is()) ? *AZStd::any_cast(userData) : AZ::EntityId(); - + ScriptCanvas::Nodes::Core::FunctionDefinitionNode* nodeling = azrtti_cast(FindNode(scSourceNodeId)); if (nodeling) diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index c7125abbc0..7052ab488f 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -360,7 +360,7 @@ namespace ScriptCanvasEditor } }; - openers.push_back({ "Lumberyard_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(), scriptCanvasEditorCallback }); + openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(), scriptCanvasEditorCallback }); } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h index cd7a8965fb..a094e4b477 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h @@ -56,7 +56,7 @@ namespace ScriptCanvasEditor VarIdRole = Qt::UserRole }; - static const char* GetMimeType() { return "lumberyard/x-scriptcanvas-varpanel"; } + static const char* GetMimeType() { return "o3de/x-scriptcanvas-varpanel"; } AZ_CLASS_ALLOCATOR(GraphVariablesModel, AZ::SystemAllocator, 0); GraphVariablesModel(QObject* parent = nullptr); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp index 06ad79c21d..c1eb2eed36 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp @@ -81,8 +81,6 @@ namespace ScriptCanvas { return ConstructCustomNodeIdentifier(scriptCanvasNode->RTTI_GetType()); } - - return NodeTypeIdentifier(0); } NodeTypeIdentifier NodeUtils::ConstructEBusIdentifier(ScriptCanvas::EBusBusId ebusIdentifier) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index cba3991111..639ef114fc 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -23,8 +23,6 @@ ly_add_target( PRIVATE Source . - PUBLIC - Include COMPILE_DEFINITIONS PRIVATE SCRIPTCANVAS_EDITOR diff --git a/Gems/TestAssetBuilder/Code/CMakeLists.txt b/Gems/TestAssetBuilder/Code/CMakeLists.txt index 1106ebf477..dbd2907033 100644 --- a/Gems/TestAssetBuilder/Code/CMakeLists.txt +++ b/Gems/TestAssetBuilder/Code/CMakeLists.txt @@ -21,8 +21,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore @@ -38,8 +36,6 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source - PUBLIC - Include BUILD_DEPENDENCIES PRIVATE Gem::TestAssetBuilder.Static diff --git a/Gems/Twitch/Code/Source/TwitchReflection.cpp b/Gems/Twitch/Code/Source/TwitchReflection.cpp index 91043426cf..d682e37519 100644 --- a/Gems/Twitch/Code/Source/TwitchReflection.cpp +++ b/Gems/Twitch/Code/Source/TwitchReflection.cpp @@ -114,8 +114,8 @@ namespace Twitch " Notifications:" + UserNotificationsToString(info.Notifications) + " CreatedDate:" + info.CreatedDate + " UpdatedDate:" + info.UpdatedDate + - " EMailVerified:" + BoolName(info.EMailVerified, "Yes", "No"); - " Partnered:" + BoolName(info.Partnered, "Yes", "No"); + " EMailVerified:" + BoolName(info.EMailVerified, "Yes", "No") + + " Partnered:" + BoolName(info.Partnered, "Yes", "No") + " TwitterConnected:" + BoolName(info.TwitterConnected, "Yes", "No"); } @@ -164,404 +164,404 @@ namespace Twitch } AZStd::string FriendInfoToString(const FriendInfo & info) - { - return UserInfoIDToString(info.User) + - " CreatedDate:" + info.CreatedDate; - } + { + return UserInfoIDToString(info.User) + + " CreatedDate:" + info.CreatedDate; + } - AZStd::string FriendListToString(const FriendList & info) - { - AZStd::string strList; + AZStd::string FriendListToString(const FriendList & info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += FriendInfoToString(i); - strList += "}"; - } + strList += "{"; + strList += FriendInfoToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string FriendRequestToString(const FriendRequest & info) - { - return UserInfoIDToString(info.User) + - " IsRecommended:" + BoolName(info.IsRecommended, "Yes", "No") + - " IsStranger:" + BoolName(info.IsStranger, "Yes", "No") + - " NonStrangerReason:" + info.NonStrangerReason + - " RequestedDate:" + info.RequestedDate; - } + AZStd::string FriendRequestToString(const FriendRequest & info) + { + return UserInfoIDToString(info.User) + + " IsRecommended:" + BoolName(info.IsRecommended, "Yes", "No") + + " IsStranger:" + BoolName(info.IsStranger, "Yes", "No") + + " NonStrangerReason:" + info.NonStrangerReason + + " RequestedDate:" + info.RequestedDate; + } - AZStd::string FriendRequestListToString(const FriendRequestList & info) - { - AZStd::string strList; + AZStd::string FriendRequestListToString(const FriendRequestList & info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += FriendRequestToString(i); - strList += "}"; - } + strList += "{"; + strList += FriendRequestToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string PresenceStatusToString(const PresenceStatus & info) - { - return "UserID:" + info.UserID + - " Index:" + AZStd::string::format("%lld", info.Index) + - " UpdatedDate:" + AZStd::string::format("%lld", info.UpdatedDate) + - " ActivityType:" + PresenceActivityTypeToString(info.ActivityType) + - " Availability:" + PresenceAvailabilityToString(info.Availability); - } + AZStd::string PresenceStatusToString(const PresenceStatus & info) + { + return "UserID:" + info.UserID + + " Index:" + AZStd::string::format("%lld", info.Index) + + " UpdatedDate:" + AZStd::string::format("%lld", info.UpdatedDate) + + " ActivityType:" + PresenceActivityTypeToString(info.ActivityType) + + " Availability:" + PresenceAvailabilityToString(info.Availability); + } - AZStd::string PresenceStatusListToString(const PresenceStatusList & info) - { - AZStd::string strList; + AZStd::string PresenceStatusListToString(const PresenceStatusList & info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += PresenceStatusToString(i); - strList += "}"; - } + strList += "{"; + strList += PresenceStatusToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string PresenceSettingsToString(const PresenceSettings & info) - { - return "IsInvisible:" + BoolName(info.IsInvisible, "Yes", "No") + - " ShareActivity:" + BoolName(info.ShareActivity, "Shared", "None"); - } + AZStd::string PresenceSettingsToString(const PresenceSettings & info) + { + return "IsInvisible:" + BoolName(info.IsInvisible, "Yes", "No") + + " ShareActivity:" + BoolName(info.ShareActivity, "Shared", "None"); + } - AZStd::string ChannelInfoToString(const ChannelInfo & info) - { - return "Followers:" + AZStd::string::format("%llu", info.NumFollowers) + - "Views:" + AZStd::string::format("%llu", info.NumViews) + - "ItemsRecieved:" + AZStd::string::format("%llu", info.NumItemsRecieved) + - "Partner:" + BoolName(info.Partner, "Yes", "No") + - "Mature:" + BoolName(info.Mature, "Yes", "No") + - "Id:" + info.Id + - "BroadcasterLanguage:" + info.BroadcasterLanguage + - "DisplayName:" + info.DisplayName + - "eMail:" + info.eMail + - "GameName:" + info.GameName + - "Language:" + info.Lanugage + - "Logo:" + info.Logo + - "Name:" + info.Name + - "ProfileBanner:" + info.ProfileBanner + - "ProfileBannerBackgroundColor:" + info.ProfileBannerBackgroundColor + - "Status:" + info.Status + - "StreamKey:" + info.StreamKey + - "UpdatedDate:" + info.UpdatedDate + - "CreatedDate:" + info.CreatedDate + - "URL:" + info.URL + - "VideoBanner:" + info.VideoBanner; - } + AZStd::string ChannelInfoToString(const ChannelInfo & info) + { + return "Followers:" + AZStd::string::format("%llu", info.NumFollowers) + + "Views:" + AZStd::string::format("%llu", info.NumViews) + + "ItemsRecieved:" + AZStd::string::format("%llu", info.NumItemsRecieved) + + "Partner:" + BoolName(info.Partner, "Yes", "No") + + "Mature:" + BoolName(info.Mature, "Yes", "No") + + "Id:" + info.Id + + "BroadcasterLanguage:" + info.BroadcasterLanguage + + "DisplayName:" + info.DisplayName + + "eMail:" + info.eMail + + "GameName:" + info.GameName + + "Language:" + info.Lanugage + + "Logo:" + info.Logo + + "Name:" + info.Name + + "ProfileBanner:" + info.ProfileBanner + + "ProfileBannerBackgroundColor:" + info.ProfileBannerBackgroundColor + + "Status:" + info.Status + + "StreamKey:" + info.StreamKey + + "UpdatedDate:" + info.UpdatedDate + + "CreatedDate:" + info.CreatedDate + + "URL:" + info.URL + + "VideoBanner:" + info.VideoBanner; + } - AZStd::string FollowerToString(const Follower& info) - { - return UserInfoIDToString(info.User) + - " CreatedDate:" + info.CreatedDate + - " Notifications:" + BoolName(info.Notifications, "On", "Off"); - } + AZStd::string FollowerToString(const Follower& info) + { + return UserInfoIDToString(info.User) + + " CreatedDate:" + info.CreatedDate + + " Notifications:" + BoolName(info.Notifications, "On", "Off"); + } - AZStd::string FollowerListToString(const FollowerList & info) - { - AZStd::string strList; + AZStd::string FollowerListToString(const FollowerList & info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += FollowerToString(i); - strList += "}"; - } + strList += "{"; + strList += FollowerToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string TeamInfoToString(const TeamInfo& info) - { - return "ID:" + info.ID + - " Background:" + info.Background + - " Banner:" + info.Banner + - " CreatedDate:" + info.CreatedDate + - " DisplayName:" + info.DisplayName + - " Info:" + info.Info + - " Logo:" + info.Logo + - " Name:" + info.Name + - " UpdatedDate:" + info.UpdatedDate; - } + AZStd::string TeamInfoToString(const TeamInfo& info) + { + return "ID:" + info.ID + + " Background:" + info.Background + + " Banner:" + info.Banner + + " CreatedDate:" + info.CreatedDate + + " DisplayName:" + info.DisplayName + + " Info:" + info.Info + + " Logo:" + info.Logo + + " Name:" + info.Name + + " UpdatedDate:" + info.UpdatedDate; + } - AZStd::string TeamInfoListToString(const TeamInfoList& info) - { - AZStd::string strList; + AZStd::string TeamInfoListToString(const TeamInfoList& info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += TeamInfoToString(i); - strList += "}"; - } + strList += "{"; + strList += TeamInfoToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string SubscriberInfoToString(const SubscriberInfo& info) - { - return "ID:" + info.ID + - " CreatedDate:" + info.CreatedDate + - UserInfoIDToString(info.User); - } + AZStd::string SubscriberInfoToString(const SubscriberInfo& info) + { + return "ID:" + info.ID + + " CreatedDate:" + info.CreatedDate + + UserInfoIDToString(info.User); + } - AZStd::string SubscriberInfoListToString(const SubscriberInfoList& info) - { - AZStd::string strList; + AZStd::string SubscriberInfoListToString(const SubscriberInfoList& info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += SubscriberInfoToString(i); - strList += "}"; - } + strList += "{"; + strList += SubscriberInfoToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string VideoInfoShortToString(const VideoInfo& info) - { - return "ID:" + info.ID; - } + AZStd::string VideoInfoShortToString(const VideoInfo& info) + { + return "ID:" + info.ID; + } - AZStd::string VideoInfoListToString(const VideoInfoList& info) - { - AZStd::string strList; + AZStd::string VideoInfoListToString(const VideoInfoList& info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += VideoInfoShortToString(i); - strList += "}"; - } + strList += "{"; + strList += VideoInfoShortToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string StartChannelCommercialResultToString(const StartChannelCommercialResult& info) - { - return "Duration:" + AZStd::string::format("%llu", info.Duration) + - " RetryAfter:" + AZStd::string::format("%llu", info.RetryAfter) + - " Message:" + info.Message; - } + AZStd::string StartChannelCommercialResultToString(const StartChannelCommercialResult& info) + { + return "Duration:" + AZStd::string::format("%llu", info.Duration) + + " RetryAfter:" + AZStd::string::format("%llu", info.RetryAfter) + + " Message:" + info.Message; + } - AZStd::string CommunityInfoToString(const CommunityInfo& info) - { - return "ID:" + info.ID + - " AvatarImageURL:" + info.AvatarImageURL + - " CoverImageURL:" + info.CoverImageURL + - " Description:" + info.Description + - " DescriptionHTML:" + info.DescriptionHTML + - " Language:" + info.Language + - " Name:" + info.Name + - " OwnerID:" + info.OwnerID + - " Rules:" + info.Rules + - " RulesHTML:" + info.RulesHTML + - " Summary:" + info.Summary; - } + AZStd::string CommunityInfoToString(const CommunityInfo& info) + { + return "ID:" + info.ID + + " AvatarImageURL:" + info.AvatarImageURL + + " CoverImageURL:" + info.CoverImageURL + + " Description:" + info.Description + + " DescriptionHTML:" + info.DescriptionHTML + + " Language:" + info.Language + + " Name:" + info.Name + + " OwnerID:" + info.OwnerID + + " Rules:" + info.Rules + + " RulesHTML:" + info.RulesHTML + + " Summary:" + info.Summary; + } - AZStd::string CommunityInfoListToString(const CommunityInfoList& info) - { - AZStd::string strList; + AZStd::string CommunityInfoListToString(const CommunityInfoList& info) + { + AZStd::string strList; - for (const auto & i : info) - { - if (!strList.empty()) - { - strList += ","; - } + for (const auto & i : info) + { + if (!strList.empty()) + { + strList += ","; + } - strList += "{"; - strList += CommunityInfoToString(i); - strList += "}"; - } + strList += "{"; + strList += CommunityInfoToString(i); + strList += "}"; + } - return strList; - } + return strList; + } - AZStd::string ReturnValueToString(const ReturnValue& info) - { - return "ReceiptID:" + AZStd::string::format("%llu", info.GetID()) + - " Result: " + ResultCodeToString(info.Result); - } + AZStd::string ReturnValueToString(const ReturnValue& info) + { + return "ReceiptID:" + AZStd::string::format("%llu", info.GetID()) + + " Result: " + ResultCodeToString(info.Result); + } - AZStd::string Int64Value::ToString() const - { - return ReturnValueToString(*this) + - AZStd::string::format(" Int64:%lld", Value); - } + AZStd::string Int64Value::ToString() const + { + return ReturnValueToString(*this) + + AZStd::string::format(" Int64:%lld", Value); + } - AZStd::string Uint64Value::ToString() const - { - return ReturnValueToString(*this) + - AZStd::string::format(" Uint64:%llu", Value); - } + AZStd::string Uint64Value::ToString() const + { + return ReturnValueToString(*this) + + AZStd::string::format(" Uint64:%llu", Value); + } - AZStd::string StringValue::ToString() const - { - return ReturnValueToString(*this) + - " String:" + "\"" + Value + "\""; - } + AZStd::string StringValue::ToString() const + { + return ReturnValueToString(*this) + + " String:" + "\"" + Value + "\""; + } - AZStd::string UserInfoValue::ToString() const - { - return ReturnValueToString(*this) + - UserInfoToString(Value); - } + AZStd::string UserInfoValue::ToString() const + { + return ReturnValueToString(*this) + + UserInfoToString(Value); + } - AZStd::string FriendRecommendationValue::ToString() const - { - return ReturnValueToString(*this) + - " ListSize:" + AZStd::string::format("%llu-", static_cast(Value.size())) + - " Recommendations:" + FriendRecommendationsToString(Value); - } + AZStd::string FriendRecommendationValue::ToString() const + { + return ReturnValueToString(*this) + + " ListSize:" + AZStd::string::format("%llu-", static_cast(Value.size())) + + " Recommendations:" + FriendRecommendationsToString(Value); + } - AZStd::string GetFriendValue::ToString() const - { - return ReturnValueToString(*this) + - " ListSize:" + AZStd::string::format("%llu-", static_cast(Value.Friends.size())) + - " Cursor:" + Value.Cursor + - " Friends:" + FriendListToString(Value.Friends); - } + AZStd::string GetFriendValue::ToString() const + { + return ReturnValueToString(*this) + + " ListSize:" + AZStd::string::format("%llu-", static_cast(Value.Friends.size())) + + " Cursor:" + Value.Cursor + + " Friends:" + FriendListToString(Value.Friends); + } - AZStd::string FriendStatusValue::ToString() const - { - return ReturnValueToString(*this) + - " Status:" + Value.Status + - UserInfoToString(Value.User); - } + AZStd::string FriendStatusValue::ToString() const + { + return ReturnValueToString(*this) + + " Status:" + Value.Status + + UserInfoToString(Value.User); + } - AZStd::string FriendRequestValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", Value.Total) + - " Cursor:" + Value.Cursor + - " Requests:" + FriendRequestListToString(Value.Requests); - } + AZStd::string FriendRequestValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", Value.Total) + + " Cursor:" + Value.Cursor + + " Requests:" + FriendRequestListToString(Value.Requests); + } - AZStd::string PresenceStatusValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + - " StatusList:" + PresenceStatusListToString(Value); - } + AZStd::string PresenceStatusValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + + " StatusList:" + PresenceStatusListToString(Value); + } - AZStd::string PresenceSettingsValue::ToString() const - { - return ReturnValueToString(*this) + - " " + PresenceSettingsToString(Value); - } + AZStd::string PresenceSettingsValue::ToString() const + { + return ReturnValueToString(*this) + + " " + PresenceSettingsToString(Value); + } - AZStd::string ChannelInfoValue::ToString() const - { - return ReturnValueToString(*this) + - " " + ChannelInfoToString(Value); - } + AZStd::string ChannelInfoValue::ToString() const + { + return ReturnValueToString(*this) + + " " + ChannelInfoToString(Value); + } - AZStd::string UserInfoListValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + - " Users:" + UserInfoListToString(Value); - } + AZStd::string UserInfoListValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + + " Users:" + UserInfoListToString(Value); + } - AZStd::string FollowerResultValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", Value.Total) + - " Cursor:" + Value.Cursor + - " Followers:" + FollowerListToString(Value.Followers); - } + AZStd::string FollowerResultValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", Value.Total) + + " Cursor:" + Value.Cursor + + " Followers:" + FollowerListToString(Value.Followers); + } - AZStd::string ChannelTeamValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + - " Teams:" + TeamInfoListToString(Value); - } + AZStd::string ChannelTeamValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", static_cast(Value.size())) + + " Teams:" + TeamInfoListToString(Value); + } - AZStd::string SubscriberValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", Value.Total) + - " Subscribers:" + SubscriberInfoListToString(Value.Subscribers); - } + AZStd::string SubscriberValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", Value.Total) + + " Subscribers:" + SubscriberInfoListToString(Value.Subscribers); + } - AZStd::string SubscriberbyUserValue::ToString() const - { - return ReturnValueToString(*this) + - " SubscriberInfo:" + SubscriberInfoToString(Value); - } + AZStd::string SubscriberbyUserValue::ToString() const + { + return ReturnValueToString(*this) + + " SubscriberInfo:" + SubscriberInfoToString(Value); + } - AZStd::string VideoReturnValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", Value.Total) + - " Videos:" + VideoInfoListToString(Value.Videos); - } + AZStd::string VideoReturnValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", Value.Total) + + " Videos:" + VideoInfoListToString(Value.Videos); + } - AZStd::string StartChannelCommercialValue::ToString() const - { - return ReturnValueToString(*this) + - " " + StartChannelCommercialResultToString(Value); - } + AZStd::string StartChannelCommercialValue::ToString() const + { + return ReturnValueToString(*this) + + " " + StartChannelCommercialResultToString(Value); + } - AZStd::string CommunityInfoValue::ToString() const - { - return ReturnValueToString(*this) + - " " + CommunityInfoToString(Value); - } + AZStd::string CommunityInfoValue::ToString() const + { + return ReturnValueToString(*this) + + " " + CommunityInfoToString(Value); + } - AZStd::string CommunityInfoReturnValue::ToString() const - { - return ReturnValueToString(*this) + - " Total:" + AZStd::string::format("%llu", Value.Total) + - " Communities:" + CommunityInfoListToString(Value.Communities); + AZStd::string CommunityInfoReturnValue::ToString() const + { + return ReturnValueToString(*this) + + " Total:" + AZStd::string::format("%llu", Value.Total) + + " Communities:" + CommunityInfoListToString(Value.Communities); } namespace Internal @@ -1218,4 +1218,4 @@ namespace Twitch ->Handler(); } } -} \ No newline at end of file +} diff --git a/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake b/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake index aea3313cce..561ab67600 100644 --- a/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake +++ b/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake @@ -10,8 +10,6 @@ # if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) - set(LY_BUILD_DEPENDENCIES PRIVATE 3rdParty::OpenMesh) diff --git a/Tests/ly_shared/PlatformSetting.py b/Tests/ly_shared/PlatformSetting.py index d78c90f295..b215275c16 100755 --- a/Tests/ly_shared/PlatformSetting.py +++ b/Tests/ly_shared/PlatformSetting.py @@ -16,7 +16,7 @@ import pytest import logging from typing import Optional, Any -import ly_test_tools.lumberyard.pipeline_utils as utils +import ly_test_tools.o3de.pipeline_utils as utils logger = logging.getLogger(__name__) diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base.lib new file mode 100644 index 0000000000..5f9059e1d7 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:626086670063e2d25c747e4532fba8b070122b63cfd119da97ff96b13a6c3d6e +size 2094438 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base_cc.pdb new file mode 100644 index 0000000000..88de799261 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/base_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:270034ee51a53ef434d0383765f951910319b7045867d10e66fb7bc5e5a8f380 +size 831488 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client.lib new file mode 100644 index 0000000000..fe4eaddad1 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:302ef869aad53a2ea5681ee1c5a96e198e5d521165bd6a9027d09ffd7df38fa5 +size 3914060 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client_cc.pdb new file mode 100644 index 0000000000..f93a003b98 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_client_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45020f9f0b490f1c001e6cc8bf1c45a29d678611c4655f85074fe23fa6c5ddd1 +size 1175552 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat.lib new file mode 100644 index 0000000000..3f4d33f8b9 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:004901f966fc28e9ae6aecc8086302592cb43208ec31a7c074f699533d84c2db +size 8978 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat_cc.pdb new file mode 100644 index 0000000000..03f989686b --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_compat_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3aa1cba7cd1564df06777f4dcb4057f8bd2fcbc176ec8a494b17f7277e44a4d +size 77824 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context.lib new file mode 100644 index 0000000000..5652923545 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36acc956e8ecf13ed164d4c416bcc92f0f31db5f30f3d1e7beb33e398a41443b +size 63796 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context_cc.pdb new file mode 100644 index 0000000000..35c42abfea --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_context_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f97ecc158d23e273367171dc032ce3ed7feeec7b7221ccf10e36d304ee467b7e +size 454656 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler.lib new file mode 100644 index 0000000000..c9f32e4272 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5ed7b8a7193e75ff9588e6c7d06e2a3c0afda514a620dd275c1338ba6acd161 +size 3054554 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler_cc.pdb new file mode 100644 index 0000000000..1328fd6d03 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_handler_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65903b1d9275b9268bdf7af1e4c2f2de46cd8dcc83eae4bfa64c2f5b38edbc57 +size 2887680 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump.lib new file mode 100644 index 0000000000..3796a0478e --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0e78280364d17a23a8feb819d71fb830f67ca40b7c932467263740cb2917ead +size 13044588 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump_cc.pdb new file mode 100644 index 0000000000..4c58046197 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_minidump_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5885d9f72f86181199e6b2f1e7fb96419982209fe7e2c8f7b06b7c77c332c836 +size 2289664 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot.lib new file mode 100644 index 0000000000..f8b4588ed5 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fb181c40f80438d0b50f79b093a3503c853a43db8e92f7d5ddfd5bb13793b16 +size 12965800 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot_cc.pdb new file mode 100644 index 0000000000..992891a75f --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_snapshot_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27ab636cdc02fe86b73c40961c289d810f4f31be9c59c61e7c5300f0e9168fe9 +size 2355200 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support.lib new file mode 100644 index 0000000000..330ad9beee --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f00b8108a7849e92d4711a0106b94931eced1859fb0281a423ad5179cacdf399 +size 240574 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support_cc.pdb new file mode 100644 index 0000000000..ff5ecf71a6 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_tool_support_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:026ca665e79cf98df13477abe84201dd1bdba7a0068b3b411b89eaf9cc8c1711 +size 446464 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util.lib new file mode 100644 index 0000000000..78b3281e6c --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3a6cd014d7a1096ab492ea62061c8eac341ffe97a856710b2dd65e183fe9248 +size 11636150 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util_cc.pdb new file mode 100644 index 0000000000..1f51fdbfd5 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/crashpad_util_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4c2b7e7ca514f1f5e768e4c7f5ec341f04b5f1e5fe82a8885476d1e1ed833f4 +size 2363392 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.cc.pdb new file mode 100644 index 0000000000..5ef03ecd9b --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5af26522ab427c4ec2ea9dbe0c41eca46bb31475b8b87ab47c513e56839ba763 +size 86016 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.lib new file mode 100644 index 0000000000..2c42ac90b0 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/getopt.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd974c961c1a1443414bc21cfa10440ed1367c7cfa15fd9608ca431631917a65 +size 22644 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.c.pdb b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.c.pdb new file mode 100644 index 0000000000..58c4ab5305 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.c.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76c990a27c549c0428095bdbe97060a40d33c3a897587ddd06e2ee8db15d4770 +size 102400 diff --git a/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.lib b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.lib new file mode 100644 index 0000000000..0b3dab07d7 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Debug_x64/third_party/zlib.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78cbbb2b947e55fb13b3f97366d759d22e828ccf2588f2a412b924fcbd2524d8 +size 350630 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/base.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/base.lib new file mode 100644 index 0000000000..ab843e4478 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/base.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07139d47140d27876fff382036637bab1e22ae8c65b5ceaf37f92fcd347587a7 +size 1124438 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/base_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/base_cc.pdb new file mode 100644 index 0000000000..366ca528e2 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/base_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b09045400a4ee55542916a915c111072a4f8b27be77378cb52f1597fd87d8150 +size 806912 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client.lib new file mode 100644 index 0000000000..027348705d --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4cbb4e87fe52a5b85739cb2cc562cc9da718b8a2d62df74428d40ccdf62cce2 +size 1696870 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client_cc.pdb new file mode 100644 index 0000000000..5a66efa3bf --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_client_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae28bf771c2788a34bf642ab95ba102e5d6c7b8e22b23742a93b8092b5c5e687 +size 1085440 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat.lib new file mode 100644 index 0000000000..7cf7f10d4c --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0803ce1fe7b23397997d6cc160803e44c7c172616223004ee5f17a5ae41d165 +size 8734 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat_cc.pdb new file mode 100644 index 0000000000..bee40682a0 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_compat_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69f1497cdf145f98a04d05cc4bae8f7c60e98de3faafab46c9dacc95d4557fb5 +size 77824 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context.lib new file mode 100644 index 0000000000..8699928d13 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8a96c249ee9af8ddd9d9f66b93cd7ec5edb45dc5e0e012645917490a80897e3 +size 49100 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context_cc.pdb new file mode 100644 index 0000000000..c92e68adbd --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_context_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fd31008151c0e7cb2dc6f3547d391ba69aeb4741b8b5b5e76abd83b6415e100 +size 430080 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler.lib new file mode 100644 index 0000000000..e2d8a48531 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c9099859046bf4dafcf6455c39accfefe5ca389d8bfdc86fe2209c5e4b8804f +size 1157858 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler_cc.pdb new file mode 100644 index 0000000000..49e5c1d8b1 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_handler_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca7cc3c846da2017736d813e56e32071d9e720319dc8fd636372923a3c25d223 +size 2527232 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump.lib new file mode 100644 index 0000000000..4ef4c8ae40 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3430726856c3b68f422614166ed64e7249b2246363c27fd2d63e63f668c2e47d +size 5155320 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump_cc.pdb new file mode 100644 index 0000000000..4a2457000f --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_minidump_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae7f896e3613565161bc41b90dc45aed9539c82261d9b5c2ed9c5a3a0b8f31b9 +size 2052096 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot.lib new file mode 100644 index 0000000000..698f891924 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c1ca49c6246323d9d4f854f4e8767735fdd51b0cc3faa7ce3d5a985e65db1a5 +size 4598666 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot_cc.pdb new file mode 100644 index 0000000000..01de39bbf7 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_snapshot_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9eac108b65d4b45ffc08d11f457274c25e9c7aba978b79cdcccd0894a07f679c +size 2134016 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support.lib new file mode 100644 index 0000000000..64786f1069 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:232322c240867a6a781784c754ac69a5e5452ff7bf6ac582ace35e9b1f68aada +size 95970 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support_cc.pdb new file mode 100644 index 0000000000..ec48eeab69 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_tool_support_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a2b9b1d36c94c189d9c5ea821a2b819b01c4db449fa6b6a574e19efc2600978 +size 413696 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util.lib new file mode 100644 index 0000000000..4c346532a8 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6bf62815ecf6591fda46ba72b3636df660d5ceaa6571d55dec0f4b306d69cb1 +size 5704098 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util_cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util_cc.pdb new file mode 100644 index 0000000000..bd5f778e18 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/crashpad_util_cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e30478f7aa319924d5b2578ec038cd58f93d9be726e918dc6693964b9550532 +size 2256896 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.cc.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.cc.pdb new file mode 100644 index 0000000000..5976aa378d --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.cc.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d154da0553fd94ec3e5059503a41db03f1d68fffed12fc76ab4902ec75f6298e +size 86016 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.lib new file mode 100644 index 0000000000..cf8a5cb625 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/getopt.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f8b36cf3305d9d10e97ebac28d53cf3f6c8cf117d8fc8bac3312c65c8e48d77 +size 29408 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.c.pdb b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.c.pdb new file mode 100644 index 0000000000..9d6836d135 --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.c.pdb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97f469e3a535f77fc242040bb80d36f8883182868bb070c33fec041722605259 +size 102400 diff --git a/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.lib b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.lib new file mode 100644 index 0000000000..b755b2ce8c --- /dev/null +++ b/Tools/Crashpad/bin/windows/vs2019/Release_x64/third_party/zlib.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5f1d98d742d61d430c0bbc73eeb4ab9dc7afb6adaa8bdde7570fe28a3a4aac8 +size 388862 diff --git a/Tools/Crashpad/handler/src/crash_report_upload_thread.cc b/Tools/Crashpad/handler/src/crash_report_upload_thread.cc index f2a29c828e..ccb1512e24 100644 --- a/Tools/Crashpad/handler/src/crash_report_upload_thread.cc +++ b/Tools/Crashpad/handler/src/crash_report_upload_thread.cc @@ -44,7 +44,7 @@ #endif // OS_MACOSX // Amazon - Handle giving the user the option of whether or not to send the report. -namespace Lumberyard +namespace O3de { bool CheckConfirmation(const crashpad::CrashReportDatabase::Report& report); bool AddAttachments(crashpad::HTTPMultipartBuilder& multipartBuilder); @@ -198,7 +198,7 @@ void CrashReportUploadThread::ProcessPendingReport( } // Amazon - Handle giving the user the option of whether or not to send the report. - if (!Lumberyard::CheckConfirmation(report)) + if (!O3DE::CheckConfirmation(report)) { database_->SkipReportUpload(report.uuid, Metrics::CrashSkippedReason::kUploadsDisabled); @@ -350,7 +350,7 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( "application/octet-stream"); // Amazon - Lumberyard::AddAttachments(http_multipart_builder); + O3de::AddAttachments(http_multipart_builder); std::unique_ptr http_transport(HTTPTransport::Create()); HTTPHeaders content_headers; @@ -390,7 +390,7 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( http_transport->SetURL(url); // Amazon - Lumberyard::UpdateHttpTransport(http_transport, url); + O3de::UpdateHttpTransport(http_transport, url); if (!http_transport->ExecuteSynchronously(response_body)) { return UploadResult::kRetry; diff --git a/Tools/Crashpad/include/client/crashpad_client.h b/Tools/Crashpad/include/client/crashpad_client.h index 7799bd9c9f..c452cdbb68 100644 --- a/Tools/Crashpad/include/client/crashpad_client.h +++ b/Tools/Crashpad/include/client/crashpad_client.h @@ -94,6 +94,8 @@ class CrashpadClient { //! a background thread. Optionally, WaitForHandlerStart() can be used at //! a suitable time to retreive the result of background startup. This //! option is only used on Windows. + //! \param[in] attachments Vector that stores file paths that should be + //! captured with each report at the time of the crash. //! //! \return `true` on success, `false` on failure with a message logged. bool StartHandler(const base::FilePath& handler, @@ -103,7 +105,8 @@ class CrashpadClient { const std::map& annotations, const std::vector& arguments, bool restartable, - bool asynchronous_start); + bool asynchronous_start, + const std::vector& attachments = {}); #if defined(OS_MACOSX) || DOXYGEN //! \brief Sets the process’ crash handler to a Mach service registered with diff --git a/Tools/LyTestTools/README.txt b/Tools/LyTestTools/README.txt index 16aa7f534f..1cdd4811fc 100644 --- a/Tools/LyTestTools/README.txt +++ b/Tools/LyTestTools/README.txt @@ -67,14 +67,14 @@ PACKAGE STRUCTURE The project is organized into packages. Each package corresponds to a tool: -- LyTestTools.ly_test_tools._internal: contains logging setup, pytest fixture, and lumberyard workspace manager modules +- LyTestTools.ly_test_tools._internal: contains logging setup, pytest fixture, and o3de workspace manager modules - LyTestTools.ly_test_tools.builtin: builtin helpers and fixtures for quickly writing tests - LyTestTools.ly_test_tools.console: modules used for consoles - LyTestTools.ly_test_tools.environment: functions related to file/process management and cleanup - LyTestTools.ly_test_tools.image: modules related to image capturing and processing - LyTestTools.ly_test_tools.launchers: game launchers library - LyTestTools.ly_test_tools.log: modules for interacting with generated or existing log files -- LyTestTools.ly_test_tools.lumberyard: modules used to interact with lumberyard +- LyTestTools.ly_test_tools.o3de: modules used to interact with Open 3D Engine - LyTestTools.ly_test_tools.mobile: modules used for android/ios - LyTestTools.ly_test_tools.report: modules used for reporting - LyTestTools.tests: LyTestTools integration, unit, and example usage tests diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/workspace.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/workspace.py index 5bf1864794..df35eda4fa 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/workspace.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/workspace.py @@ -19,9 +19,9 @@ import tempfile import ly_test_tools.environment.file_system import ly_test_tools.environment.process_utils as process_utils -import ly_test_tools.lumberyard.asset_processor -import ly_test_tools.lumberyard.settings as settings -import ly_test_tools.lumberyard.shader_compiler +import ly_test_tools.o3de.asset_processor +import ly_test_tools.o3de.settings as settings +import ly_test_tools.o3de.shader_compiler import ly_test_tools._internal.managers.artifact_manager as artifact_manager import ly_test_tools._internal.managers.abstract_resource_locator as arl @@ -46,7 +46,7 @@ class AbstractWorkspaceManager: The workspace contains information about the workspace being used and the running pytest test. :param resource_locator: A resource locator to create paths for the workspace - :param project: Lumberyard project to use for the LumberyardRelease object + :param project: O3DE project to use for the LumberyardRelease object :param tmp_path: A path to use for storing temp files, if not specified default to the system's tmp :param output_path: A path used to store artifacts, if not specified defaults to "\\dev\\TestResults\\" @@ -55,8 +55,8 @@ class AbstractWorkspaceManager: self.project = project self.artifact_manager = artifact_manager.NullArtifactManager() - self.asset_processor = ly_test_tools.lumberyard.asset_processor.AssetProcessor(self) - self.shader_compiler = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(self) + self.asset_processor = ly_test_tools.o3de.asset_processor.AssetProcessor(self) + self.shader_compiler = ly_test_tools.o3de.shader_compiler.ShaderCompiler(self) self._original_cwd = os.getcwd() self.tmp_path = tmp_path self.output_path = output_path diff --git a/Tools/LyTestTools/ly_test_tools/log/log_monitor.py b/Tools/LyTestTools/ly_test_tools/log/log_monitor.py index 6c02c72bca..ca3cd24303 100755 --- a/Tools/LyTestTools/ly_test_tools/log/log_monitor.py +++ b/Tools/LyTestTools/ly_test_tools/log/log_monitor.py @@ -32,7 +32,7 @@ def check_exact_match(line, expected_line): """ Uses regular expressions to find an exact (not partial) match for 'expected_line' in 'line', i.e. in the example below it matches 'foo' and succeeds: - line value: '66118.999958 - INFO - [MainThread] - ly_test_tools.lumberyard.asset_processor - foo' + line value: '66118.999958 - INFO - [MainThread] - ly_test_tools.o3de.asset_processor - foo' expected_line: 'foo' :param line: The log line string to search, diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/__init__.py b/Tools/LyTestTools/ly_test_tools/o3de/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/__init__.py rename to Tools/LyTestTools/ly_test_tools/o3de/__init__.py diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/ap_log_parser.py b/Tools/LyTestTools/ly_test_tools/o3de/ap_log_parser.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/ap_log_parser.py rename to Tools/LyTestTools/ly_test_tools/o3de/ap_log_parser.py diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py old mode 100755 new mode 100644 similarity index 99% rename from Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor.py rename to Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py index 70c5a37dfd..230e85e6bf --- a/Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py @@ -26,8 +26,8 @@ import psutil import ly_test_tools import ly_test_tools.environment.waiter as waiter import ly_test_tools.environment.file_system as file_system -import ly_test_tools.lumberyard.pipeline_utils as utils -from ly_test_tools.lumberyard.ap_log_parser import APLogParser +import ly_test_tools.o3de.pipeline_utils as utils +from ly_test_tools.o3de.ap_log_parser import APLogParser logger = logging.getLogger(__name__) diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor_config_util.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_config_util.py old mode 100755 new mode 100644 similarity index 98% rename from Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor_config_util.py rename to Tools/LyTestTools/ly_test_tools/o3de/asset_processor_config_util.py index 7b49d406b7..259d6b5b0b --- a/Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor_config_util.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_config_util.py @@ -15,8 +15,8 @@ AssetProcessorPlatformConfig.setreg import logging import os.path as path -from ly_test_tools.lumberyard.settings import RegistrySettings -from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_SETTINGS_ROOT_KEY +from ly_test_tools.o3de.settings import RegistrySettings +from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_SETTINGS_ROOT_KEY logger = logging.getLogger(__name__) AssetProcessorConfig = "AssetProcessorPlatformConfig.setreg" diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/asset_processor_utils.py rename to Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/ini_configuration_util.py b/Tools/LyTestTools/ly_test_tools/o3de/ini_configuration_util.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/ini_configuration_util.py rename to Tools/LyTestTools/ly_test_tools/o3de/ini_configuration_util.py diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/pipeline_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/pipeline_utils.py old mode 100755 new mode 100644 similarity index 99% rename from Tools/LyTestTools/ly_test_tools/lumberyard/pipeline_utils.py rename to Tools/LyTestTools/ly_test_tools/o3de/pipeline_utils.py index 8a1ffbd646..3763b7eac0 --- a/Tools/LyTestTools/ly_test_tools/lumberyard/pipeline_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/pipeline_utils.py @@ -29,7 +29,7 @@ from typing import Dict, List, Tuple, Optional, Callable # Import LyTestTools import ly_test_tools.environment.file_system as fs import ly_test_tools.environment.process_utils as process_utils -from ly_test_tools.lumberyard.ap_log_parser import APLogParser +from ly_test_tools.o3de.ap_log_parser import APLogParser logger = logging.getLogger(__name__) diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/settings.py b/Tools/LyTestTools/ly_test_tools/o3de/settings.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/settings.py rename to Tools/LyTestTools/ly_test_tools/o3de/settings.py diff --git a/Tools/LyTestTools/ly_test_tools/lumberyard/shader_compiler.py b/Tools/LyTestTools/ly_test_tools/o3de/shader_compiler.py old mode 100755 new mode 100644 similarity index 100% rename from Tools/LyTestTools/ly_test_tools/lumberyard/shader_compiler.py rename to Tools/LyTestTools/ly_test_tools/o3de/shader_compiler.py diff --git a/Tools/LyTestTools/tests/unit/test_asset_processor.py b/Tools/LyTestTools/tests/unit/test_asset_processor.py index 2f40d26088..09731ccec5 100755 --- a/Tools/LyTestTools/tests/unit/test_asset_processor.py +++ b/Tools/LyTestTools/tests/unit/test_asset_processor.py @@ -8,7 +8,7 @@ or, if provided, by the license below or the license accompanying this file. Do 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. -Unit tests for ly_test_tools.lumberyard.asset_processor +Unit tests for ly_test_tools.o3de.asset_processor """ import datetime import unittest.mock as mock @@ -18,7 +18,7 @@ import pytest import ly_test_tools._internal.managers.workspace import ly_test_tools._internal.managers.abstract_resource_locator -import ly_test_tools.lumberyard.asset_processor +import ly_test_tools.o3de.asset_processor pytestmark = pytest.mark.SUITE_smoke @@ -34,12 +34,12 @@ mock_project_path = os.path.join('some', 'dir', mock_project) mock.MagicMock(return_value=mock_initial_path)) @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) -@mock.patch('ly_test_tools.lumberyard.asset_processor.logger.warning', mock.MagicMock()) +@mock.patch('ly_test_tools.o3de.asset_processor.logger.warning', mock.MagicMock()) class TestAssetProcessor(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_Init_DefaultParams_MembersSetCorrectly(self, mock_workspace): - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) assert under_test._workspace == mock_workspace assert under_test._port is not None @@ -47,15 +47,15 @@ class TestAssetProcessor(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') @mock.patch('subprocess.Popen') - @mock.patch('ly_test_tools.lumberyard.asset_processor.AssetProcessor.connect_socket') - @mock.patch('ly_test_tools.lumberyard.asset_processor.ASSET_PROCESSOR_PLATFORM_MAP', {'foo': 'bar'}) + @mock.patch('ly_test_tools.o3de.asset_processor.AssetProcessor.connect_socket') + @mock.patch('ly_test_tools.o3de.asset_processor.ASSET_PROCESSOR_PLATFORM_MAP', {'foo': 'bar'}) def test_Start_NoneRunning_ProcStarted(self, mock_connect, mock_popen, mock_workspace): mock_ap_path = 'mock_ap_path' mock_workspace.asset_processor_platform = 'foo' mock_workspace.paths.asset_processor.return_value = mock_ap_path mock_workspace.project = mock_project mock_workspace.paths.project.return_value = mock_project_path - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) under_test.enable_asset_processor_platform = mock.MagicMock() under_test.wait_for_idle = mock.MagicMock() @@ -77,7 +77,7 @@ class TestAssetProcessor(object): @mock.patch('ly_test_tools.environment.process_utils.process_exists', mock.MagicMock(return_value=True)) @mock.patch('socket.socket.connect') def test_Start_ProcAlreadyRunning_ProcNotChanged(self, mock_connect, mock_popen, mock_workspace): - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) under_test.process_exists = mock.MagicMock(return_value=True) under_test.asset_processor_platform = mock.MagicMock(return_value=ly_test_tools.HOST_OS_PLATFORM) mock_proc = mock.MagicMock() @@ -90,9 +90,9 @@ class TestAssetProcessor(object): mock_connect.assert_not_called() @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') - @mock.patch('ly_test_tools.lumberyard.asset_processor.waiter.wait_for') + @mock.patch('ly_test_tools.o3de.asset_processor.waiter.wait_for') def test_Stop_ProcAlreadyRunning_ProcStopped(self, mock_waiter, mock_workspace): - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) under_test.get_process_list = mock.MagicMock(return_value=[mock.MagicMock()]) under_test._control_connection = mock.MagicMock() under_test.get_pid = mock.MagicMock(return_value=0) @@ -111,7 +111,7 @@ class TestAssetProcessor(object): def test_BatchProcess_NoFastscanBatchCompletes_Success(self, mock_run, mock_workspace): mock_workspace.project = None mock_workspace.paths.project.return_value = mock_project_path - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) apb_path = mock_workspace.paths.asset_processor_batch() mock_run.return_value.returncode = 0 result, _ = under_test.batch_process(1, False) @@ -128,7 +128,7 @@ class TestAssetProcessor(object): def test_BatchProcess_FastscanBatchCompletes_Success(self, mock_run, mock_workspace): mock_workspace.project = mock_project mock_workspace.paths.project.return_value = mock_project_path - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) apb_path = mock_workspace.paths.asset_processor_batch() mock_run.return_value.returncode = 0 @@ -147,7 +147,7 @@ class TestAssetProcessor(object): def test_BatchProcess_ReturnCodeFail_Failure(self, mock_run, mock_workspace): mock_workspace.project = None mock_workspace.paths.project.return_value = mock_project_path - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) apb_path = mock_workspace.paths.asset_processor_batch() mock_run.return_value.returncode = 1 @@ -162,7 +162,7 @@ class TestAssetProcessor(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_EnableAssetProcessorPlatform_AssetProcessorObject_Updated(self, mock_workspace): - under_test = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) under_test.enable_asset_processor_platform('foo') assert "foo" in under_test._enabled_platform_overrides @@ -170,7 +170,7 @@ class TestAssetProcessor(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_BackupAPSettings_Called_CallsBackupAPSettings(self, mock_workspace): mock_temp_path = 'foo_path' - mock_asset_processor = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + mock_asset_processor = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) mock_workspace.settings.get_temp_path.return_value = mock_temp_path mock_asset_processor.backup_ap_settings() @@ -180,18 +180,18 @@ class TestAssetProcessor(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_RestoreAPSettings_Called_CallsRestoreAPSettings(self, mock_workspace): mock_temp_path = 'foo_path' - mock_asset_processor = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + mock_asset_processor = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) mock_workspace.settings.get_temp_path.return_value = mock_temp_path mock_asset_processor.restore_ap_settings() mock_workspace.settings.restore_asset_processor_settings.assert_called_with(mock_temp_path) - @mock.patch('ly_test_tools.lumberyard.asset_processor.AssetProcessor.restore_ap_settings') - @mock.patch('ly_test_tools.lumberyard.asset_processor.AssetProcessor.stop') + @mock.patch('ly_test_tools.o3de.asset_processor.AssetProcessor.restore_ap_settings') + @mock.patch('ly_test_tools.o3de.asset_processor.AssetProcessor.stop') @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_Teardown_Called_CallsRestoreAPSettingsAndStop(self, mock_workspace, mock_stop, mock_restore_ap): - mock_asset_processor = ly_test_tools.lumberyard.asset_processor.AssetProcessor(mock_workspace) + mock_asset_processor = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) mock_asset_processor.teardown() diff --git a/Tools/LyTestTools/tests/unit/test_launcher_android.py b/Tools/LyTestTools/tests/unit/test_launcher_android.py index febd418f93..e9993ebf01 100755 --- a/Tools/LyTestTools/tests/unit/test_launcher_android.py +++ b/Tools/LyTestTools/tests/unit/test_launcher_android.py @@ -234,7 +234,7 @@ class TestAndroidLauncher: mock_workspace.shader_compiler.stop.assert_called_once() @mock.patch('ly_test_tools.launchers.platforms.base.Launcher._config_ini_to_dict') - @mock.patch('ly_test_tools.lumberyard.settings.LySettings.modify_platform_setting', mock.MagicMock) + @mock.patch('ly_test_tools.o3de.settings.LySettings.modify_platform_setting', mock.MagicMock) def test_ConfigureSettings_DefaultValues_SetsValues(self, mock_config): mock_config.return_value = VALID_ANDROID_CONFIG mock_workspace = MockedWorkspace() diff --git a/Tools/LyTestTools/tests/unit/test_settings.py b/Tools/LyTestTools/tests/unit/test_settings.py index 47c4d1bc18..55f1b3c3f1 100755 --- a/Tools/LyTestTools/tests/unit/test_settings.py +++ b/Tools/LyTestTools/tests/unit/test_settings.py @@ -14,7 +14,7 @@ import unittest import pytest -import ly_test_tools.lumberyard.settings +import ly_test_tools.o3de.settings pytestmark = pytest.mark.SUITE_smoke @@ -51,10 +51,10 @@ class TestReplaceLineInFile(unittest.TestCase): try: with mock.patch('__builtin__.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) except ImportError: with mock.patch('builtins.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) mock_log_warning.assert_called_once() @@ -68,10 +68,10 @@ class TestReplaceLineInFile(unittest.TestCase): with pytest.raises(NotImplementedError): try: with mock.patch('__builtin__.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) except ImportError: with mock.patch('builtins.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) @mock.patch('fileinput.input') @mock.patch('os.path.isfile') @@ -80,10 +80,10 @@ class TestReplaceLineInFile(unittest.TestCase): try: with mock.patch('__builtin__.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) except ImportError: with mock.patch('builtins.open'): - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, self.search_for, self.replace_with) mock_input.return_value.close.assert_called_once_with() @@ -101,7 +101,7 @@ class TestReplaceLineInFile(unittest.TestCase): mock.call.write("Setting4="), mock.call.write('\n'), ] - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, 'Setting1', 'NewFoo') + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, 'Setting1', 'NewFoo') mock_stdout.assert_has_calls(expected_print_lines) @@ -119,7 +119,7 @@ class TestReplaceLineInFile(unittest.TestCase): mock.call.write("Setting4="), mock.call.write('\n'), ] - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, 'Setting2', 'NewBar') + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, 'Setting2', 'NewBar') mock_stdout.assert_has_calls(expected_print_lines) @@ -137,7 +137,7 @@ class TestReplaceLineInFile(unittest.TestCase): mock.call.write("Setting4=NewContent"), mock.call.write('\n'), ] - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, 'Setting4', 'NewContent') + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, 'Setting4', 'NewContent') mock_stdout.assert_has_calls(expected_print_lines) @@ -155,7 +155,7 @@ class TestReplaceLineInFile(unittest.TestCase): mock.call.write("Setting4="), mock.call.write('\n'), ] - ly_test_tools.lumberyard.settings._edit_text_settings_file(self.file_name, 'Setting5', 'NewSetting!') + ly_test_tools.o3de.settings._edit_text_settings_file(self.file_name, 'Setting5', 'NewSetting!') mock_stdout.assert_has_calls(expected_print_lines) @@ -182,7 +182,7 @@ class TestJsonSettings(unittest.TestCase): mock_open = mock.mock_open(read_data=self.mock_file_content) with mock.patch('builtins.open', mock_open): - with ly_test_tools.lumberyard.settings.JsonSettings(self.test_file_name) as js: + with ly_test_tools.o3de.settings.JsonSettings(self.test_file_name) as js: # get the whole document value = js.get_key('') assert len(value) == 5 @@ -204,7 +204,7 @@ class TestJsonSettings(unittest.TestCase): default_value = -10 with mock.patch('builtins.open', mock_open): - with ly_test_tools.lumberyard.settings.JsonSettings(self.test_file_name) as js: + with ly_test_tools.o3de.settings.JsonSettings(self.test_file_name) as js: value = js.get_key('/scale/w', default_value) assert value == default_value @@ -213,7 +213,7 @@ class TestJsonSettings(unittest.TestCase): expected = 100 with mock.patch('builtins.open', mock_open): - with ly_test_tools.lumberyard.settings.JsonSettings(self.test_file_name) as js: + with ly_test_tools.o3de.settings.JsonSettings(self.test_file_name) as js: js.set_key('/scale/x', expected) value = js.get_key('/scale/x') assert value == expected @@ -230,7 +230,7 @@ class TestJsonSettings(unittest.TestCase): json_dump.side_effect = _mock_dump with mock.patch('builtins.open', mock_open): - with ly_test_tools.lumberyard.settings.JsonSettings(self.test_file_name) as js: + with ly_test_tools.o3de.settings.JsonSettings(self.test_file_name) as js: js.set_key('/name', expected) assert expected == new_dict_content['name'] @@ -246,7 +246,7 @@ class TestJsonSettings(unittest.TestCase): json_dump.side_effect = _mock_dump with mock.patch('builtins.open', mock_open): - with ly_test_tools.lumberyard.settings.JsonSettings(self.test_file_name) as js: + with ly_test_tools.o3de.settings.JsonSettings(self.test_file_name) as js: js.remove_key('/scale/z') assert len(new_dict_content['scale']) == 2 diff --git a/Tools/LyTestTools/tests/unit/test_shader_compiler.py b/Tools/LyTestTools/tests/unit/test_shader_compiler.py index 99bc1d21dc..d419247eb4 100755 --- a/Tools/LyTestTools/tests/unit/test_shader_compiler.py +++ b/Tools/LyTestTools/tests/unit/test_shader_compiler.py @@ -8,7 +8,7 @@ or, if provided, by the license below or the license accompanying this file. Do 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. -Unit tests for ly_test_tools.lumberyard.shader_compiler +Unit tests for ly_test_tools.o3de.shader_compiler """ import unittest.mock as mock @@ -16,7 +16,7 @@ import pytest import ly_test_tools._internal.managers.workspace import ly_test_tools._internal.managers.abstract_resource_locator -import ly_test_tools.lumberyard.shader_compiler +import ly_test_tools.o3de.shader_compiler pytestmark = pytest.mark.SUITE_smoke @@ -31,12 +31,12 @@ mock_project = 'mock_project' mock.MagicMock(return_value=mock_initial_path)) @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) -@mock.patch('ly_test_tools.lumberyard.asset_processor.logger.warning', mock.MagicMock()) +@mock.patch('ly_test_tools.o3de.asset_processor.logger.warning', mock.MagicMock()) class TestShaderCompiler(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') def test_Init_MockWorkspace_MembersSetCorrectly(self, mock_workspace): - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) assert under_test._workspace == mock_workspace assert under_test._sc_proc is None @@ -48,7 +48,7 @@ class TestShaderCompiler(object): mock_shader_compiler_path = 'mock_shader_compiler_path' mock_workspace.paths.get_shader_compiler_path.return_value = mock_shader_compiler_path mock_popen.return_value = mock.MagicMock() - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) assert under_test._sc_proc is None @@ -59,9 +59,9 @@ class TestShaderCompiler(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') @mock.patch('subprocess.Popen') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.MAC', True) + @mock.patch('ly_test_tools.o3de.shader_compiler.MAC', True) def test_Start_NotImplemented_ErrorRaised(self, mock_popen, mock_workspace): - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) assert under_test._sc_proc is None @@ -73,13 +73,13 @@ class TestShaderCompiler(object): @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') @mock.patch('subprocess.Popen') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.logger.info') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.MAC', True) + @mock.patch('ly_test_tools.o3de.shader_compiler.logger.info') + @mock.patch('ly_test_tools.o3de.shader_compiler.MAC', True) def test_Start_AlreadyRunning_ProcessNotChanged(self, mock_logger, mock_popen, mock_workspace): mock_shader_compiler_path = 'mock_shader_compiler_path' mock_workspace.paths.get_shader_compiler_path.return_value = mock_shader_compiler_path mock_popen.return_value = mock.MagicMock() - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) under_test._sc_proc = 'foo' @@ -92,12 +92,12 @@ class TestShaderCompiler(object): 'but we already have one open!'.format(mock_shader_compiler_path)) @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.process_utils.kill_processes_started_from') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.waiter.wait_for') + @mock.patch('ly_test_tools.o3de.shader_compiler.process_utils.kill_processes_started_from') + @mock.patch('ly_test_tools.o3de.shader_compiler.waiter.wait_for') def test_Stop_AlreadyRunning_ProcessStopped(self, mock_wait, mock_kill, mock_workspace): mock_shader_compiler_path = 'mock_shader_compiler_path' mock_workspace.paths.get_shader_compiler_path.return_value = mock_shader_compiler_path - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) under_test._sc_proc = 'foo' @@ -108,13 +108,13 @@ class TestShaderCompiler(object): mock_wait.assert_called_once() @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.process_utils.kill_processes_started_from') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.waiter.wait_for') - @mock.patch('ly_test_tools.lumberyard.shader_compiler.logger.info') + @mock.patch('ly_test_tools.o3de.shader_compiler.process_utils.kill_processes_started_from') + @mock.patch('ly_test_tools.o3de.shader_compiler.waiter.wait_for') + @mock.patch('ly_test_tools.o3de.shader_compiler.logger.info') def test_Stop_NoneRunning_MessageLogged(self, mock_logger, mock_wait, mock_kill, mock_workspace): mock_shader_compiler_path = 'mock_shader_compiler_path' mock_workspace.paths.get_shader_compiler_path.return_value = mock_shader_compiler_path - under_test = ly_test_tools.lumberyard.shader_compiler.ShaderCompiler(mock_workspace) + under_test = ly_test_tools.o3de.shader_compiler.ShaderCompiler(mock_workspace) under_test._sc_proc = None diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json b/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json index f5d3b316c4..e7e1193062 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json +++ b/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json @@ -153,5 +153,15 @@ "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "ALL_BUILD" } + }, + "mac_packaging_all": { + "TAGS": [ + "packaging" + ], + "COMMAND": "python_mac.sh", + "PARAMETERS": { + "SCRIPT_PATH": "scripts/build/package/package.py", + "SCRIPT_PARAMETERS": "--platform Mac --type all" + } } } diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index 197d48eee6..b6731ae239 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -107,6 +107,7 @@ function(ly_add_external_target) set(BASE_PATH "${LY_3RDPARTY_PATH}/${ly_add_external_target_3RDPARTY_DIRECTORY}") else() + ly_install_external_target(${ly_add_external_target_3RDPARTY_ROOT_DIRECTORY}) set(BASE_PATH "${ly_add_external_target_3RDPARTY_ROOT_DIRECTORY}") endif() @@ -288,6 +289,25 @@ function(ly_add_external_target) endfunction() +#! ly_install_external_target: external libraries which are not part of 3rdParty need to be installed +# +# \arg:3RDPARTY_ROOT_DIRECTORY custom 3rd party directory which needs to be installed +function(ly_install_external_target 3RDPARTY_ROOT_DIRECTORY) + + # Install the Find file to our /cmake directory + install(FILES ${CMAKE_CURRENT_LIST_FILE} DESTINATION cmake) + + # We only want to install external targets that are part of our source tree + # Checking for relative path beginning with "../" also works when the path + # given is on another drive letter on windows(i.e., RELATIVE_PATH returns an absolute path) + file(RELATIVE_PATH rel_path ${CMAKE_SOURCE_DIR} ${3RDPARTY_ROOT_DIRECTORY}) + if (NOT ${rel_path} MATCHES "^../") + get_filename_component(rel_path ${rel_path} DIRECTORY) + install(DIRECTORY ${3RDPARTY_ROOT_DIRECTORY} DESTINATION ${rel_path}) + endif() + +endfunction() + # Add the 3rdParty folder to find the modules list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/3rdParty) ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/3rdParty/Platform/${PAL_PLATFORM_NAME}) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index ff7c1a4d11..4659c3f03a 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -31,6 +31,8 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARG ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) +ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) +ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 488350f9b4..7973eb3303 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -36,6 +36,8 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) +ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) +ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index c37ee73375..afecb0788c 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -37,6 +37,9 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME Blast-1.1.7-rev1-multiplatform TARGETS Blast PACKAGE_HASH 36b8f393bcd25d0f85cfc7a831ebbdac881e6054c4f0735649966aa6aa86e6f0) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) +ly_associate_package(PACKAGE_NAME NvCloth-1.1.6-rev1-multiplatform TARGETS NvCloth PACKAGE_HASH 05fc62634ca28644e7659a89e97f4520d791e6ddf4b66f010ac669e4e2ed4454) +ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) +ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) @@ -51,3 +54,4 @@ ly_associate_package(PACKAGE_NAME pyside2-qt-5.15.1-rev2-windows TARGETS pys ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev1-windows TARGETS OpenImageIO PACKAGE_HASH b9f6d6df180ad240b9f17a68c1862c7d8f38234de0e692e83116254b0ee467e5) ly_associate_package(PACKAGE_NAME qt-5.15.2-windows TARGETS Qt PACKAGE_HASH edaf954c647c99727bfd313dab2959803d2df0873914bb96368c3d8286eed6d9) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-windows TARGETS libsamplerate PACKAGE_HASH dcf3c11a96f212a52e2c9241abde5c364ee90b0f32fe6eeb6dcdca01d491829f) +ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Windows/Crashpad_windows.cmake b/cmake/3rdParty/Platform/Windows/Crashpad_windows.cmake index 5d82e71443..ec1ce8db02 100644 --- a/cmake/3rdParty/Platform/Windows/Crashpad_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/Crashpad_windows.cmake @@ -9,11 +9,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(libpath ${BASE_PATH}/bin/windows/vs2015/$,Debug,Release>_x64) +set(libpath ${BASE_PATH}/bin/windows/vs2019/$,Debug,Release>_x64) set(CRASHPAD_LIBS ${libpath}/base.lib ${libpath}/crashpad_client.lib + ${libpath}/crashpad_context.lib ${libpath}/crashpad_util.lib winhttp version @@ -30,6 +31,6 @@ set(CRASHPAD_HANDLER_LIBS ${libpath}/third_party/getopt.lib ${libpath}/crashpad_minidump.lib ${libpath}/crashpad_snapshot.lib - ${libpath}/crashpad_handler_lib.lib + ${libpath}/crashpad_handler.lib ${libpath}/third_party/zlib.lib ) diff --git a/cmake/3rdPartyPackages.cmake b/cmake/3rdPartyPackages.cmake index 75a9f1a2cb..3984111996 100644 --- a/cmake/3rdPartyPackages.cmake +++ b/cmake/3rdPartyPackages.cmake @@ -13,7 +13,7 @@ include_guard() include(cmake/LySet.cmake) # OVERVIEW: -# this is the Lumberyard Package system. +# this is the Open 3D Engine Package system. # It allows you to host a package on a server and download it as needed when a target # requests that specific package, or manually whenever you want to do so. # Most users will just call ly_associate_package(...) to associate a package with a target diff --git a/cmake/FindTargetTemplate.cmake b/cmake/FindTargetTemplate.cmake new file mode 100644 index 0000000000..7d0129d05a --- /dev/null +++ b/cmake/FindTargetTemplate.cmake @@ -0,0 +1,45 @@ +# +# 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. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +ly_add_target( + +NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED + +@NAMESPACE_PLACEHOLDER@ + +@INCLUDE_DIRECTORIES_PLACEHOLDER@ + +@BUILD_DEPENDENCIES_PLACEHOLDER@ + +@RUNTIME_DEPENDENCIES_PLACEHOLDER@ + +@COMPILE_DEFINITIONS_PLACEHOLDER@ +) + +# The below if was generated from if (NOT HEADER_ONLY_PLACEHOLDER) +# HEADER_ONLY_PLACEHOLDER evaluates to TRUE or FALSE +if (NOT @HEADER_ONLY_PLACEHOLDER@) + # Load information for each installed configuration. + foreach(config @ALL_CONFIGS@) + set(@NAME_PLACEHOLDER@_${config}_FOUND FALSE) + include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake") + endforeach() + + find_package_handle_standard_args(@NAME_PLACEHOLDER@ + "Could not find package @NAME_PLACEHOLDER@" + @TARGET_CONFIG_FOUND_VARS_PLACEHOLDER@) +else() + set(@NAME_PLACEHOLDER@_FOUND TRUE) +endif() \ No newline at end of file diff --git a/cmake/Findo3deTemplate.cmake b/cmake/Findo3deTemplate.cmake new file mode 100644 index 0000000000..0e904fd95d --- /dev/null +++ b/cmake/Findo3deTemplate.cmake @@ -0,0 +1,35 @@ +# +# 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. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +# This will be called from within the installed engine's CMakeLists.txt +macro(ly_find_o3de_packages) + @FIND_PACKAGES_PLACEHOLDER@ + find_package(LauncherGenerator) +endmacro() + + +function(o3de_current_file_path path) + set(${path} ${CMAKE_CURRENT_FUNCTION_LIST_DIR} PARENT_SCOPE) +endfunction() + + +# We are using the engine's CMakeLists.txt to handle initialization/importing targets +# Since this is external to the project's source, we need to specify an output directory +# even though we don't build +macro(o3de_initialize) + set(LY_PROJECTS ${CMAKE_SOURCE_DIR}) + o3de_current_file_path(current_path) + add_subdirectory(${current_path}/.. o3de) +endmacro() \ No newline at end of file diff --git a/cmake/Install.cmake b/cmake/Install.cmake new file mode 100644 index 0000000000..b56f5ced85 --- /dev/null +++ b/cmake/Install.cmake @@ -0,0 +1,13 @@ +# +# 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. +# + +ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) +include(${pal_dir}/Install_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) \ No newline at end of file diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 1cfc9c473a..25465ce69c 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -53,6 +53,8 @@ define_property(TARGET PROPERTY GEM_MODULE # \arg:HEADERONLY (bool) defines this target to be a header only library. A ${NAME}_HEADERS project will be created for the IDE # \arg:EXECUTABLE (bool) defines this target to be an executable # \arg:APPLICATION (bool) defines this target to be an application (executable that is not a console) +# \arg:UNKNOWN (bool) defines this target to be unknown. This is used when importing installed targets from Find files +# \arg:IMPORTED (bool) defines this target to be imported. # \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies # \arg:OUTPUT_NAME (optional) overrides the name of the output target. If not specified, the name will be used. # \arg:OUTPUT_SUBDIRECTORY places the runtime binary in a subfolder within the output folder (this only affects to runtime binaries) @@ -75,7 +77,7 @@ define_property(TARGET PROPERTY GEM_MODULE # \arg:AUTOGEN_RULES a set of AutoGeneration rules to be passed to the AzAutoGen expansion system function(ly_add_target) - set(options STATIC SHARED MODULE GEM_MODULE HEADERONLY EXECUTABLE APPLICATION AUTOMOC AUTOUIC AUTORCC NO_UNITY) + set(options STATIC SHARED MODULE GEM_MODULE HEADERONLY EXECUTABLE APPLICATION UNKNOWN IMPORTED AUTOMOC AUTOUIC AUTORCC NO_UNITY) set(oneValueArgs NAME NAMESPACE OUTPUT_SUBDIRECTORY OUTPUT_NAME) set(multiValueArgs FILES_CMAKE GENERATED_FILES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES PLATFORM_INCLUDE_FILES TARGET_PROPERTIES AUTOGEN_RULES) @@ -85,8 +87,10 @@ function(ly_add_target) if(NOT ly_add_target_NAME) message(FATAL_ERROR "You must provide a name for the target") endif() - if(NOT ly_add_target_FILES_CMAKE) - message(FATAL_ERROR "You must provide a list of _files.cmake files for the target") + if(NOT ly_add_target_IMPORTED) + if(NOT ly_add_target_FILES_CMAKE) + message(FATAL_ERROR "You must provide a list of _files.cmake files for the target") + endif() endif() # If the GEM_MODULE tag is passed set the normal MODULE argument @@ -125,8 +129,12 @@ function(ly_add_target) set(linking_options APPLICATION) set(linking_count "${linking_count}1") endif() + if(ly_add_target_UNKNOWN) + set(linking_options UNKNOWN) + set(linking_count "${linking_count}1") + endif() if(NOT ("${linking_count}" STREQUAL "1")) - message(FATAL_ERROR "More than one of the following options [STATIC | SHARED | MODULE | HEADERONLY | EXECUTABLE | APPLICATION] was specified and they are mutually exclusive") + message(FATAL_ERROR "More than one of the following options [STATIC | SHARED | MODULE | HEADERONLY | EXECUTABLE | APPLICATION | UNKNOWN] was specified and they are mutually exclusive") endif() if(ly_add_target_NAMESPACE) @@ -157,6 +165,11 @@ function(ly_add_target) SOURCES ${ALLFILES} ${ly_add_target_GENERATED_FILES} ) set(project_NAME ${ly_add_target_NAME}_HEADERS) + elseif(ly_add_target_UNKNOWN) + add_library(${ly_add_target_NAME} + ${linking_options} + IMPORTED + ) else() add_library(${ly_add_target_NAME} ${linking_options} @@ -197,7 +210,7 @@ function(ly_add_target) endif() if (ly_add_target_INCLUDE_DIRECTORIES) - target_include_directories(${ly_add_target_NAME} + ly_target_include_directories(${ly_add_target_NAME} ${ly_add_target_INCLUDE_DIRECTORIES} ) endif() @@ -325,6 +338,17 @@ function(ly_add_target) ) endif() + if(NOT ly_add_target_IMPORTED) + ly_install_target( + ${ly_add_target_NAME} + NAMESPACE ${ly_add_target_NAMESPACE} + INCLUDE_DIRECTORIES ${ly_add_target_INCLUDE_DIRECTORIES} + BUILD_DEPENDENCIES ${ly_add_target_BUILD_DEPENDENCIES} + RUNTIME_DEPENDENCIES ${ly_add_target_RUNTIME_DEPENDENCIES} + COMPILE_DEFINITIONS ${ly_add_target_COMPILE_DEFINITIONS} + ) + endif() + endfunction() #! ly_target_link_libraries: wraps target_link_libraries handling also MODULE linkage. @@ -384,7 +408,7 @@ function(ly_delayed_target_link_libraries) endif() if(item_type STREQUAL MODULE_LIBRARY) - target_include_directories(${target} ${visibility} $) + ly_target_include_directories(${target} ${visibility} $) target_link_libraries(${target} ${visibility} $) target_compile_definitions(${target} ${visibility} $) target_compile_options(${target} ${visibility} $) @@ -485,7 +509,7 @@ endfunction() # Looks at the the following variables within the platform include file to set the equivalent target properties # LY_FILES_CMAKE -> extract list of files -> target_sources # LY_FILES -> target_source -# LY_INCLUDE_DIRECTORIES -> target_include_directories +# LY_INCLUDE_DIRECTORIES -> ly_target_include_directories # LY_COMPILE_DEFINITIONS -> target_compile_definitions # LY_COMPILE_OPTIONS -> target_compile_options # LY_LINK_OPTIONS -> target_link_options @@ -511,11 +535,7 @@ macro(ly_configure_target_platform_properties) message(FATAL_ERROR "The supplied PLATFORM_INCLUDE_FILE(${platform_include_file}) cannot be included.\ Parsing of target will halt") endif() - if(ly_add_target_HEADERONLY) - target_sources(${ly_add_target_NAME} INTERFACE ${platform_include_file}) - else() - target_sources(${ly_add_target_NAME} PRIVATE ${platform_include_file}) - endif() + target_sources(${ly_add_target_NAME} PRIVATE ${platform_include_file}) ly_source_groups_from_folders("${platform_include_file}") if(LY_FILES_CMAKE) @@ -531,7 +551,7 @@ macro(ly_configure_target_platform_properties) target_sources(${ly_add_target_NAME} PRIVATE ${LY_FILES}) endif() if (LY_INCLUDE_DIRECTORIES) - target_include_directories(${ly_add_target_NAME} ${LY_INCLUDE_DIRECTORIES}) + ly_target_include_directories(${ly_add_target_NAME} ${LY_INCLUDE_DIRECTORIES}) endif() if(LY_COMPILE_DEFINITIONS) target_compile_definitions(${ly_add_target_NAME} ${LY_COMPILE_DEFINITIONS}) @@ -634,6 +654,42 @@ function(ly_add_source_properties) endfunction() +function(ly_target_include_directories TARGET) + + # Add the includes to the build and install interface + set(reserved_keywords PRIVATE PUBLIC INTERFACE) + unset(last_keyword) + foreach(include ${ARGN}) + if(${include} IN_LIST reserved_keywords) + list(APPEND adapted_includes ${include}) + elseif(IS_ABSOLUTE ${include}) + list(APPEND adapted_includes + $ + ) + else() + string(GENEX_STRIP ${include} include_genex_expr) + if(include_genex_expr STREQUAL include) # only for cases where there are no generation expressions + # We will be installing the includes using the same directory structure used in our source tree. + # The INSTALL_INTERFACE path tells CMake the location of the includes relative to the install prefix. + # When the target is imported into an external project, cmake will find these includes at /include/ + # where is the location of the lumberyard install on disk. + file(REAL_PATH ${include} include_real) + file(RELATIVE_PATH install_dir ${CMAKE_SOURCE_DIR} ${include_real}) + list(APPEND adapted_includes + $ + $ + ) + else() + list(APPEND adapted_includes + ${include} + ) + endif() + endif() + endforeach() + target_include_directories(${TARGET} ${adapted_includes}) + +endfunction() + #! ly_project_add_subdirectory: calls add_subdirectory() if the project name is in the project list # diff --git a/cmake/LyAutoGen.cmake b/cmake/LyAutoGen.cmake index a95b0cd76f..16a8a8de55 100644 --- a/cmake/LyAutoGen.cmake +++ b/cmake/LyAutoGen.cmake @@ -26,8 +26,7 @@ function(ly_add_autogen) if(ly_add_autogen_AUTOGEN_RULES) set(AZCG_INPUTFILES ${ly_add_autogen_ALLFILES}) list(FILTER AZCG_INPUTFILES INCLUDE REGEX ".*\.(xml|json|jinja)$") - list(APPEND ly_add_autogen_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated") - target_include_directories(${ly_add_autogen_NAME} ${ly_add_autogen_INCLUDE_DIRECTORIES}) + ly_target_include_directories(${ly_add_autogen_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated") execute_process( COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/Code/Framework/AzAutoGen/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" "-n" OUTPUT_VARIABLE AUTOGEN_OUTPUTS diff --git a/cmake/Platform/Android/Install_android.cmake b/cmake/Platform/Android/Install_android.cmake new file mode 100644 index 0000000000..8473ba1d0e --- /dev/null +++ b/cmake/Platform/Android/Install_android.cmake @@ -0,0 +1,12 @@ +# +# 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(cmake/Platform/Common/Install_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Android/platform_android_files.cmake b/cmake/Platform/Android/platform_android_files.cmake index 0ccca99881..04c9e20a94 100644 --- a/cmake/Platform/Android/platform_android_files.cmake +++ b/cmake/Platform/Android/platform_android_files.cmake @@ -12,7 +12,9 @@ set(FILES ../Common/Configurations_common.cmake ../Common/Clang/Configurations_clang.cmake + ../Common/Install_common.cmake Configurations_android.cmake + Install_android.cmake LYTestWrappers_android.cmake LYWrappers_android.cmake PAL_android.cmake diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake new file mode 100644 index 0000000000..9164105f3a --- /dev/null +++ b/cmake/Platform/Common/Install_common.cmake @@ -0,0 +1,284 @@ +# +# 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. +# + + +#! ly_install_target: registers the target to be installed by cmake install. +# +# \arg:NAME name of the target +# \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies +# \arg:INCLUDE_DIRECTORIES paths to the include directories +# \arg:BUILD_DEPENDENCIES list of interfaces this target depends on (could be a compilation dependency +# if the dependency is only exposing an include path, or could be a linking +# dependency is exposing a lib) +# \arg:RUNTIME_DEPENDENCIES list of dependencies this target depends on at runtime +# \arg:COMPILE_DEFINITIONS list of compilation definitions this target will use to compile +function(ly_install_target ly_install_target_NAME) + + # All include directories marked PUBLIC or INTERFACE will be installed + set(include_location "include") + get_target_property(include_directories ${ly_install_target_NAME} INTERFACE_INCLUDE_DIRECTORIES) + + if (include_directories) + set_target_properties(${ly_install_target_NAME} PROPERTIES PUBLIC_HEADER "${include_directories}") + # The include directories are specified relative to the CMakeLists.txt file that adds the target. + # We need to install the includes relative to our source tree root because that's where INSTALL_INTERFACE + # will point CMake when it looks for headers + file(RELATIVE_PATH relative_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + string(APPEND include_location "/${relative_path}") + endif() + + ly_generate_target_find_file( + NAME ${ly_install_target_NAME} + ${ARGN} + ) + + install( + TARGETS ${ly_install_target_NAME} + EXPORT ${ly_install_target_NAME}Targets + LIBRARY DESTINATION lib/$ + ARCHIVE DESTINATION lib/$ + RUNTIME DESTINATION bin/$ + PUBLIC_HEADER DESTINATION ${include_location} + ) + + install(EXPORT ${ly_install_target_NAME}Targets + DESTINATION cmake_autogen/${ly_install_target_NAME} + ) + + # Header only targets(i.e., INTERFACE) don't have outputs + get_target_property(target_type ${ly_install_target_NAME} TYPE) + if(NOT ${target_type} STREQUAL "INTERFACE_LIBRARY") + ly_generate_target_config_file(${ly_install_target_NAME}) + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${ly_install_target_NAME}_$.cmake" + DESTINATION cmake_autogen/${ly_install_target_NAME} + ) + endif() + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Find${ly_install_target_NAME}.cmake" + DESTINATION cmake + ) + +endfunction() + + +#! ly_generate_target_find_file: generates the Find${target}.cmake file which is used when importing installed packages. +# +# \arg:NAME name of the target +# \arg:INCLUDE_DIRECTORIES paths to the include directories +# \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies +# \arg:BUILD_DEPENDENCIES list of interfaces this target depends on (could be a compilation dependency +# if the dependency is only exposing an include path, or could be a linking +# dependency is exposing a lib) +# \arg:RUNTIME_DEPENDENCIES list of dependencies this target depends on at runtime +# \arg:COMPILE_DEFINITIONS list of compilation definitions this target will use to compile +function(ly_generate_target_find_file) + + set(options) + set(oneValueArgs NAME NAMESPACE) + set(multiValueArgs COMPILE_DEFINITIONS BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES INCLUDE_DIRECTORIES) + cmake_parse_arguments(ly_generate_target_find_file "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # These targets will be imported. So we strip PRIVATE properties. + # We can only set INTERFACE properties on imported targets + unset(build_dependencies_interface_props) + unset(compile_definitions_interface_props) + unset(include_directories_interface_props) + unset(installed_include_directories_interface_props) + ly_strip_non_interface_properties(build_dependencies_interface_props ${ly_generate_target_find_file_BUILD_DEPENDENCIES}) + ly_strip_non_interface_properties(compile_definitions_interface_props ${ly_generate_target_find_file_COMPILE_DEFINITIONS}) + ly_strip_non_interface_properties(include_directories_interface_props ${ly_generate_target_find_file_INCLUDE_DIRECTORIES}) + + set(NAME_PLACEHOLDER ${ly_generate_target_find_file_NAME}) + + # Includes need additional processing to add the install root + foreach(include ${include_directories_interface_props}) + set(installed_include_prefix "\${LY_ROOT_FOLDER}/include/") + file(RELATIVE_PATH relative_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${include}) + string(APPEND installed_include_prefix ${relative_path}) + list(APPEND installed_include_directories_interface_props ${installed_include_prefix}) + endforeach() + + if(ly_generate_target_find_file_NAMESPACE) + set(NAMESPACE_PLACEHOLDER "NAMESPACE ${ly_generate_target_find_file_NAMESPACE}") + endif() + if(installed_include_directories_interface_props) + string(REPLACE ";" "\n" include_dirs "${installed_include_directories_interface_props}") + set(INCLUDE_DIRECTORIES_PLACEHOLDER "INCLUDE_DIRECTORIES\nINTERFACE\n${include_dirs}") + endif() + if(build_dependencies_interface_props) + string(REPLACE ";" "\n" build_deps "${build_dependencies_interface_props}") + set(BUILD_DEPENDENCIES_PLACEHOLDER "BUILD_DEPENDENCIES\nINTERFACE\n${build_deps}") + endif() + if(ly_generate_target_find_file_RUNTIME_DEPENDENCIES) + string(REPLACE ";" "\n" runtime_deps "${ly_generate_target_find_file_RUNTIME_DEPENDENCIES}") + set(RUNTIME_DEPENDENCIES_PLACEHOLDER "RUNTIME_DEPENDENCIES\n${runtime_deps}") + endif() + if(compile_definitions_interface_props) + string(REPLACE ";" "\n" compile_defs "${compile_definitions_interface_props}") + set(COMPILE_DEFINITIONS_PLACEHOLDER "COMPILE_DEFINITIONS\nINTERFACE\n${compile_defs}") + endif() + + string(REPLACE ";" " " ALL_CONFIGS "${CMAKE_CONFIGURATION_TYPES}") + + set(target_config_found_vars "") + foreach(config ${CMAKE_CONFIGURATION_TYPES}) + string(APPEND target_config_found_vars "\n${ly_generate_target_find_file_NAME}_${config}_FOUND") + endforeach() + set(TARGET_CONFIG_FOUND_VARS_PLACEHOLDER "${target_config_found_vars}") + + # Interface libs aren't built so they don't generate a library. These are our HEADER_ONLY targets. + get_target_property(target_type ${ly_generate_target_find_file_NAME} TYPE) + if(NOT ${target_type} STREQUAL "INTERFACE_LIBRARY") + set(HEADER_ONLY_PLACEHOLDER FALSE) + else() + set(HEADER_ONLY_PLACEHOLDER TRUE) + endif() + + configure_file(${LY_ROOT_FOLDER}/cmake/FindTargetTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) + +endfunction() + + +#! ly_generate_target_config_file: generates the ${target}_$.cmake files for a target +# +# The generated file will set the location of the target binary per configuration +# These per config files will be included by the target's find file to set the location of the binary/ +# \arg:NAME name of the target +function(ly_generate_target_config_file NAME) + + # SHARED_LIBRARY is omitted from this list because we link to the implib on Windows + set(BINARY_DIR_OUTPUTS EXECUTABLE APPLICATION) + set(target_file_contents "") + if(${target_type} IN_LIST BINARY_DIR_OUTPUTS) + set(out_file_generator TARGET_FILE_NAME) + set(out_dir bin) + else() + set(out_file_generator TARGET_LINKER_FILE_NAME) + set(out_dir lib) + endif() + + string(APPEND target_file_contents " +# Generated by O3DE + +set_target_properties(${NAME} PROPERTIES IMPORTED_LOCATION \"\${LY_ROOT_FOLDER}/${out_dir}/$/$<${out_file_generator}:${NAME}>\") + +if(EXISTS \"\${LY_ROOT_FOLDER}/${out_dir}/$/$<${out_file_generator}:${NAME}>\") + set(${NAME}_$_FOUND TRUE) +else() + set(${NAME}_$_FOUND FALSE) +endif()") + + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}_$.cmake" CONTENT ${target_file_contents}) + +endfunction() + + +#! ly_strip_non_interface_properties: strips private properties since we're exporting an interface target +# +# \arg:INTERFACE_PROPERTIES list of interface properties to be returned +function(ly_strip_non_interface_properties INTERFACE_PROPERTIES) + set(reserved_keywords PRIVATE PUBLIC INTERFACE) + unset(last_keyword) + unset(stripped_props) + foreach(prop ${ARGN}) + if(${prop} IN_LIST reserved_keywords) + set(last_keyword ${prop}) + else() + if (NOT last_keyword STREQUAL "PRIVATE") + list(APPEND stripped_props ${prop}) + endif() + endif() + endforeach() + + set(${INTERFACE_PROPERTIES} ${stripped_props} PARENT_SCOPE) +endfunction() + + +#! ly_setup_o3de_install: generates the Findo3de.cmake file and setup install locations for scripts, tools, assets etc., +function(ly_setup_o3de_install) + + get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) + unset(find_package_list) + foreach(target IN LISTS all_targets) + list(APPEND find_package_list "find_package(${target})") + endforeach() + + string(REPLACE ";" "\n" FIND_PACKAGES_PLACEHOLDER "${find_package_list}") + + configure_file(${LY_ROOT_FOLDER}/cmake/Findo3deTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) + + ly_install_launcher_target_generator() + + ly_install_o3de_directories() + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake" + DESTINATION cmake + ) + + install(FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt" + DESTINATION . + ) + +endfunction() + + +#! ly_install_o3de_directories: install directories required by the engine +function(ly_install_o3de_directories) + + # List of directories we want to install relative to engine root + set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole ctest_scripts scripts) + foreach(dir ${DIRECTORIES_TO_INSTALL}) + + get_filename_component(install_path ${dir} DIRECTORY) + if (NOT install_path) + set(install_path .) + endif() + + install(DIRECTORY "${CMAKE_SOURCE_DIR}/${dir}" + DESTINATION ${install_path} + ) + + endforeach() + + # Directories which have excludes + install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" + DESTINATION . + REGEX "Findo3de.cmake" EXCLUDE + ) + + install(DIRECTORY "${CMAKE_SOURCE_DIR}/python" + DESTINATION . + REGEX "downloaded_packages" EXCLUDE + REGEX "runtime" EXCLUDE + ) + +endfunction() + + +#! ly_install_launcher_target_generator: install source files needed for project launcher generation +function(ly_install_launcher_target_generator) + + install(FILES + ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/launcher_generator.cmake + ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/launcher_project_files.cmake + ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/LauncherProject.cpp + ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/StaticModules.in + DESTINATION LauncherGenerator + ) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/Platform + DESTINATION LauncherGenerator + ) + install(FILES ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/FindLauncherGenerator.cmake + DESTINATION cmake + ) + +endfunction() \ No newline at end of file diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 7ecfb98706..25b6e63ab9 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -76,7 +76,6 @@ ly_append_configurations_options( /wd4457 # declaration hides function parameter /wd4459 # declaration hides global declaration /wd4701 # potentially unintialized local variable - /wd4702 # unreachable code # Enabling warnings that are disabled by default from /W4 # https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019 @@ -162,10 +161,10 @@ ly_set(LY_CXX_SYSTEM_INCLUDE_CONFIGURATION_FLAG /experimental:external # Turns on "external" headers feature for MSVC compilers /external:W0 # Set warning level in external headers to 0. This is used to suppress warnings 3rdParty libraries which uses the "system_includes" option in their json configuration /wd4193 # Temporary workaround for the /experiment:external feature generating warning C4193: #pragma warning(pop): no matching '#pragma warning(push)' + /wd4702 # Despite we set it to W0, we found that 3rdParty::OpenMesh was issuing these warnings while using some template functions. Disabling it here does the trick ) if(NOT CMAKE_INCLUDE_SYSTEM_FLAG_CXX) ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX /external:I) endif() include(cmake/Platform/Common/TargetIncludeSystemDirectories_unsupported.cmake) - diff --git a/cmake/Platform/Linux/Install_linux.cmake b/cmake/Platform/Linux/Install_linux.cmake new file mode 100644 index 0000000000..8473ba1d0e --- /dev/null +++ b/cmake/Platform/Linux/Install_linux.cmake @@ -0,0 +1,12 @@ +# +# 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(cmake/Platform/Common/Install_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Linux/platform_linux_files.cmake b/cmake/Platform/Linux/platform_linux_files.cmake index 678d2961e5..8b6bdf1361 100644 --- a/cmake/Platform/Linux/platform_linux_files.cmake +++ b/cmake/Platform/Linux/platform_linux_files.cmake @@ -12,7 +12,9 @@ set(FILES ../Common/Configurations_common.cmake ../Common/Clang/Configurations_clang.cmake + ../Common/Install_common.cmake Configurations_linux.cmake + Install_linux.cmake LYTestWrappers_linux.cmake LYWrappers_linux.cmake PAL_linux.cmake diff --git a/cmake/Platform/Mac/Install_mac.cmake b/cmake/Platform/Mac/Install_mac.cmake new file mode 100644 index 0000000000..8c96c199de --- /dev/null +++ b/cmake/Platform/Mac/Install_mac.cmake @@ -0,0 +1,21 @@ +# +# 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. +# + +# Empty implementations for untested platforms to fix build errors. + +function(ly_install_target ly_install_target_NAME) + +endfunction() + + +function(ly_setup_o3de_install) + +endfunction() \ No newline at end of file diff --git a/cmake/Platform/Mac/platform_mac_files.cmake b/cmake/Platform/Mac/platform_mac_files.cmake index 30c89d0f4c..82e2827623 100644 --- a/cmake/Platform/Mac/platform_mac_files.cmake +++ b/cmake/Platform/Mac/platform_mac_files.cmake @@ -13,6 +13,7 @@ set(FILES ../Common/Configurations_common.cmake ../Common/Clang/Configurations_clang.cmake Configurations_mac.cmake + Install_mac.cmake LYTestWrappers_mac.cmake LYWrappers_mac.cmake PAL_mac.cmake diff --git a/cmake/Platform/Windows/Install_windows.cmake b/cmake/Platform/Windows/Install_windows.cmake new file mode 100644 index 0000000000..8473ba1d0e --- /dev/null +++ b/cmake/Platform/Windows/Install_windows.cmake @@ -0,0 +1,12 @@ +# +# 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(cmake/Platform/Common/Install_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Windows/platform_windows_files.cmake b/cmake/Platform/Windows/platform_windows_files.cmake index 3310972cee..bf9cb05d17 100644 --- a/cmake/Platform/Windows/platform_windows_files.cmake +++ b/cmake/Platform/Windows/platform_windows_files.cmake @@ -14,6 +14,7 @@ set(FILES ../Common/VisualStudio_common.cmake ../Common/Configurations_common.cmake ../Common/MSVC/Configurations_msvc.cmake + ../Common/Install_common.cmake ../Common/LYWrappers_default.cmake ../Common/TargetIncludeSystemDirectories_unsupported.cmake Configurations_windows.cmake @@ -21,4 +22,5 @@ set(FILES LYWrappers_windows.cmake PAL_windows.cmake PALDetection_windows.cmake + Install_windows.cmake ) diff --git a/cmake/Platform/iOS/Install_ios.cmake b/cmake/Platform/iOS/Install_ios.cmake new file mode 100644 index 0000000000..8c96c199de --- /dev/null +++ b/cmake/Platform/iOS/Install_ios.cmake @@ -0,0 +1,21 @@ +# +# 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. +# + +# Empty implementations for untested platforms to fix build errors. + +function(ly_install_target ly_install_target_NAME) + +endfunction() + + +function(ly_setup_o3de_install) + +endfunction() \ No newline at end of file diff --git a/cmake/Platform/iOS/platform_ios_files.cmake b/cmake/Platform/iOS/platform_ios_files.cmake index 1e8b18d0ea..ca14b5e80f 100644 --- a/cmake/Platform/iOS/platform_ios_files.cmake +++ b/cmake/Platform/iOS/platform_ios_files.cmake @@ -13,6 +13,7 @@ set(FILES ../Common/Configurations_common.cmake ../Common/Clang/Configurations_clang.cmake Configurations_ios.cmake + Install_ios.cmake LYTestWrappers_ios.cmake LYWrappers_ios.cmake PAL_ios.cmake diff --git a/cmake/SettingsRegistry.cmake b/cmake/SettingsRegistry.cmake index fda8428cbb..fd5985a5a1 100644 --- a/cmake/SettingsRegistry.cmake +++ b/cmake/SettingsRegistry.cmake @@ -10,7 +10,7 @@ # # Responsible for generating a settings registry file containing the moduleload dependencies of any ly_delayed_load_targets -# This is used for example, to allow Lumberyard Applications to know which set of gems have built for a particular project/target +# This is used for example, to allow Open 3D Engine Applications to know which set of gems have built for a particular project/target # combination include_guard() diff --git a/cmake/Tools/Platform/Android/android_support.py b/cmake/Tools/Platform/Android/android_support.py index d98aee177c..6443077457 100755 --- a/cmake/Tools/Platform/Android/android_support.py +++ b/cmake/Tools/Platform/Android/android_support.py @@ -787,14 +787,14 @@ class AndroidProjectGenerator(object): gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = \ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR.format(config=native_config, config_lower=native_config_lower, - asset_layout_folder=(self.build_dir / 'app/src/main/assets').as_posix(), + asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='Test.Assets/**/*.*') else: # Copy over settings registry files from the Registry folder with build output directory gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = \ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR.format(config=native_config, config_lower=native_config_lower, - asset_layout_folder=(self.build_dir / 'app/src/main/assets').as_posix(), + asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='**/Registry/*.setreg') if self.include_assets_in_apk: @@ -805,7 +805,7 @@ class AndroidProjectGenerator(object): asset_type=self.asset_type, project_path=self.project_path.as_posix(), asset_mode=self.asset_mode if native_config != 'Release' else 'PAK', - asset_layout_folder=common.normalize_path_for_settings(self.build_dir / 'app/src/main/assets'), + asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), config=native_config) else: gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = '' diff --git a/cmake/Tools/Platform/Android/generate_android_project.py b/cmake/Tools/Platform/Android/generate_android_project.py index 28c6d7c601..f3f6a3acda 100755 --- a/cmake/Tools/Platform/Android/generate_android_project.py +++ b/cmake/Tools/Platform/Android/generate_android_project.py @@ -28,7 +28,7 @@ from cmake.Tools.Platform.Android import android_support GRADLE_ARGUMENT_NAME = '--gradle-install-path' GRADLE_MIN_VERSION = LooseVersion('4.10.1') -GRADLE_MAX_VERSION = LooseVersion('5.6.4') +GRADLE_MAX_VERSION = LooseVersion('7.0.0') GRADLE_VERSION_REGEX = re.compile(r"Gradle\s(\d+.\d+.?\d*)") GRADLE_EXECUTABLE = 'gradle.bat' if platform.system() == 'Windows' else 'gradle' diff --git a/cmake/UnitTest.cmake b/cmake/UnitTest.cmake index 096f0f7e7e..c867f9dc18 100644 --- a/cmake/UnitTest.cmake +++ b/cmake/UnitTest.cmake @@ -39,7 +39,7 @@ set(CTEST_RUN_FLAGS ${CTEST_RUN_FLAGS_STRING} CACHE STRING "Command line argumen set(CMAKE_CTEST_ARGUMENTS ${CTEST_RUN_FLAGS} -LE SUITE_benchmark) #! ly_add_suite_build_and_run_targets - Add CMake Targets for associating dependencies with each -# suite of test supported by Lumberyard +# suite of test supported by Open 3D Engine function(ly_add_suite_build_and_run_targets) if(NOT PAL_TRAIT_BUILD_TESTS_SUPPORTED) return() diff --git a/cmake/Version.cmake b/cmake/Version.cmake index ade3d86318..08d79d4ce6 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -10,6 +10,6 @@ # string(TIMESTAMP current_year "%Y") -set(LY_VERSION_COPYRIGHT_YEAR ${current_year} CACHE STRING "Lumberyard's copyright year") -set(LY_VERSION_STRING "0.0.0.0" CACHE STRING "Lumberyard's version") -set(LY_VERSION_BUILD_NUMBER 0 CACHE STRING "Lumberyard's build number") \ No newline at end of file +set(LY_VERSION_COPYRIGHT_YEAR ${current_year} CACHE STRING "Open 3D Engine's copyright year") +set(LY_VERSION_STRING "0.0.0.0" CACHE STRING "Open 3D Engine's version") +set(LY_VERSION_BUILD_NUMBER 0 CACHE STRING "Open 3D Engine's build number") \ No newline at end of file diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index 03b6c1d990..2b0f65ca99 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -19,6 +19,7 @@ set(FILES EngineFinder.cmake FileUtil.cmake Findo3de.cmake + Install.cmake LyAutoGen.cmake LySet.cmake LYTestWrappers.cmake diff --git a/engine.json b/engine.json index ed6677d795..5091605f4c 100644 --- a/engine.json +++ b/engine.json @@ -1,6 +1,6 @@ { "engine_name": "o3de", "FileVersion": 1, - "LumberyardVersion": "0.0.0.0", - "LumberyardCopyrightYear": 2021 + "O3DEVersion": "0.0.0.0", + "O3DECopyrightYear": 2021 } diff --git a/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json b/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json index eed4c45fcb..26733303a6 100644 --- a/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json +++ b/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json @@ -4,6 +4,7 @@ "AWS/AWSNativeSDK/1.7.167-az.2/**": "#include", "AWS/GameLift/3.4.0/**": "#include", "civetweb/civetweb-20160922-az.2/**": "#include", + "CMake/3.19.1/**": "#include", "DirectXShaderCompiler/1.0.1-az.1/**": "#include", "DirectXShaderCompiler/2020.08.07/**": "#include", "DirectXShaderCompiler/5.0.0-az/**": "#include", @@ -13,7 +14,6 @@ "FbxSdk/2016.1.2-az.1/**": "#include", "libav/11.7/**": "#include", "OpenSSL/1.1.1b-noasm-az/**": "#include", - "Qt/5.15.1.2-az/**": "#include", "RadTelemetry/3.5.0.17/**": "#include", "tiff/3.9.5-az.3/**": "#include", diff --git a/scripts/build/package/Platform/Mac/package_env.json b/scripts/build/package/Platform/Mac/package_env.json index 642c39d625..f21c9fdaab 100644 --- a/scripts/build/package/Platform/Mac/package_env.json +++ b/scripts/build/package/Platform/Mac/package_env.json @@ -1,5 +1,7 @@ { - "local_env": {}, + "local_env": { + "S3_PREFIX": "${BRANCH_NAME}/Mac" + }, "types":{ "all":{ "PACKAGE_TARGETS":[ @@ -7,6 +9,16 @@ "FILE_LIST": "all.json", "FILE_LIST_TYPE": "All", "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-mac-all-${BUILD_NUMBER}.zip" + }, + { + "FILE_LIST": "3rdParty.json", + "FILE_LIST_TYPE": "Mac", + "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-mac-3rdParty-${BUILD_NUMBER}.zip" + }, + { + "FILE_LIST": "3rdParty.json", + "FILE_LIST_TYPE": "3rdParty", + "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-mac-3rdParty-Warsaw-${BUILD_NUMBER}.zip" } ], "BOOTSTRAP_CFG_GAME_FOLDER":"CMakeTestbed", diff --git a/scripts/build/package/Platform/Mac/package_filelists/3rdParty.json b/scripts/build/package/Platform/Mac/package_filelists/3rdParty.json new file mode 100644 index 0000000000..ff019f701f --- /dev/null +++ b/scripts/build/package/Platform/Mac/package_filelists/3rdParty.json @@ -0,0 +1,82 @@ +{ + "@3rdParty":{ + "3rdParty.txt":"#include", + "AWS/AWSNativeSDK/1.7.167-az.2":{ + "*":"#include", + "include/**":"#include", + "LICENSE*":"#include", + "lib/mac/**":"#include", + "bin/mac/**":"#include", + "lib/ios/**":"#include", + "bin/ios/**":"#include" + }, + "DirectXShaderCompiler/1.0.1-az.1":{ + "*":"#include", + "src/**":"#include", + "bin/darwin_x64/**":"#include" + }, + "DirectXShaderCompiler/2020.08.07":{ + "*":"#include", + "bin/darwin_x64/**":"#include" + }, + "DirectXShaderCompiler/5.0.0-az":{ + "*":"#include", + "bin/darwin_x64/**":"#include" + }, + "etc2comp/2017_04_24-az.2":{ + "*":"#include", + "EtcLib/Etc/**":"#include", + "EtcLib/EtcCodec/**":"#include", + "EtcLib/*":"#include", + "EtcLib/OSX_x86/**":"#include" + }, + "expat/2.1.0-pkg.3":{ + "*":"#include", + "amiga/**":"#include", + "bcb5/**":"#include", + "conftools/**":"#include", + "doc/**":"#include", + "examples/**":"#include", + "lib/**":"#include", + "m4/**":"#include", + "tests/**":"#include", + "vms/**":"#include", + "win32/**":"#include", + "xmlwf/**":"#include", + "build/osx/**":"#include" + }, + "FreeType2/2.5.0.1-pkg.3":{ + "freetype-2.5.0.1/**":"#include", + "dist/**":"#include", + "mac/**":"#include", + "ios*/**":"#include", + "build/osx/**":"#include" + }, + "Redistributables/FbxSdk/2016.1.2":{ + "*mac*":"#include" + }, + "OpenSSL/1.1.1b-noasm-az":{ + "include/**":"#include", + "ssl/**":"#include", + "LICENSE":"#include", + "bin/**":"#include", + "lib/darwin*/**":"#include", + "lib/ios*/**":"#include" + }, + "Qt/5.15.1.2-az":{ + "LICENSE":"#include", + "LGPL_EXCEPTION.TXT":"#include", + "LICENSE.GPLV3":"#include", + "LICENSE.LGPLV3":"#include", + "QT-NOTICE.TXT":"#include", + "clang_64/**":"#include" + }, + "tiff/3.9.5-az.3":{ + "COPYRIGHT":"#include", + "README":"#include", + "RELEASE-DATE":"#include", + "VERSION":"#include", + "libtiff/macosx_clang/**":"#include" + } + } +} \ No newline at end of file From 774580cea2d399814cd83881438d2426dd861c96 Mon Sep 17 00:00:00 2001 From: alexpete Date: Tue, 13 Apr 2021 17:30:43 -0700 Subject: [PATCH 025/122] Updating README to mention 3p rev13 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9246104a29..caed4b515c 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ If you have the Git credential manager core installed, you should not be prompte ### Build Steps -1. Download the 3rdParty zip file from here: **[https://d2c171ws20a1rv.cloudfront.net/3rdParty-windows-no-symbols-rev12.zip](https://d2c171ws20a1rv.cloudfront.net/3rdParty-windows-no-symbols-rev12.zip)** +1. Download the 3rdParty zip file from here: **[https://d2c171ws20a1rv.cloudfront.net/3rdParty-windows-no-symbols-rev13.zip](https://d2c171ws20a1rv.cloudfront.net/3rdParty-windows-no-symbols-rev13.zip)** 2. Unzip this file into a writable folder. This will also act as a cache location for the 3rdParty downloader by default (configurable with the `LY_PACKAGE_DOWNLOAD_CACHE_LOCATION` environment variable) 3. Install the following redistributables to the following: - Visual Studio and VC++ redistributable can be installed to any location From fa9366b81017a29f92ba1cd3ad158eccd3118ade Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Tue, 13 Apr 2021 19:35:59 -0500 Subject: [PATCH 026/122] Updating the AutomatedTesting project to support being built as an External Project --- AutomatedTesting/CMakeLists.txt | 40 +++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/AutomatedTesting/CMakeLists.txt b/AutomatedTesting/CMakeLists.txt index b2d9a18c6a..289d0a6565 100644 --- a/AutomatedTesting/CMakeLists.txt +++ b/AutomatedTesting/CMakeLists.txt @@ -9,12 +9,38 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json) +#! Adds the --project-path argument to the VS IDE debugger command arguments +function(add_vs_debugger_arguments) + # Inject the project root into the --project-path argument into the Visual Studio Debugger arguments by defaults + list(APPEND app_targets AutomatedTesting.GameLauncher AutomatedTesting.ServerLauncher) + list(APPEND app_targets AssetBuilder AssetProcessor AssetProcessorBatch Editor) + foreach(app_target IN LISTS app_targets) + if (TARGET ${app_target}) + set_property(TARGET ${app_target} APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${CMAKE_CURRENT_LIST_DIR}\"") + endif() + endforeach() +endfunction() -string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name") -if(${json_error}) - message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'") -endif() +if(NOT PROJECT_NAME) + cmake_minimum_required(VERSION 3.19) + project(AutomatedTesting + LANGUAGES C CXX + VERSION 1.0.0.0 + ) + include(EngineFinder.cmake OPTIONAL) + find_package(o3de REQUIRED) + o3de_initialize() + add_vs_debugger_arguments() +else() + # Add the project_name to global LY_PROJECTS_TARGET_NAME property + file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json) -set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) -add_subdirectory(Gem) + string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name") + if(json_error) + message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'") + endif() + + set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) + + add_subdirectory(Gem) +endif() \ No newline at end of file From 92b8e590ce850090f197b18b328a23ab68a3e60b Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Tue, 13 Apr 2021 19:42:30 -0500 Subject: [PATCH 027/122] Added better error message around when the Unified Launcher target for a Project cannot be configured due to issues querying the project name from the provided project path --- Code/LauncherUnified/CMakeLists.txt | 15 +++++++++++++++ Templates/DefaultProject/Template/CMakeLists.txt | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Code/LauncherUnified/CMakeLists.txt b/Code/LauncherUnified/CMakeLists.txt index 0d056686b8..2cd53bdb41 100644 --- a/Code/LauncherUnified/CMakeLists.txt +++ b/Code/LauncherUnified/CMakeLists.txt @@ -73,6 +73,21 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC # If the project_path is relative, it is evaluated relative to the ${LY_ROOT_FOLDER} # Otherwise the the absolute project_path is returned with symlinks resolved file(REAL_PATH ${project_path} project_real_path BASE_DIRECTORY ${LY_ROOT_FOLDER}) + if(NOT project_name) + if(NOT EXISTS ${project_real_path}/project.json) + message(FATAL_ERROR "The specified project path of ${project_real_path} does not contain a project.json file with a \"project name\" entry in it") + else() + # Add the project_name to global LY_PROJECTS_TARGET_NAME property + file(READ "${project_real_path}/project.json" project_json) + string(JSON project_name ERROR_VARIABLE json_error GET ${project_json} "project_name") + if(json_error) + message(FATAL_ERROR "There is an error reading the \"project_name\" key from the '${project_real_path}/project.json' file: ${json_error}") + endif() + message(WARNING "The project located at path ${project_real_path} has a valid \"project name\" of '${project_name}' read from it's project.json file." + " This indicates that the ${project_real_path}/CMakeLists.txt is not properly appending the \"project name\" " + "to the LY_PROJECTS_TARGET_NAME global property. Other configuration errors might occur") + endif() + endif() ################################################################################ # Monolithic game ################################################################################ diff --git a/Templates/DefaultProject/Template/CMakeLists.txt b/Templates/DefaultProject/Template/CMakeLists.txt index 24b229d05b..c314f0da5c 100644 --- a/Templates/DefaultProject/Template/CMakeLists.txt +++ b/Templates/DefaultProject/Template/CMakeLists.txt @@ -38,7 +38,7 @@ else() file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json) string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name") - if(${json_error}) + if(json_error) message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'") endif() From 957945f8093c0fbc9ced20e5bebec14e2d03ee38 Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Tue, 13 Apr 2021 19:50:06 -0500 Subject: [PATCH 028/122] Clarified the error message that is output when the project.json is not found --- Code/LauncherUnified/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/LauncherUnified/CMakeLists.txt b/Code/LauncherUnified/CMakeLists.txt index 2cd53bdb41..f0eb361f42 100644 --- a/Code/LauncherUnified/CMakeLists.txt +++ b/Code/LauncherUnified/CMakeLists.txt @@ -75,7 +75,7 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC file(REAL_PATH ${project_path} project_real_path BASE_DIRECTORY ${LY_ROOT_FOLDER}) if(NOT project_name) if(NOT EXISTS ${project_real_path}/project.json) - message(FATAL_ERROR "The specified project path of ${project_real_path} does not contain a project.json file with a \"project name\" entry in it") + message(FATAL_ERROR "The specified project path of ${project_real_path} does not contain a project.json file") else() # Add the project_name to global LY_PROJECTS_TARGET_NAME property file(READ "${project_real_path}/project.json" project_json) From ca3df5d6c8f89edb1cfa4c1d8e3ca5a463af6e26 Mon Sep 17 00:00:00 2001 From: karlberg Date: Tue, 13 Apr 2021 20:24:08 -0700 Subject: [PATCH 029/122] Various bug fixes to get entity replication working --- .../AzCore/AzCore/Component/TransformBus.h | 2 +- .../DataStructures/FixedSizeBitset.h | 3 + .../DataStructures/FixedSizeVectorBitset.inl | 12 +-- .../Serialization/AzContainerSerializers.h | 10 +-- Gems/Multiplayer/Code/Include/IMultiplayer.h | 16 ++++ .../Source/AutoGen/AutoComponent_Header.jinja | 31 ++++---- .../Source/AutoGen/AutoComponent_Source.jinja | 66 +++++++++------- .../LocalPredictionPlayerInputComponent.cpp | 1 - .../Components/MultiplayerComponent.cpp | 8 +- .../Source/Components/MultiplayerComponent.h | 8 +- .../Components/MultiplayerController.cpp | 5 ++ .../Source/Components/MultiplayerController.h | 4 + .../Components/NetworkTransformComponent.cpp | 78 ++++++++++++++++++- .../Components/NetworkTransformComponent.h | 32 ++++++-- .../ClientToServerConnectionData.cpp | 59 ++++++++++++++ .../ClientToServerConnectionData.h | 47 +++++++++++ .../ClientToServerConnectionData.inl | 19 +++++ .../Source/ConnectionData/IConnectionData.h | 1 + .../Source/MultiplayerSystemComponent.cpp | 54 ++++++++----- .../Code/Source/MultiplayerSystemComponent.h | 2 +- .../EntityReplicationManager.cpp | 37 +++++---- .../EntityReplicationManager.h | 3 +- .../EntityReplication/EntityReplicator.cpp | 6 +- .../NetworkEntity/NetworkEntityManager.cpp | 21 +++-- .../Source/NetworkTime/RewindableObject.inl | 11 +-- .../NullReplicationWindow.cpp | 47 +++++++++++ .../NullReplicationWindow.h | 38 +++++++++ .../ServerToClientReplicationWindow.cpp | 6 +- Gems/Multiplayer/Code/multiplayer_files.cmake | 5 ++ 29 files changed, 495 insertions(+), 137 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl create mode 100644 Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp create mode 100644 Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h diff --git a/Code/Framework/AzCore/AzCore/Component/TransformBus.h b/Code/Framework/AzCore/AzCore/Component/TransformBus.h index b0e617f220..2003b949e2 100644 --- a/Code/Framework/AzCore/AzCore/Component/TransformBus.h +++ b/Code/Framework/AzCore/AzCore/Component/TransformBus.h @@ -26,7 +26,7 @@ namespace AZ { class Transform; - using TransformChangedEvent = Event; + using TransformChangedEvent = Event; using ParentChangedEvent = Event; diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h index 21e12cd305..a91f42b3a0 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h @@ -114,6 +114,9 @@ namespace AzNetworking void ClearUnusedBits(); ContainerType m_container; + + template + friend class FixedSizeVectorBitset; }; } diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl index a8aceb4dd5..038e68d1d0 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl @@ -192,19 +192,11 @@ namespace AzNetworking template inline void FixedSizeVectorBitset::ClearUnusedBits() { - constexpr ElementType AllOnes = static_cast(~0); - const ElementType LastUsedBits = (GetSize() % BitsetType::ElementTypeBits); -#pragma warning(push) -#pragma warning(disable : 4293) // shift count negative or too big, undefined behaviour -#pragma warning(disable : 6326) // constant constant comparison - const ElementType ShiftAmount = (LastUsedBits == 0) ? 0 : BitsetType::ElementTypeBits - LastUsedBits; - const ElementType ClearBitMask = AllOnes >> ShiftAmount; -#pragma warning(pop) uint32_t usedElementSize = (GetSize() + BitsetType::ElementTypeBits - 1) / BitsetType::ElementTypeBits; - for (uint32_t i = usedElementSize + 1; i < CAPACITY; ++i) + for (uint32_t i = usedElementSize + 1; i < BitsetType::ElementCount; ++i) { m_bitset.GetContainer()[i] = 0; } - m_bitset.GetContainer()[m_bitset.GetContainer().size() - 1] &= ClearBitMask; + m_bitset.ClearUnusedBits(); } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h index 70dc7847d2..a43a09165c 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h @@ -270,7 +270,7 @@ namespace AzNetworking value.StoreToFloat3(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); + serializer.Serialize(values[2], "zValue"); value = AZ::Vector3::CreateFromFloat3(values); return serializer.IsValid(); } @@ -285,8 +285,8 @@ namespace AzNetworking value.StoreToFloat4(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); - serializer.Serialize(values[1], "wValue"); + serializer.Serialize(values[2], "zValue"); + serializer.Serialize(values[3], "wValue"); value = AZ::Vector4::CreateFromFloat4(values); return serializer.IsValid(); } @@ -301,8 +301,8 @@ namespace AzNetworking value.StoreToFloat4(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); - serializer.Serialize(values[1], "wValue"); + serializer.Serialize(values[2], "zValue"); + serializer.Serialize(values[3], "wValue"); value = AZ::Quaternion::CreateFromFloat4(values); return serializer.IsValid(); } diff --git a/Gems/Multiplayer/Code/Include/IMultiplayer.h b/Gems/Multiplayer/Code/Include/IMultiplayer.h index fd2b0e6cce..94744dbb54 100644 --- a/Gems/Multiplayer/Code/Include/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/IMultiplayer.h @@ -95,4 +95,20 @@ namespace Multiplayer private: MultiplayerStats m_stats; }; + + inline const char* GetEnumString(MultiplayerAgentType value) + { + switch (value) + { + case MultiplayerAgentType::Uninitialized: + return "Uninitialized"; + case MultiplayerAgentType::Client: + return "Client"; + case MultiplayerAgentType::ClientServer: + return "ClientServer"; + case MultiplayerAgentType::DedicatedServer: + return "DedicatedServer"; + } + return "INVALID"; + } } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 33509a61c7..f5774b07c0 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -33,22 +33,20 @@ const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const; #} {% macro DeclareNetworkPropertySetter(Property) %} {% set PropertyName = UpperFirst(Property.attrib['Name']) %} -{% if Property.attrib['IsPredictable'] | booleanTrue %} -{% if Property.attrib['Container'] == 'Array' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index); -{% elif Property.attrib['Container'] == 'Vector' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index); -bool {{ PropertyName }}PushBack(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -bool {{ PropertyName }}PopBack(const Multiplayer::NetworkInput&); -void {{ PropertyName }}Clear(const Multiplayer::NetworkInput&); -{% elif Property.attrib['Container'] == 'Object' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&); -{% else %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -{% endif %} +{% if Property.attrib['Container'] == 'Array' %} +void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index); +{% elif Property.attrib['Container'] == 'Vector' %} +void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index); +bool {{ PropertyName }}PushBack(const {{ Property.attrib['Type'] }}& value); +bool {{ PropertyName }}PopBack(); +void {{ PropertyName }}Clear(); +{% elif Property.attrib['Container'] == 'Object' %} +void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(); +{% else %} +void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value); {% endif %} {% endmacro %} {# @@ -417,6 +415,7 @@ namespace {{ Component.attrib['Namespace'] }} static const Multiplayer::NetComponentId s_componentId = static_cast({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }}); static void Reflect(AZ::ReflectContext* context); + static void ReflectToEditContext(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 5dc470fcd1..aee15bc190 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -73,18 +73,17 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even {# #} -{% macro DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %} -{% if Property.attrib['IsPredictable'] | booleanTrue %} -{% if Property.attrib['Container'] == 'Array' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value) +{% macro DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %} +{% if Property.attrib['Container'] == 'Array' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index) { int32_t bitIndex = index + static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}); GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true); @@ -92,16 +91,16 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index]; } -{% elif Property.attrib['Container'] == 'Vector' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value) +{% elif Property.attrib['Container'] == 'Vector' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index) { int32_t bitIndex = index + static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}); GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true); @@ -109,7 +108,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index]; } -bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }} &value) +bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value) { int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.GetSize(); GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.PushBack(value); @@ -134,24 +133,24 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear(const Multi GetParent().MarkDirty(); } -{% elif Property.attrib['Container'] == 'Object' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }}& value) +{% elif Property.attrib['Container'] == 'Object' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}() = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}() { GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), true); GetParent().MarkDirty(); return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}{% if Property.attrib['IsRewindable']|booleanTrue %}.Modify(){% endif %}; } -{% else %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value) +{% else %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value) { @@ -161,7 +160,6 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl } } -{% endif %} {% endif %} {% endmacro %} {# @@ -273,7 +271,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} {% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %} {{ DefineNetworkPropertyGet(ClassName, Property, "GetParent().") }} -{{ DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }} +{{ DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }} {% endif %} {% endcall %} {% endmacro %} @@ -478,6 +476,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re {%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%} {% endcall %} {% if networkPropertyCount.value > 0 %} + MultiplayerStats& stats = AZ::Interface::Get()->GetStats(); // We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server) [[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} @@ -509,7 +508,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ Property.attrib['Name'] }}", - GetNetComponentId() + GetNetComponentId(), + stats ); {% endif %} {% endcall %} @@ -1111,23 +1111,29 @@ namespace {{ Component.attrib['Namespace'] }} {{ DefineNetworkPropertyReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(16) -}} {{ DefineNetworkPropertyReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(16) -}} {{ DefineNetworkPropertyReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(16) }} - {{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }} - ; + {{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }}; + } + ReflectToEditContext(context); + } + void {{ ComponentBaseName }}::{{ ComponentBaseName }}::ReflectToEditContext(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { - editContext->Class<{{ ComponentBaseName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}") + editContext->Class<{{ ComponentName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) - {{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(20) }} - {{ DefineArchetypePropertyEditReflection(Component, ComponentBaseName)|indent(20) }} - ; + {{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentName)|indent(20) }} + {{ DefineArchetypePropertyEditReflection(Component, ComponentName)|indent(20) }}; } } } diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 0f96fd45e1..6ff27ebe6c 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -24,7 +24,6 @@ namespace Multiplayer serializeContext->Class() ->Version(1); } - LocalPredictionPlayerInputComponentBase::Reflect(context); } diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp index 8dc8c6d303..fcdad87416 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp @@ -43,8 +43,12 @@ namespace Multiplayer NetEntityId MultiplayerComponent::GetNetEntityId() const { - const NetBindComponent* netBindComponent = GetNetBindComponent(); - return netBindComponent ? netBindComponent->GetNetEntityId() : InvalidNetEntityId; + return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId; + } + + NetEntityRole MultiplayerComponent::GetNetEntityRole() const + { + return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole; } ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h index 46823f4c92..9efc13ed4b 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h @@ -62,6 +62,7 @@ namespace Multiplayer //! @} NetEntityId GetNetEntityId() const; + NetEntityRole GetNetEntityRole() const; ConstNetworkEntityHandle GetEntityHandle() const; NetworkEntityHandle GetEntityHandle(); void MarkDirty(); @@ -109,7 +110,8 @@ namespace Multiplayer int32_t bitIndex, TYPE& value, const char* name, - [[maybe_unused]] NetComponentId componentId + [[maybe_unused]] NetComponentId componentId, + MultiplayerStats& stats ) { if (bitset.GetBit(bitIndex)) @@ -119,6 +121,7 @@ namespace Multiplayer serializer.Serialize(value, name); if (modifyRecord && !serializer.GetTrackedChangesFlag()) { + // If the serializer didn't change any values, then lower the flag so we don't unnecessarily notify bitset.SetBit(bitIndex, false); } const uint32_t postUpdateSize = serializer.GetSize(); @@ -126,8 +129,7 @@ namespace Multiplayer const uint32_t updateSize = (postUpdateSize - prevUpdateSize); if (updateSize > 0) { - MultiplayerStats& stats = AZ::Interface::Get()->GetStats(); - if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) + if (modifyRecord) { stats.m_propertyUpdatesRecv++; stats.m_propertyUpdatesRecvBytes += updateSize; diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp index 97746c3f6c..737ecc10cc 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp @@ -27,6 +27,11 @@ namespace Multiplayer return m_owner.GetNetEntityId(); } + NetEntityRole MultiplayerController::GetNetEntityRole() const + { + return GetNetBindComponent()->GetNetEntityRole(); + } + AZ::Entity* MultiplayerController::GetEntity() const { return m_owner.GetEntity(); diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h index 3495893812..9e3c7d68ab 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h @@ -47,6 +47,10 @@ namespace Multiplayer //! @return the networkId for the entity that owns this controller NetEntityId GetNetEntityId() const; + //! Returns the networkRole for the entity that owns this controller. + //! @return the networkRole for the entity that owns this controller + NetEntityRole GetNetEntityRole() const; + //! Returns the raw AZ::Entity pointer for the entity that owns this controller. //! @return the raw AZ::Entity pointer for the entity that owns this controller AZ::Entity* GetEntity() const; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 2e6ae60558..607e2813ec 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include namespace Multiplayer { @@ -24,7 +26,81 @@ namespace Multiplayer serializeContext->Class() ->Version(1); } - NetworkTransformComponentBase::Reflect(context); } + + NetworkTransformComponent::NetworkTransformComponent() + : m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); }) + , m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) + , m_scaleEventHandler([this](const AZ::Vector3& scale) { OnScaleChangedEvent(scale); }) + { + ; + } + + void NetworkTransformComponent::OnInit() + { + ; + } + + void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + RotationAddEvent(m_rotationEventHandler); + TranslationAddEvent(m_translationEventHandler); + ScaleAddEvent(m_scaleEventHandler); + } + + void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetRotation(rotation); + GetTransformComponent()->SetWorldTM(worldTm); + } + + void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetTranslation(translation); + GetTransformComponent()->SetWorldTM(worldTm); + } + + void NetworkTransformComponent::OnScaleChangedEvent(const AZ::Vector3& scale) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetScale(scale); + GetTransformComponent()->SetWorldTM(worldTm); + } + + + NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) + : NetworkTransformComponentControllerBase(parent) + , m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); }) + { + ; + } + + void NetworkTransformComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); + OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM()); + } + + void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm) + { + if (GetNetEntityRole() == NetEntityRole::Authority) + { + SetRotation(worldTm.GetRotation()); + SetTranslation(worldTm.GetTranslation()); + SetScale(worldTm.GetScale()); + } + } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h index 4719f11a7a..2ae3ab4bb9 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h @@ -13,6 +13,7 @@ #pragma once #include +#include namespace Multiplayer { @@ -22,20 +23,37 @@ namespace Multiplayer public: AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase); - static void Reflect([[maybe_unused]] AZ::ReflectContext* context); + static void Reflect(AZ::ReflectContext* context); - void OnInit() override {} - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + NetworkTransformComponent(); + + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnRotationChangedEvent(const AZ::Quaternion& rotation); + void OnTranslationChangedEvent(const AZ::Vector3& translation); + void OnScaleChangedEvent(const AZ::Vector3& scale); + + AZ::Event::Handler m_rotationEventHandler; + AZ::Event::Handler m_translationEventHandler; + AZ::Event::Handler m_scaleEventHandler; }; class NetworkTransformComponentController : public NetworkTransformComponentControllerBase { public: - NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) {} + NetworkTransformComponentController(NetworkTransformComponent& parent); - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnTransformChangedEvent(const AZ::Transform& worldTm); + + AZ::TransformChangedEvent::Handler m_transformChangedHandler; + AZ::ScheduledEvent m_transformChangeEvent; }; } diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp new file mode 100644 index 0000000000..1388c1f5d2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp @@ -0,0 +1,59 @@ +/* +* 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 + +namespace Multiplayer +{ + static constexpr uint32_t Uint32Max = AZStd::numeric_limits::max(); + + // This can be used to help mitigate client side performance when large numbers of entities are created off the network + AZ_CVAR(uint32_t, cl_ClientMaxRemoteEntitiesPendingCreationCount, Uint32Max, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we have sent to the client, but have not had a confirmation back from the client"); + AZ_CVAR(AZ::TimeMs, cl_ClientEntityReplicatorPendingRemovalTimeMs, AZ::TimeMs{ 10000 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "How long should wait prior to removing an entity for the client through a change in the replication window, entity deletes are still immediate"); + + ClientToServerConnectionData::ClientToServerConnectionData + ( + AzNetworking::IConnection* connection, + AzNetworking::IConnectionListener& connectionListener + ) + : m_connection(connection) + , m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer) + { + m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount); + m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs); + } + + ClientToServerConnectionData::~ClientToServerConnectionData() + { + m_entityReplicationManager.Clear(false); + } + + ConnectionDataType ClientToServerConnectionData::GetConnectionDataType() const + { + return ConnectionDataType::ClientToServer; + } + + AzNetworking::IConnection* ClientToServerConnectionData::GetConnection() const + { + return m_connection; + } + + EntityReplicationManager& ClientToServerConnectionData::GetReplicationManager() + { + return m_entityReplicationManager; + } + + void ClientToServerConnectionData::Update([[maybe_unused]] AZ::TimeMs serverGameTimeMs) + { + m_entityReplicationManager.ActivatePendingEntities(); + } +} diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h new file mode 100644 index 0000000000..b63ffee9a3 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h @@ -0,0 +1,47 @@ +/* +* 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 +{ + class ClientToServerConnectionData final + : public IConnectionData + { + public: + ClientToServerConnectionData + ( + AzNetworking::IConnection* connection, + AzNetworking::IConnectionListener& connectionListener + ); + ~ClientToServerConnectionData() override; + + //! IConnectionData interface + //! @{ + ConnectionDataType GetConnectionDataType() const override; + AzNetworking::IConnection* GetConnection() const override; + EntityReplicationManager& GetReplicationManager() override; + void Update(AZ::TimeMs serverGameTimeMs) override; + //! @} + + bool CanSendUpdates(); + + private: + EntityReplicationManager m_entityReplicationManager; + AzNetworking::IConnection* m_connection = nullptr; + bool m_canSendUpdates = true; + }; +} + +#include diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl new file mode 100644 index 0000000000..1ee5711341 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl @@ -0,0 +1,19 @@ +/* +* 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. +* +*/ + +namespace Multiplayer +{ + inline bool ClientToServerConnectionData::CanSendUpdates() + { + return m_canSendUpdates; + } +} diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h index ba2541ec7b..ebff75fd9b 100644 --- a/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h +++ b/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h @@ -19,6 +19,7 @@ namespace Multiplayer { enum class ConnectionDataType { + ClientToServer, ServerToClient, ServerToServer }; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index a622814088..70323d7de3 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -66,6 +68,7 @@ namespace Multiplayer AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with"); AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking"); AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server"); + AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -126,24 +129,27 @@ namespace Multiplayer // Handle deferred local rpc messages that were generated during the updates m_networkEntityManager.DispatchLocalDeferredRpcMessages(); m_networkEntityManager.NotifyEntitiesChanged(); + // Let the network system know the frame is done and we can collect dirty bits m_networkEntityManager.NotifyEntitiesDirtied(); + // Send out the game state update to all connections + { + auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) + { + if (connection.GetUserData() != nullptr) + { + IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); + connectionData->Update(serverGameTimeMs); + } + }; + + m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); + } + MultiplayerStats& stats = GetStats(); stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); - auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) - { - if (connection.GetUserData() != nullptr) - { - IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); - connectionData->Update(serverGameTimeMs); - } - }; - - // Send out the game state update to all connections - m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); - MultiplayerPackets::SyncConsole packet; AZ::ThreadSafeDeque::DequeType cvarUpdates; m_cvarCommands.Swap(cvarUpdates); @@ -245,12 +251,8 @@ namespace Multiplayer AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); AZ::Interface::Get()->PerformCommand(commandString.c_str()); - // This is a bit tricky, so it warrants extra commenting - // The cry level loader has a 'map' command used to invoke the level load system - // We don't want any explicit cry dependencies, so instead we rely on the - // az console binding inside SystemInit to echo any unhandled commands to - // the cry console by stripping off the prefix 'sv_' - AZ::Interface::Get()->PerformCommand(commandString.c_str() + 3); + AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); return true; } @@ -410,6 +412,16 @@ namespace Multiplayer AZStd::unique_ptr window = AZStd::make_unique(controlledEntity, connection); reinterpret_cast(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window)); } + else + { + if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so + { + connection->SetUserData(new ClientToServerConnectionData(connection, *this)); + } + + AZStd::unique_ptr window = AZStd::make_unique(); + reinterpret_cast(connection->GetUserData())->GetReplicationManager().SetEntityActivationTimeSliceMs(cl_defaultNetworkEntityActivationTimeSliceMs); + } } bool MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer) @@ -463,6 +475,7 @@ namespace Multiplayer } } m_agentType = multiplayerType; + AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType)); } void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) @@ -535,14 +548,15 @@ namespace Multiplayer void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer; + AZ::Interface::Get()->InitializeMultiplayer(serverType); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); networkInterface->Listen(sv_port); - AZ::Interface::Get()->InitializeMultiplayer(serverType); } AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to"); void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { + AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); if (arguments.size() < 1) @@ -567,12 +581,12 @@ namespace Multiplayer int32_t portNumber = atol(portStr); const IpAddress ipAddress(addressStr, aznumeric_cast(portNumber), networkInterface->GetType()); networkInterface->Connect(ipAddress); - AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); } AZ_CONSOLEFREEFUNC(connect, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection to a remote host"); void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { + AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; networkInterface->GetConnectionSet().VisitConnections(visitor); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index f249124fb0..1e10f9841e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include namespace AzNetworking { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e58b7fde9d..8c076f759d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -126,9 +127,9 @@ namespace Multiplayer MultiplayerPackets::EntityUpdates entityUpdatePacket; entityUpdatePacket.SetHostTimeMs(serverGameTimeMs); // Serialize everything - for (auto it = toSendList.begin(); it != toSendList.end();) + while (!toSendList.empty()) { - EntityReplicator* replicator = *it; + EntityReplicator* replicator = toSendList.front(); NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket()); const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize(); @@ -144,15 +145,15 @@ namespace Multiplayer pendingPacketSize += nextMessageSize; entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage); - replicatorUpdatedList.push_back(*it); - it = toSendList.erase(it); + replicatorUpdatedList.push_back(replicator); + toSendList.pop_front(); if (largeEntityDetected) { AZLOG_WARN("\n\n*******************************"); AZLOG_WARN ( - "Serializing Extremely Large Entity (%u) - MaxPayload: %d NeededSize %d", + "Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d", aznumeric_cast(replicator->GetEntityHandle().GetNetEntityId()), maxPayloadSize, nextMessageSize @@ -173,16 +174,16 @@ namespace Multiplayer EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList() { + if (m_replicationWindow == nullptr) + { + return EntityReplicatorList(); + } + // Generate a list of all our entities that need updates - EntityReplicatorList autonomousReplicators; - autonomousReplicators.reserve(m_replicatorsPendingSend.size()); - EntityReplicatorList proxyReplicators; - proxyReplicators.reserve(m_replicatorsPendingSend.size()); + EntityReplicatorList toSendList; uint32_t elementsAdded = 0; - for (auto iter = m_replicatorsPendingSend.begin(); - iter != m_replicatorsPendingSend.end() - && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount();) + for (auto iter = m_replicatorsPendingSend.begin(); iter != m_replicatorsPendingSend.end() && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount(); ) { EntityReplicator* replicator = GetEntityReplicator(*iter); bool clearPendingSend = true; @@ -218,13 +219,13 @@ namespace Multiplayer if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous) { - autonomousReplicators.push_back(replicator); + toSendList.push_back(replicator); } else { if (elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount()) { - proxyReplicators.push_back(replicator); + toSendList.push_back(replicator); } } } @@ -243,9 +244,6 @@ namespace Multiplayer } } - EntityReplicatorList toSendList; - toSendList.swap(autonomousReplicators); - toSendList.insert(toSendList.end(), proxyReplicators.begin(), proxyReplicators.end()); return toSendList; } @@ -543,6 +541,7 @@ namespace Multiplayer // Create an entity if we don't have one if (createEntity) { + // @pereslav //replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity()); AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString()); if (replicatorEntity == nullptr) @@ -765,7 +764,7 @@ namespace Multiplayer return HandleEntityDeleteMessage(entityReplicator, packetHeader, updateMessage); } - AzNetworking::NetworkOutputSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize()); + AzNetworking::TrackChangedSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize()); PrefabEntityId prefabEntityId; if (updateMessage.GetHasValidPrefabId()) @@ -1125,7 +1124,7 @@ namespace Multiplayer { if (message.GetPropertyUpdateData().GetSize() > 0) { - AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize()); + AzNetworking::TrackChangedSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize()); if (!HandlePropertyChangeMessage ( replicator, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 1385a33208..a6470e6c34 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ namespace Multiplayer using RpcMessages = AZStd::list; bool DispatchOrphanedRpc(NetworkEntityRpcMessage& message, EntityReplicator* entityReplicator); - using EntityReplicatorList = AZStd::vector; + using EntityReplicatorList = AZStd::deque; EntityReplicatorList GenerateEntityUpdateList(); void SendEntityUpdatesPacketHelper(AZ::TimeMs serverGameTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index b0d0328ba8..0edb5db250 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -283,7 +283,7 @@ namespace Multiplayer AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent"); bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority) - && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); + && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client; bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous; if (isAuthority || isClient || isAutonomous) @@ -311,9 +311,9 @@ namespace Multiplayer { bool ret(false); bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server) - && (GetRemoteNetworkRole() == NetEntityRole::Authority); + && (GetRemoteNetworkRole() == NetEntityRole::Authority); bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client) - || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); + || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); if (isServer || isClient) { ret = true; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 46d1617760..23be4fb4fb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,12 @@ namespace Multiplayer , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) { AZ::Interface::Register(this); + if (AZ::Interface::Get() != nullptr) + { + // Null guard needed for unit tests + AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); + AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); + } } NetworkEntityManager::~NetworkEntityManager() @@ -43,13 +50,6 @@ namespace Multiplayer void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr entityDomain) { - if (AZ::Interface::Get() != nullptr) - { - // Null guard needed for unit tests - AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); - AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); - } - m_hostId = hostId; m_entityDomain = AZStd::move(entityDomain); m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); @@ -282,8 +282,13 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { + // @pereslav + // Note that this is a total hack.. we should not be listening to this event on a client + // Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage() + const bool isClient = AZ::Interface::Get()->GetAgentType() == MultiplayerAgentType::Client; + const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority; const NetEntityId netEntityId = m_nextEntityId++; - netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); + netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole); } } diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl index d5936e6718..69752210bb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl @@ -73,7 +73,7 @@ namespace Multiplayer template inline BASE_TYPE& RewindableObject::Modify() { - ApplicationFrameId frameTime = GetCurrentTimeForProperty(); + const ApplicationFrameId frameTime = GetCurrentTimeForProperty(); if (frameTime < m_headTime) { AZ_Assert(false, "Trying to mutate a rewindable in the past"); @@ -82,7 +82,7 @@ namespace Multiplayer { SetValueForTime(GetValueForTime(frameTime), frameTime); } - const BASE_TYPE& returnValue = GetValueForTime(GetCurrentTimeForProperty()); + const BASE_TYPE& returnValue = GetValueForTime(frameTime); return const_cast(returnValue); } @@ -103,10 +103,11 @@ namespace Multiplayer template inline bool RewindableObject::Serialize(AzNetworking::ISerializer& serializer) { - BASE_TYPE current = GetValueForTime(GetCurrentTimeForProperty()); - if (serializer.Serialize(current, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)) + const ApplicationFrameId frameTime = GetCurrentTimeForProperty(); + BASE_TYPE value = GetValueForTime(frameTime); + if (serializer.Serialize(value, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)) { - SetValueForTime(current, GetCurrentTimeForProperty()); + SetValueForTime(value, frameTime); } return serializer.IsValid(); } diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp new file mode 100644 index 0000000000..698376dccf --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp @@ -0,0 +1,47 @@ +/* +* 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 "NullReplicationWindow.h" + +namespace Multiplayer +{ + bool NullReplicationWindow::ReplicationSetUpdateReady() + { + return true; + } + + const ReplicationSet& NullReplicationWindow::GetReplicationSet() const + { + return m_emptySet; + } + + uint32_t NullReplicationWindow::GetMaxEntityReplicatorSendCount() const + { + return 0; + } + + bool NullReplicationWindow::IsInWindow([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, NetEntityRole& outNetworkRole) const + { + outNetworkRole = NetEntityRole::InvalidRole; + return false; + } + + void NullReplicationWindow::UpdateWindow() + { + ; + } + + void NullReplicationWindow::DebugDraw() const + { + // Nothing to draw + } +} diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h new file mode 100644 index 0000000000..76562a34e2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h @@ -0,0 +1,38 @@ +/* +* 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 +{ + class NullReplicationWindow + : public IReplicationWindow + { + public: + NullReplicationWindow() = default; + + //! IReplicationWindow interface + //! @{ + bool ReplicationSetUpdateReady() override; + const ReplicationSet& GetReplicationSet() const override; + uint32_t GetMaxEntityReplicatorSendCount() const override; + bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override; + void UpdateWindow() override; + void DebugDraw() const override; + //! @} + + private: + ReplicationSet m_emptySet; + }; +} diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp index cfb1286496..d0726f1341 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp @@ -202,8 +202,7 @@ namespace Multiplayer void ServerToClientReplicationWindow::OnEntityActivated(const AZ::EntityId& entityId) { - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId); + AZ::Entity* entity = AZ::Interface::Get()->FindEntity(entityId); ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker()); NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent(); @@ -234,8 +233,7 @@ namespace Multiplayer void ServerToClientReplicationWindow::OnEntityDeactivated(const AZ::EntityId& entityId) { - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId); + AZ::Entity* entity = AZ::Interface::Get()->FindEntity(entityId); ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker()); NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent(); diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index eea9379df9..275625b8b4 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -34,6 +34,9 @@ set(FILES Source/Components/NetBindComponent.h Source/Components/NetworkTransformComponent.cpp Source/Components/NetworkTransformComponent.h + Source/ConnectionData/ClientToServerConnectionData.cpp + Source/ConnectionData/ClientToServerConnectionData.h + Source/ConnectionData/ClientToServerConnectionData.inl Source/ConnectionData/IConnectionData.h Source/ConnectionData/ServerToClientConnectionData.cpp Source/ConnectionData/ServerToClientConnectionData.h @@ -81,6 +84,8 @@ set(FILES Source/NetworkTime/NetworkTime.h Source/NetworkTime/RewindableObject.h Source/NetworkTime/RewindableObject.inl + Source/ReplicationWindows/NullReplicationWindow.cpp + Source/ReplicationWindows/NullReplicationWindow.h Source/ReplicationWindows/IReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp Source/ReplicationWindows/ServerToClientReplicationWindow.h From 7b6ecc036b406561bac3ce117166c8e51afeb55c Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 13 Apr 2021 21:16:04 -0700 Subject: [PATCH 030/122] Minor updates --- Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h | 2 +- .../Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp | 2 ++ Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h index f5ec9feebb..d12d30284e 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/BufferDescriptor.h @@ -33,7 +33,7 @@ namespace AZ /// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are not updated often InputAssembly = AZ_BIT(0), - /// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are updated perf frame + /// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are updated frequently DynamicInputAssembly = AZ_BIT(1), /// Supports constant access through a ShaderResourceGroup. diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index 866c355dad..841c71126a 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -835,6 +835,8 @@ namespace AZ size_t prevEndOfLine = argBufferStr.rfind("\n", resourceStartPos); size_t nextEndOfLine = argBufferStr.find("\n", resourceStartPos); size_t startOfEntryPos = argBufferStr.find(resourceStr, prevEndOfLine); + + //Check to see if a valid entry is found. if(startOfEntryPos == AZStd::string::npos || startOfEntryPos > nextEndOfLine) { AZ_Error(MetalShaderPlatformName, startOfEntryPos != AZStd::string::npos, "Entry-> %s not found within Descriptor set %s", resourceStr, argBufferStr.c_str()); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index d6b2b2c906..f95e871d33 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -211,6 +211,7 @@ namespace AZ return GetCPUGPUMemoryMode(); } + //This flag is used for IA buffers that is updated frequently and hence shared mmory is the best fit if (RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::DynamicInputAssembly)) { return MTLStorageModeShared; From 2655aaa633e8f132e4a3a66db7f6b3acbd5b50c3 Mon Sep 17 00:00:00 2001 From: hultonha Date: Wed, 14 Apr 2021 11:30:40 +0100 Subject: [PATCH 031/122] update ByteStreamSerializer to use Base64 encoding --- .../Json/ByteStreamSerializer.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 2da71ba68a..09adaf38cb 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace AZ { @@ -31,11 +32,13 @@ namespace AZ { case rapidjson::kStringType: { JsonByteStream* valAsByteStream = static_cast(outputValue); - JsonByteStream buffer; - buffer.resize(inputValue.GetStringLength()); - AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); - *valAsByteStream = AZStd::move(buffer); - return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + JsonByteStream buffer(inputValue.GetStringLength()); + if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength())) + { + *valAsByteStream = AZStd::move(buffer); + return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + } + return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed."); } case rapidjson::kArrayType: case rapidjson::kObjectType: @@ -58,12 +61,10 @@ namespace AZ using JsonSerializationResult::Tasks; const JsonByteStream& valAsByteStream = *static_cast(inputValue); - if (context.ShouldKeepDefaults() || !defaultValue || - (valAsByteStream != *static_cast(defaultValue))) + if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast(defaultValue))) { - outputValue.SetString( - reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), - context.GetJsonAllocator()); + const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size()); + outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator()); return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored."); } From e1e746066da9e064500815e3a06fd26b88b60d4a Mon Sep 17 00:00:00 2001 From: hultonha Date: Wed, 14 Apr 2021 12:04:23 +0100 Subject: [PATCH 032/122] add some preliminary tests for ByteStreamSerializer --- .../Json/ByteStreamSerializerTests.cpp | 59 +++++++++++++++++++ .../AzCore/Tests/azcoretests_files.cmake | 1 + 2 files changed, 60 insertions(+) create mode 100644 Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp new file mode 100644 index 0000000000..110466d1a0 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp @@ -0,0 +1,59 @@ +/* + * 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 + +namespace JsonSerializationTests +{ + class ByteStreamSerializerTestDescription : public JsonSerializerConformityTestDescriptor + { + public: + AZStd::shared_ptr CreateSerializer() override + { + return AZStd::make_shared(); + } + + AZStd::shared_ptr CreateDefaultInstance() override + { + return AZStd::make_shared(); + } + + AZStd::shared_ptr CreateFullySetInstance() override + { + // create a JsonByteStream (AZStd::vector) with ten 'a's + return AZStd::make_shared(10, 'a'); + } + + AZStd::string_view GetJsonForFullySetInstance() override + { + // Base64 encoded version of 'aaaaaaaaaa' (see CreateFullySetInstance) + return R"("YWFhYWFhYWFhYQ==")"; + } + + void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override + { + features.EnableJsonType(rapidjson::kStringType); + features.m_supportsPartialInitialization = false; + features.m_supportsInjection = false; + } + + bool AreEqual(const AZ::JsonByteStream& lhs, const AZ::JsonByteStream& rhs) override + { + return lhs == rhs; + } + }; + + using ByteStreamConformityTestTypes = ::testing::Types; + INSTANTIATE_TYPED_TEST_CASE_P(JsonByteStreamSerialzier, JsonSerializerConformityTests, ByteStreamConformityTestTypes); +} // namespace JsonSerializationTests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index c51cf46a37..2129761bfe 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -98,6 +98,7 @@ set(FILES Serialization/Json/BaseJsonSerializerTests.cpp Serialization/Json/BasicContainerSerializerTests.cpp Serialization/Json/BoolSerializerTests.cpp + Serialization/Json/ByteStreamSerializerTests.cpp Serialization/Json/ColorSerializerTests.cpp Serialization/Json/DoubleSerializerTests.cpp Serialization/Json/IntSerializerTests.cpp From 59252235d5eae7e5ad0eb9d3403e9b737089e2db Mon Sep 17 00:00:00 2001 From: pereslav Date: Wed, 14 Apr 2021 13:13:01 +0100 Subject: [PATCH 033/122] Fixed dangling pointer in InitializeCatalog --- Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.cpp b/Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.cpp index 7cb0090ef5..e01b105d13 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.cpp @@ -617,9 +617,9 @@ namespace AzFramework // won't free the mutex until the load is complete. // So instead, queue the notification until the next tick, so that it doesn't occur within the AssetCatalogRequestBus mutex, and also // so that the entire AssetCatalog initialization is complete. - AZ::TickBus::QueueFunction([catalogRegistryFile]() + AZ::TickBus::QueueFunction([catalogRegistryString = AZStd::string(catalogRegistryFile)]() { - AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryFile); + AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryString.c_str()); }); } } From 6f67aabd67278ce906ec211e93ec2b763511d142 Mon Sep 17 00:00:00 2001 From: moudgils Date: Wed, 14 Apr 2021 09:42:13 -0700 Subject: [PATCH 034/122] Minor cleanup --- Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp | 3 +-- Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp index 8247ceb41a..9eb5638186 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp @@ -39,8 +39,7 @@ namespace AZ { m_device = &device; - if (RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::InputAssembly) || - RHI::CheckBitsAll(descriptor.m_bindFlags, RHI::BufferBindFlags::DynamicInputAssembly)) + if(RHI::CheckBitsAny(descriptor.m_bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { m_readOnlyState |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER | D3D12_RESOURCE_STATE_INDEX_BUFFER; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp index cb2ad7d2ed..81fd9e751b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp @@ -74,9 +74,9 @@ namespace AZ const RHI::BufferView* Buffer::GetBufferView() const { - if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly || - m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::DynamicInputAssembly) + if(RHI::CheckBitsAny(m_rhiBuffer->GetDescriptor().m_bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { + AZ_Assert(false, "Input assembly buffer doesn't need a regular buffer view, it requires a stream or index buffer view."); return nullptr; } @@ -204,12 +204,11 @@ namespace AZ void Buffer::InitBufferView() { // Skip buffer view creation for input assembly buffers - if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly || - m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::DynamicInputAssembly) + if(RHI::CheckBitsAny(m_rhiBuffer->GetDescriptor().m_bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) { return; } - + m_bufferView = m_rhiBuffer->GetBufferView(m_bufferViewDescriptor); if(!m_bufferView.get()) From 70c2d5ee4082f51415094e8971645535312814ac Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 10:24:23 -0700 Subject: [PATCH 035/122] SPEC-5789 Remove inclusion of CMakeParseArguments --- cmake/3rdParty.cmake | 2 -- cmake/LYWrappers.cmake | 1 - 2 files changed, 3 deletions(-) diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index b6731ae239..d1b1fe7cc6 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -21,8 +21,6 @@ if(NOT EXISTS ${LY_3RDPARTY_PATH}/3rdParty.txt) message(FATAL_ERROR "3rdParty.txt not found in ${LY_3RDPARTY_PATH}, call cmake defining a valid LY_3RDPARTY_PATH or use cmake-gui to configure it") endif() -include(CMakeParseArguments) - #! ly_add_external_target_path: adds a path to module path so 3rdparty Find files can be added from paths different than cmake/3rdParty # # \arg:PATH path to add diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 25465ce69c..bd904adaa3 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -12,7 +12,6 @@ set(LY_UNITY_BUILD OFF CACHE BOOL "UNITY builds") include(CMakeFindDependencyMacro) -include(CMakeParseArguments) include(cmake/LyAutoGen.cmake) ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) From bbec18d0300d817f0fa2cf5b63732a218b29d4c1 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 14 Apr 2021 10:45:22 -0700 Subject: [PATCH 036/122] Fix initial camera position when working directly with Atom --- Gems/Camera/Code/Source/CameraComponentController.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index e66de5b95b..2799d897d6 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -98,15 +98,16 @@ namespace Camera AZ_Assert(m_atomCamera, "Attempted to activate Atom camera before component activation"); const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); - atomViewportRequests->PushView(contextName, m_atomCamera); - AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(contextName); - // Ensure the Atom camera is updated with our current transform state AZ::Transform localTransform; AZ::TransformBus::EventResult(localTransform, m_entityId, &AZ::TransformBus::Events::GetLocalTM); AZ::Transform worldTransform; AZ::TransformBus::EventResult(worldTransform, m_entityId, &AZ::TransformBus::Events::GetWorldTM); OnTransformChanged(localTransform, worldTransform); + + // Push the Atom camera after we make sure we're up-to-date with our component's transform to ensure the viewport reads the correct state + atomViewportRequests->PushView(contextName, m_atomCamera); + AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(contextName); UpdateCamera(); } } From 97d0f4267118e869a05a27b3fa7ab1102496a2f3 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 14 Apr 2021 10:45:54 -0700 Subject: [PATCH 037/122] Enable EditorViewportWidget by default --- Code/Sandbox/Editor/ViewManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Sandbox/Editor/ViewManager.cpp b/Code/Sandbox/Editor/ViewManager.cpp index b08c40cf2d..268bc19963 100644 --- a/Code/Sandbox/Editor/ViewManager.cpp +++ b/Code/Sandbox/Editor/ViewManager.cpp @@ -37,7 +37,7 @@ #include #include -AZ_CVAR(bool, ed_useAtomNativeViewport, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Atom-native Editor viewport (experimental, not yet stable"); +AZ_CVAR(bool, ed_useAtomNativeViewport, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Atom-native Editor viewport (experimental, not yet stable"); bool CViewManager::IsMultiViewportEnabled() { From 90ad9f5141b84dec8485cf485c93504623ee96e4 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:14:38 -0700 Subject: [PATCH 038/122] SPEC-6266 Release Mode time sampling with AZ_TRACE_METHOD --- Code/Framework/AzCore/AzCore/Debug/EventTrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Debug/EventTrace.h b/Code/Framework/AzCore/AzCore/Debug/EventTrace.h index 56a5c3b9a8..c2228c9150 100644 --- a/Code/Framework/AzCore/AzCore/Debug/EventTrace.h +++ b/Code/Framework/AzCore/AzCore/Debug/EventTrace.h @@ -42,9 +42,8 @@ namespace AZ } } -#define AZ_TRACE_METHOD_NAME_CATEGORY(name, category) AZ::Debug::EventTrace::ScopedSlice AZ_JOIN(ScopedSlice__, __LINE__)(name, category); - #ifdef AZ_PROFILE_TELEMETRY +# define AZ_TRACE_METHOD_NAME_CATEGORY(name, category) AZ::Debug::EventTrace::ScopedSlice AZ_JOIN(ScopedSlice__, __LINE__)(name, category); # define AZ_TRACE_METHOD_NAME(name) \ AZ_TRACE_METHOD_NAME_CATEGORY(name, "") \ AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzTrace, name) @@ -53,6 +52,7 @@ namespace AZ AZ_TRACE_METHOD_NAME_CATEGORY(AZ_FUNCTION_SIGNATURE, "") \ AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzTrace) #else +# define AZ_TRACE_METHOD_NAME_CATEGORY(name, category) # define AZ_TRACE_METHOD_NAME(name) AZ_TRACE_METHOD_NAME_CATEGORY(name, "") # define AZ_TRACE_METHOD() AZ_TRACE_METHOD_NAME(AZ_FUNCTION_SIGNATURE) #endif From 28ccb5d381ae24cbba011047f507b0f8d12cf4ae Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 14 Apr 2021 12:17:45 -0700 Subject: [PATCH 039/122] Fixing camera panning and zooming --- ...MaterialEditorViewportInputControllerBus.h | 3 +++ .../Viewport/InputController/Behavior.cpp | 24 +++++++++++++++++++ .../MaterialEditorViewportInputController.cpp | 13 ++++++++++ .../MaterialEditorViewportInputController.h | 3 +++ .../InputController/PanCameraBehavior.cpp | 4 +--- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h index 04250c4efd..2acdc79286 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h @@ -53,6 +53,9 @@ namespace MaterialEditor //! Modify camera's field of view //! @param value field of view in degrees virtual void SetFieldOfView(float value) = 0; + + //! Check if camera is looking directly at a model + virtual bool IsCameraCentered() const = 0; }; using MaterialEditorViewportInputControllerRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp index 8355b390ef..159d3339be 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp @@ -76,11 +76,35 @@ namespace MaterialEditor void Behavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z) { m_distanceToTarget = m_distanceToTarget - z; + + bool isCameraCentered = false; + MaterialEditorViewportInputControllerRequestBus::BroadcastResult( + isCameraCentered, + &MaterialEditorViewportInputControllerRequestBus::Handler::IsCameraCentered); + + // if camera is looking at the model (locked to the model) we don't want to zoom past the model's center + if (isCameraCentered) + { + m_distanceToTarget = AZ::GetMax(m_distanceToTarget, 0.0f); + } + AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget)); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position); + + // if camera is not locked to the model, move its focal point so we can free look + if (!isCameraCentered) + { + m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z)); + MaterialEditorViewportInputControllerRequestBus::Broadcast( + &MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition, + m_targetPosition); + MaterialEditorViewportInputControllerRequestBus::BroadcastResult( + m_distanceToTarget, + &MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget); + } } float Behavior::GetSensitivityX() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp index e180a5d979..83ec5a41c5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp @@ -96,6 +96,7 @@ namespace MaterialEditor void MaterialEditorViewportInputController::SetTargetPosition(const AZ::Vector3& targetPosition) { m_targetPosition = targetPosition; + m_isCameraCentered = false; } float MaterialEditorViewportInputController::GetDistanceToTarget() const @@ -246,6 +247,7 @@ namespace MaterialEditor cameraPosition = cameraRotation.TransformVector(cameraPosition); AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, cameraTransform); + m_isCameraCentered = true; // reset model AZ::Transform modelTransform = AZ::Transform::CreateIdentity(); @@ -258,6 +260,12 @@ namespace MaterialEditor AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); + + if (m_behavior) + { + m_behavior->End(); + m_behavior->Start(); + } } void MaterialEditorViewportInputController::SetFieldOfView(float value) @@ -265,6 +273,11 @@ namespace MaterialEditor Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value); } + bool MaterialEditorViewportInputController::IsCameraCentered() const + { + return m_isCameraCentered; + } + void MaterialEditorViewportInputController::CalculateExtents() { AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h index aa3dd836d6..ee40b5c259 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h @@ -45,6 +45,7 @@ namespace MaterialEditor void GetExtents(float& distanceMin, float& distanceMax) const override; void Reset() override; void SetFieldOfView(float value) override; + bool IsCameraCentered() const override; // AzFramework::ViewportControllerInstance interface overrides... bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; @@ -95,6 +96,8 @@ namespace MaterialEditor float m_distanceMin = 1.0f; //! Maximum distance from camera to target float m_distanceMax = 10.0f; + //! True if camera is centered on a model + bool m_isCameraCentered = true; static constexpr float MaxDistanceMultiplier = 2.5f; static constexpr float StartingDistanceMultiplier = 2.0f; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp index 087591e6ea..e36a335129 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp @@ -34,10 +34,8 @@ namespace MaterialEditor targetPosition); } - void PanCameraBehavior::TickInternal(float x, float y, float z) + void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z) { - Behavior::TickInternal(x, y, z); - AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::Quaternion rotation = transform.GetRotation(); From 042241a1193d68f964c6e3559a5c1289e574d592 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:26:20 -0700 Subject: [PATCH 040/122] SPEC-6268 Remove check for 3rdParty.txt --- cmake/3rdParty.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index d1b1fe7cc6..4cd3ab2917 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -17,8 +17,8 @@ set(LY_3RDPARTY_PATH "" CACHE PATH "Path to the 3rdParty folder") if(LY_3RDPARTY_PATH) file(TO_CMAKE_PATH ${LY_3RDPARTY_PATH} LY_3RDPARTY_PATH) endif() -if(NOT EXISTS ${LY_3RDPARTY_PATH}/3rdParty.txt) - message(FATAL_ERROR "3rdParty.txt not found in ${LY_3RDPARTY_PATH}, call cmake defining a valid LY_3RDPARTY_PATH or use cmake-gui to configure it") +if(NOT EXISTS ${LY_3RDPARTY_PATH}) + message(FATAL_ERROR "3rdParty folder: ${LY_3RDPARTY_PATH} does not exist, call cmake defining a valid LY_3RDPARTY_PATH or use cmake-gui to configure it") endif() #! ly_add_external_target_path: adds a path to module path so 3rdparty Find files can be added from paths different than cmake/3rdParty From 12088d88a05678de2a21a8d0fc5303dd8632ba7d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:27:14 -0700 Subject: [PATCH 041/122] SPEC-6275 Remove AutomatedReview folder --- AutomatedReview/Jenkinsfile | 709 -------------------------------- AutomatedReview/lumberyard.json | 12 - 2 files changed, 721 deletions(-) delete mode 100644 AutomatedReview/Jenkinsfile delete mode 100644 AutomatedReview/lumberyard.json diff --git a/AutomatedReview/Jenkinsfile b/AutomatedReview/Jenkinsfile deleted file mode 100644 index 8cf7a62726..0000000000 --- a/AutomatedReview/Jenkinsfile +++ /dev/null @@ -1,709 +0,0 @@ -#!/usr/bin/env groovy -/* -* 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. -* -*/ - -PIPELINE_CONFIG_FILE = 'AutomatedReview/lumberyard.json' -INCREMENTAL_BUILD_SCRIPT_PATH = 'scripts/build/bootstrap/incremental_build_util.py' - -EMPTY_JSON = readJSON text: '{}' - -ENGINE_REPOSITORY_NAME = 'o3de' - -def pipelineProperties = [] - -def pipelineParameters = [ - // Build/clean Parameters - // The CLEAN_OUTPUT_DIRECTORY is used by ci_build scripts. Creating the parameter here passes it as an environment variable to jobs and is consumed that way - booleanParam(defaultValue: false, description: 'Deletes the contents of the output directory before building. This will cause a \"clean\" build. NOTE: does not imply CLEAN_ASSETS', name: 'CLEAN_OUTPUT_DIRECTORY'), - booleanParam(defaultValue: false, description: 'Deletes the contents of the output directories of the AssetProcessor before building.', name: 'CLEAN_ASSETS'), - booleanParam(defaultValue: false, description: 'Deletes the contents of the workspace and forces a complete pull.', name: 'CLEAN_WORKSPACE'), - booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME'), - string(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE'), - - // Pull Request Parameters - string(defaultValue: '', description: '', name: 'DESTINATION_BRANCH'), - string(defaultValue: '', description: '', name: 'DESTINATION_COMMIT'), - string(defaultValue: '', description: '', name: 'PULL_REQUEST_ID'), - string(defaultValue: '', description: '', name: 'REPOSITORY_NAME'), - string(defaultValue: '', description: '', name: 'SOURCE_BRANCH'), - string(defaultValue: '', description: '', name: 'SOURCE_COMMIT') -] - -def palSh(cmd, lbl = '', winSlashReplacement = true) { - if (env.IS_UNIX) { - sh label: lbl, - script: cmd - } else if (winSlashReplacement) { - bat label: lbl, - script: cmd.replace('/','\\') - } else { - bat label: lbl, - script: cmd - } -} - -def palMkdir(path) { - if (env.IS_UNIX) { - sh label: "Making directories ${path}", - script: "mkdir -p ${path}" - } else { - def win_path = path.replace('/','\\') - bat label: "Making directories ${win_path}", - script: "mkdir ${win_path}." - } -} - -def palRm(path) { - if (env.IS_UNIX) { - sh label: "Removing ${path}", - script: "rm ${path}" - } else { - def win_path = path.replace('/','\\') - bat label: "Removing ${win_path}", - script: "del ${win_path}" - } -} - -def palRmDir(path) { - if (env.IS_UNIX) { - sh label: "Removing ${path}", - script: "rm -rf ${path}" - } else { - def win_path = path.replace('/','\\') - bat label: "Removing ${win_path}", - script: "rd /s /q ${win_path}" - } -} - -def IsJobEnabled(buildTypeMap, pipelineName, platformName) { - def job_list_override = params.JOB_LIST_OVERRIDE.tokenize(',') - if(params.PULL_REQUEST_ID) { // dont allow pull requests to filter platforms/jobs - if(buildTypeMap.value.TAGS) { - return buildTypeMap.value.TAGS.contains(pipelineName) - } - } else if (!job_list_override.isEmpty()) { - return params[platformName] && job_list_override.contains(buildTypeMap.key); - } else { - if (params[platformName]) { - if(buildTypeMap.value.TAGS) { - return buildTypeMap.value.TAGS.contains(pipelineName) - } - } - } - return false -} - -def GetRunningPipelineName(JENKINS_JOB_NAME) { - // If the job name has an underscore - def job_parts = JENKINS_JOB_NAME.tokenize('/')[0].tokenize('_') - if (job_parts.size() > 1) { - return [job_parts.take(job_parts.size() - 1).join('_'), job_parts[job_parts.size()-1]] - } - return [job_parts[0], 'default'] -} - -@NonCPS -def RegexMatcher(str, regex) { - def matcher = (str =~ regex) - return matcher ? matcher.group(1) : null -} - -def LoadPipelineConfig(String pipelineName, String branchName, String scmType) { - echo 'Loading pipeline config' - if (scmType == 'codecommit') { - PullFilesFromGit(PIPELINE_CONFIG_FILE, branchName, true, ENGINE_REPOSITORY_NAME) - } - def pipelineConfig = {} - pipelineConfig = readJSON file: PIPELINE_CONFIG_FILE - palRm(PIPELINE_CONFIG_FILE) - pipelineConfig.platforms = EMPTY_JSON - - // Load the pipeline configs per platform - pipelineConfig.PIPELINE_CONFIGS.each { pipeline_config -> - def platform_regex = pipeline_config.replace('.','\\.').replace('*', '(.*)') - if (!env.IS_UNIX) { - platform_regex = platform_regex.replace('/','\\\\') - } - echo "Downloading platform pipeline configs ${pipeline_config}" - if (scmType == 'codecommit') { - PullFilesFromGit(pipeline_config, branchName, false, ENGINE_REPOSITORY_NAME) - } - echo "Searching platform pipeline configs in ${pipeline_config} using ${platform_regex}" - for (pipeline_config_path in findFiles(glob: pipeline_config)) { - echo "\tFound platform pipeline config ${pipeline_config_path}" - def platform = RegexMatcher(pipeline_config_path, platform_regex) - if(platform) { - pipelineConfig.platforms[platform] = EMPTY_JSON - pipelineConfig.platforms[platform].PIPELINE_ENV = readJSON file: pipeline_config_path.toString() - } - palRm(pipeline_config_path.toString()) - } - } - - // Load the build configs - pipelineConfig.BUILD_CONFIGS.each { build_config -> - def platform_regex = build_config.replace('.','\\.').replace('*', '(.*)') - if (!env.IS_UNIX) { - platform_regex = platform_regex.replace('/','\\\\') - } - echo "Downloading configs ${build_config}" - if (scmType == 'codecommit') { - PullFilesFromGit(build_config, branchName, false, ENGINE_REPOSITORY_NAME) - } - echo "Searching configs in ${build_config} using ${platform_regex}" - for (build_config_path in findFiles(glob: build_config)) { - echo "\tFound config ${build_config_path}" - def platform = RegexMatcher(build_config_path, platform_regex) - if(platform) { - pipelineConfig.platforms[platform].build_types = readJSON file: build_config_path.toString() - } - } - } - return pipelineConfig -} - -def GetSCMType() { - def gitUrl = scm.getUserRemoteConfigs()[0].getUrl() - if (gitUrl ==~ /https:\/\/git-codecommit.*/) { - return 'codecommit' - } else if (gitUrl ==~ /https:\/\/github.com.*/) { - return 'github' - } - return 'unknown' -} - -def GetBuildEnvVars(Map platformEnv, Map buildTypeEnv, String pipelineName) { - def envVarMap = [:] - platformPipelineEnv = platformEnv['ENV'] ?: [:] - platformPipelineEnv.each { var -> - envVarMap[var.key] = var.value - } - platformEnvOverride = platformEnv['PIPELINE_ENV_OVERRIDE'] ?: [:] - platformPipelineEnvOverride = platformEnvOverride[pipelineName] ?: [:] - platformPipelineEnvOverride.each { var -> - envVarMap[var.key] = var.value - } - buildTypeEnv.each { var -> - // This may override the above one if there is an entry defined by the job - envVarMap[var.key] = var.value - } - - // Environment that only applies to to Jenkins tweaks. - // For 3rdParty downloads, we store them in the EBS volume so we can reuse them across node - // instances. This allow us to scale up and down without having to re-download 3rdParty - envVarMap['LY_PACKAGE_DOWNLOAD_CACHE_LOCATION'] = "${envVarMap['WORKSPACE']}/3rdParty/downloaded_packages" - envVarMap['LY_PACKAGE_UNPACK_LOCATION'] = "${envVarMap['WORKSPACE']}/3rdParty/packages" - - return envVarMap -} - -def GetEnvStringList(Map envVarMap) { - def strList = [] - envVarMap.each { var -> - strList.add("${var.key}=${var.value}") - } - return strList -} - -// Pulls/downloads files from the repo through codecommit. Despite Glob matching is NOT supported, '*' is supported -// as a folder or filename (not a portion, it has to be the whole folder or filename) -def PullFilesFromGit(String filenamePath, String branchName, boolean failIfNotFound = true, String repositoryName = env.DEFAULT_REPOSITORY_NAME) { - echo "PullFilesFromGit filenamePath=${filenamePath} branchName=${branchName} repositoryName=${repositoryName}" - def folderPathParts = filenamePath.tokenize('/') - def filename = folderPathParts[folderPathParts.size()-1] - folderPathParts.remove(folderPathParts.size()-1) // remove the filename - def folderPath = folderPathParts.join('/') - if (folderPath.contains('*')) { - - def currentPath = '' - for (int i = 0; i < folderPathParts.size(); i++) { - if (folderPathParts[i] == '*') { - palMkdir(currentPath) - retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${currentPath} > ${currentPath}/.codecommit", "GetFolder ${currentPath}") } - def folderInfo = readJSON file: "${currentPath}/.codecommit" - folderInfo.subFolders.each { folder -> - def newSubPath = currentPath + '/' + folder.relativePath - for (int j = i+1; j < folderPathParts.size(); j++) { - newSubPath = newSubPath + '/' + folderPathParts[j] - } - newSubPath = newSubPath + '/' + filename - PullFilesFromGit(newSubPath, branchName, false, repositoryName) - } - palRm("${currentPath}/.codecommit") - } - if (i == 0) { - currentPath = folderPathParts[i] - } else { - currentPath = currentPath + '/' + folderPathParts[i] - } - } - - } else if (filename.contains('*')) { - - palMkdir(folderPath) - retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${folderPath} > ${folderPath}/.codecommit", "GetFolder ${folderPath}") } - def folderInfo = readJSON file: "${folderPath}/.codecommit" - folderInfo.files.each { file -> - PullFilesFromGit("${folderPath}/${filename}", branchName, false, repositoryName) - } - palRm("${folderPath}/.codecommit") - - } else { - - def errorFile = "${folderPath}/error.txt" - palMkdir(folderPath) - retry(3) { - try { - if(env.IS_UNIX) { - sh label: "Downloading ${filenamePath}", - script: "aws codecommit get-file --repository-name ${repositoryName} --commit-specifier ${branchName} --file-path ${filenamePath} --query fileContent --output text 2>${errorFile} > ${filenamePath}_encoded" - sh label: 'Decoding', - script: "base64 --decode ${filenamePath}_encoded > ${filenamePath}" - } else { - errorFile = errorFile.replace('/','\\') - win_filenamePath = filenamePath.replace('/', '\\') - bat label: "Downloading ${win_filenamePath}", - script: "aws codecommit get-file --repository-name ${repositoryName} --commit-specifier ${branchName} --file-path ${filenamePath} --query fileContent --output text 2>${errorFile} > ${win_filenamePath}_encoded" - bat label: 'Decoding', - script: "certutil -decode ${win_filenamePath}_encoded ${win_filenamePath}" - } - palRm("${filenamePath}_encoded") - } catch (Exception ex) { - def error = '' - if(fileExists(errorFile)) { - error = readFile errorFile - } - if (!error || !(!failIfNotFound && error.contains('FileDoesNotExistException'))) { - palRm("${errorFile} ${filenamePath}.encoded ${filenamePath}") - throw new Exception("Could not get file: ${filenamePath}, ex: ${ex}, stderr: ${error}") - } - } - palRm(errorFile) - } - } -} - -def SetLfsCredentials(cmd, lbl = '') { - if (env.IS_UNIX) { - sh label: lbl, - script: cmd - } else { - bat label: lbl, - script: cmd - } -} - -def CheckoutBootstrapScripts(String branchName) { - checkout([$class: "GitSCM", - branches: [[name: "*/${branchName}"]], - doGenerateSubmoduleConfigurations: false, - extensions: [ - [ - $class: "SparseCheckoutPaths", - sparseCheckoutPaths: [ - [ $class: "SparseCheckoutPath", path: "AutomatedReview/" ], - [ $class: "SparseCheckoutPath", path: "scripts/build/bootstrap/" ], - [ $class: "SparseCheckoutPath", path: "Tools/build/JenkinsScripts/build/Platform" ] - ] - ], - [ - $class: "CloneOption", depth: 1, noTags: false, reference: "", shallow: true - ] - ], - submoduleCfg: [], - userRemoteConfigs: scm.userRemoteConfigs - ]) -} - -def CheckoutRepo(boolean disableSubmodules = false) { - dir(ENGINE_REPOSITORY_NAME) { - palSh('git lfs uninstall', 'Git LFS Uninstall') // Prevent git from pulling lfs objects during checkout - - if(fileExists('.git')) { - // If the repository after checkout is locked, likely we took a snapshot while git was running, - // to leave the repo in a usable state, garbagecollect. This also helps in situations where - def indexLockFile = '.git/index.lock' - if(fileExists(indexLockFile)) { - palSh('git gc', 'Git GarbageCollect') - } - if(fileExists(indexLockFile)) { // if it is still there, remove it - palRm(indexLockFile) - } - } - } - - def random = new Random() - def retryAttempt = 0 - retry(5) { - if (retryAttempt > 0) { - sleep random.nextInt(60 * retryAttempt) // Stagger checkouts to prevent HTTP 429 (Too Many Requests) response from CodeCommit - } - retryAttempt = retryAttempt + 1 - if(params.PULL_REQUEST_ID) { - // This is a pull request build. Perform merge with destination branch before building. - dir(ENGINE_REPOSITORY_NAME) { - checkout scm: [ - $class: 'GitSCM', - branches: scm.branches, - extensions: [ - [$class: 'PreBuildMerge', options: [mergeRemote: 'origin', mergeTarget: params.DESTINATION_BRANCH]], - [$class: 'SubmoduleOption', disableSubmodules: disableSubmodules, recursiveSubmodules: true], - [$class: 'CheckoutOption', timeout: 60] - ], - userRemoteConfigs: scm.userRemoteConfigs - ] - } - } else { - dir(ENGINE_REPOSITORY_NAME) { - checkout scm: [ - $class: 'GitSCM', - branches: scm.branches, - extensions: [ - [$class: 'SubmoduleOption', disableSubmodules: disableSubmodules, recursiveSubmodules: true], - [$class: 'CheckoutOption', timeout: 60] - ], - userRemoteConfigs: scm.userRemoteConfigs - ] - } - } - } - - // Add folder where we will store the 3rdParty downloads and packages - if(!fileExists('3rdParty')) { - palMkdir('3rdParty') - } - - dir(ENGINE_REPOSITORY_NAME) { - // Run lfs in a separate step. Jenkins is unable to load the credentials for the custom LFS endpoint - withCredentials([usernamePassword(credentialsId: "${env.GITHUB_USER}", passwordVariable: 'accesstoken', usernameVariable: 'username')]) { - SetLfsCredentials("git config -f .lfsconfig lfs.url https://${username}:${accesstoken}@${env.LFS_URL}", 'Set credentials') - } - palSh('git lfs install', 'Git LFS Install') - palSh('git lfs pull', 'Git LFS Pull') - - // CHANGE_ID is used by some scripts to identify uniquely the current change (usually metric jobs) - palSh('git rev-parse HEAD > commitid', 'Getting commit id') - env.CHANGE_ID = readFile file: 'commitid' - env.CHANGE_ID = env.CHANGE_ID.trim() - palRm('commitid') - } -} - -def PreBuildCommonSteps(Map pipelineConfig, String projectName, String pipeline, String branchName, String platform, String buildType, String workspace, boolean mount = true, boolean disableSubmodules = false) { - echo 'Starting pre-build common steps...' - - if (mount) { - unstash name: 'incremental_build_script' - - def pythonCmd = '' - if(env.IS_UNIX) pythonCmd = 'sudo -E python -u ' - else pythonCmd = 'python -u ' - - if(env.RECREATE_VOLUME.toBoolean()) { - palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action delete --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Deleting volume') - } - timeout(5) { - palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action mount --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Mounting volume') - } - - if(env.IS_UNIX) { - sh label: 'Setting volume\'s ownership', - script: """ - if sudo test ! -d "${workspace}"; then - sudo mkdir -p ${workspace} - cd ${workspace}/.. - sudo chown -R lybuilder:root . - fi - """ - } - } - - // Cleanup previous repo location, we are currently at the root of the workspace, if we have a .git folder - // we need to cleanup. Once all branches take this relocation, we can remove this - if(env.CLEAN_WORKSPACE.toBoolean() || fileExists("${workspace}/.git")) { - if(fileExists(workspace)) { - palRmDir(workspace) - } - } - - dir(workspace) { - - CheckoutRepo(disableSubmodules) - - // Get python - dir(ENGINE_REPOSITORY_NAME) { - if(env.IS_UNIX) { - sh label: 'Getting python', - script: 'python/get_python.sh' - } else { - bat label: 'Getting python', - script: 'python/get_python.bat' - } - - if(env.CLEAN_OUTPUT_DIRECTORY.toBoolean() || env.CLEAN_ASSETS.toBoolean()) { - def command = "${pipelineConfig.BUILD_ENTRY_POINT} --platform ${platform} --type clean" - if (env.IS_UNIX) { - sh label: "Running ${platform} clean", - script: "${pipelineConfig.PYTHON_DIR}/python.sh -u ${command}" - } else { - bat label: "Running ${platform} clean", - script: "${pipelineConfig.PYTHON_DIR}/python.cmd -u ${command}".replace('/','\\') - } - } - } - } -} - -def Build(Map options, String platform, String type, String workspace) { - def command = "${options.BUILD_ENTRY_POINT} --platform ${platform} --type ${type}" - dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { - if (env.IS_UNIX) { - sh label: "Running ${platform} ${type}", - script: "${options.PYTHON_DIR}/python.sh -u ${command}" - } else { - bat label: "Running ${platform} ${type}", - script: "${options.PYTHON_DIR}/python.cmd -u ${command}".replace('/','\\') - } - } -} - -def TestMetrics(Map options, String workspace, String branchName, String repoName, String buildJobName, String outputDirectory, String configuration) { - catchError(buildResult: null, stageResult: null) { - def cmakeBuildDir = [workspace, ENGINE_REPOSITORY_NAME, outputDirectory].join('/') - dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { - checkout scm: [ - $class: 'GitSCM', - branches: [[name: '*/main']], - extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'mars']], - userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars', credentialsId: "${env.GITHUB_USER}"]] - ] - withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { - def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py -e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} ${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " - bat label: "Publishing ${buildJobName} Test Metrics", - script: command - } - } - } -} - -def PostBuildCommonSteps(String workspace, boolean mount = true) { - echo 'Starting post-build common steps...' - - if(params.PULL_REQUEST_ID) { - dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { - if(fileExists('.git')) { - palSh('git reset --hard HEAD', 'Discard PR merge, git reset') - } - } - } - - if (mount) { - def pythonCmd = '' - if(env.IS_UNIX) pythonCmd = 'sudo -E python -u ' - else pythonCmd = 'python -u ' - - try { - timeout(5) { - palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action unmount", 'Unmounting volume') - } - } catch (Exception e) { - echo "Unmount script error ${e}" - } - } -} - -def CreateSetupStage(Map pipelineConfig, String projectName, String pipelineName, String branchName, String platformName, String jobName, Map environmentVars) { - return { - stage("Setup") { - PreBuildCommonSteps(pipelineConfig, projectName, pipelineName, branchName, platformName, jobName, environmentVars['WORKSPACE'], environmentVars['MOUNT_VOLUME']) - } - } -} - -def CreateBuildStage(Map pipelineConfig, String platformName, String jobName, Map environmentVars) { - return { - stage("${jobName}") { - Build(pipelineConfig, platformName, jobName, environmentVars['WORKSPACE']) - } - } -} - -def CreateTestMetricsStage(Map pipelineConfig, String branchName, Map environmentVars, String buildJobName, String outputDirectory, String configuration) { - return { - stage("${buildJobName}_metrics") { - TestMetrics(pipelineConfig, environmentVars['WORKSPACE'], branchName, env.DEFAULT_REPOSITORY_NAME, buildJobName, outputDirectory, configuration) - } - } -} - -def CreateTeardownStage(Map environmentVars) { - return { - stage("Teardown") { - PostBuildCommonSteps(environmentVars['WORKSPACE'], environmentVars['MOUNT_VOLUME']) - } - } -} - -def projectName = '' -def pipelineName = '' -def branchName = '' -def pipelineConfig = {} - -// Start Pipeline -try { - stage('Setup Pipeline') { - node('controller') { - def envVarList = [] - if(isUnix()) { - envVarList.add('IS_UNIX=1') - } - withEnv(envVarList) { - timestamps { - (projectName, pipelineName) = GetRunningPipelineName(env.JOB_NAME) // env.JOB_NAME is the name of the job given by Jenkins - scmType = GetSCMType() - - if(env.BRANCH_NAME) { - branchName = env.BRANCH_NAME - } else { - branchName = scm.branches[0].name // for non-multibranch pipelines - env.BRANCH_NAME = branchName // so scripts that read this environment have it (e.g. incremental_build_util.py) - } - pipelineProperties.add(disableConcurrentBuilds()) - - echo "Running \"${pipelineName}\" for \"${branchName}\"..." - - if (scmType == 'github') { - CheckoutBootstrapScripts(branchName) - } - - // Load configs - pipelineConfig = LoadPipelineConfig(pipelineName, branchName, scmType) - - // Add each platform as a parameter that the user can disable if needed - pipelineConfig.platforms.each { platform -> - pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) - } - pipelineProperties.add(parameters(pipelineParameters)) - properties(pipelineProperties) - - // Stash the INCREMENTAL_BUILD_SCRIPT_PATH since all nodes will use it - if (scmType == 'codecommit') { - PullFilesFromGit(INCREMENTAL_BUILD_SCRIPT_PATH, branchName, true, ENGINE_REPOSITORY_NAME) - } - stash name: 'incremental_build_script', - includes: INCREMENTAL_BUILD_SCRIPT_PATH - } - } - } - } - - if(env.BUILD_NUMBER == '1') { - // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users - // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 - currentBuild.result = 'SUCCESS' - return - } - - // Build and Post-Build Testing Stage - def buildConfigs = [:] - - // Platform Builds run on EC2 - pipelineConfig.platforms.each { platform -> - platform.value.build_types.each { build_job -> - if (IsJobEnabled(build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline - def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) - envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this - def nodeLabel = envVars['NODE_LABEL'] - - buildConfigs["${platform.key} [${build_job.key}]"] = { - node("${nodeLabel}") { - if(isUnix()) { // Has to happen inside a node - envVars['IS_UNIX'] = 1 - } - withEnv(GetEnvStringList(envVars)) { - timeout(time: envVars['TIMEOUT'], unit: 'MINUTES', activity: true) { - try { - def build_job_name = build_job.key - - CreateSetupStage(pipelineConfig, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() - - if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages - build_job.value.steps.each { build_step -> - build_job_name = build_step - CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() - } - } else { - CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() - } - - if (env.MARS_REPO && platform.key == 'Windows' && build_job_name.startsWith('test')) { - def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY - def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION - CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() - } - } - catch(Exception e) { - // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java - // {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED} - def currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' - if (currentResult == 'FAILURE') { - currentBuild.result = 'FAILURE' - error "FAILURE: ${e}" - } else if (currentResult == 'UNSTABLE') { - currentBuild.result = 'UNSTABLE' - unstable(message: "UNSTABLE: ${e}") - } - } - finally { - CreateTeardownStage(envVars).call() - } - } - } - } - } - } - } - } - - timestamps { - - stage('Build') { - parallel buildConfigs // Run parallel builds - } - - echo 'All builds successful' - } -} -catch(Exception e) { - error "Exception: ${e}" -} -finally { - try { - if(env.SNS_TOPIC) { - snsPublish( - topicArn: env.SNS_TOPIC, - subject:'Build Result', - message:"${currentBuild.currentResult}:${params.REPOSITORY_NAME}:${params.SOURCE_BRANCH}:${params.SOURCE_COMMIT}:${params.DESTINATION_COMMIT}:${params.PULL_REQUEST_ID}:${BUILD_URL}:${env.RECREATE_VOLUME}:${env.CLEAN_OUTPUT_DIRECTORY}:${env.CLEAN_ASSETS}" - ) - } - step([ - $class: 'Mailer', - notifyEveryUnstableBuild: true, - sendToIndividuals: true, - recipients: emailextrecipients([ - [$class: 'CulpritsRecipientProvider'], - [$class: 'RequesterRecipientProvider'] - ]) - ]) - } catch(Exception e) { - } -} diff --git a/AutomatedReview/lumberyard.json b/AutomatedReview/lumberyard.json deleted file mode 100644 index a174b7b449..0000000000 --- a/AutomatedReview/lumberyard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "BUILD_ENTRY_POINT": "Tools/build/JenkinsScripts/build/ci_build.py", - "PIPELINE_CONFIGS": [ - "Tools/build/JenkinsScripts/build/Platform/*/pipeline.json", - "restricted/*/Tools/build/JenkinsScripts/build/pipeline.json" - ], - "BUILD_CONFIGS": [ - "Tools/build/JenkinsScripts/build/Platform/*/build_config.json", - "restricted/*/Tools/build/JenkinsScripts/build/build_config.json" - ], - "PYTHON_DIR": "python" -} From 2c3a98878fd9985aba685c5af220f39297c03f02 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:29:31 -0700 Subject: [PATCH 042/122] SPEC-6137 Add a non-unity build for Linux in AR gating runs --- .../JenkinsScripts/build/Platform/Linux/build_config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json b/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json index a7d881c995..a1676902f9 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json +++ b/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json @@ -12,7 +12,7 @@ "default" ], "steps": [ - "profile", + "profile_nounity", "asset_profile", "test_profile" ] @@ -43,6 +43,7 @@ }, "profile": { "TAGS": [ + "nightly", "daily-pipeline-metrics", "weekly-build-metrics" ], @@ -57,7 +58,6 @@ }, "profile_nounity": { "TAGS": [ - "nightly", "weekly-build-metrics" ], "COMMAND": "build_linux.sh", From 78e5a069faf1e906baed9c3c2827eaca1eda5970 Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Wed, 14 Apr 2021 14:31:44 -0500 Subject: [PATCH 043/122] Removed Cry branding on error messages (#41) --- Code/CryEngine/Cry3DEngine/cvars.cpp | 2 +- Code/CryEngine/CrySystem/AZCrySystemInitLogSink.cpp | 4 ++-- Code/CryEngine/CrySystem/SystemWin32.cpp | 6 +++--- Code/LauncherUnified/Launcher.cpp | 2 +- Code/Sandbox/Editor/CryEdit.cpp | 2 +- Code/Sandbox/Editor/CryEditDoc.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Code/CryEngine/Cry3DEngine/cvars.cpp b/Code/CryEngine/Cry3DEngine/cvars.cpp index a34507e62e..e63c539a85 100644 --- a/Code/CryEngine/Cry3DEngine/cvars.cpp +++ b/Code/CryEngine/Cry3DEngine/cvars.cpp @@ -922,7 +922,7 @@ void CVars::Init() "Will not render CGFs past the given amount of drawcalls\n" "(<=0 off (default), >0 draw calls limit)"); - REGISTER_CVAR(e_CheckOctreeObjectsBoxSize, 1, VF_NULL, "CryWarning for crazy sized COctreeNode m_objectsBoxes"); + REGISTER_CVAR(e_CheckOctreeObjectsBoxSize, 1, VF_NULL, "Warning for crazy sized COctreeNode m_objectsBoxes"); REGISTER_CVAR(e_DebugGeomPrep, 0, VF_NULL, "enable logging of Geom preparation"); DefineConstIntCVar(e_GeomCaches, 1, VF_NULL, "Activates drawing of geometry caches"); REGISTER_CVAR(e_GeomCacheBufferSize, 128, VF_CHEAT, "Geometry cache stream buffer upper limit size in MB. Default: 128"); diff --git a/Code/CryEngine/CrySystem/AZCrySystemInitLogSink.cpp b/Code/CryEngine/CrySystem/AZCrySystemInitLogSink.cpp index ae8b1b1c09..857a9e993d 100644 --- a/Code/CryEngine/CrySystem/AZCrySystemInitLogSink.cpp +++ b/Code/CryEngine/CrySystem/AZCrySystemInitLogSink.cpp @@ -35,7 +35,7 @@ namespace AZ } AZ::OSString msgBoxMessage; - msgBoxMessage.append("CrySystem could not initialize correctly for the following reason(s):"); + msgBoxMessage.append("O3DE could not initialize correctly for the following reason(s):"); for (const AZ::OSString& errMsg : m_errorStringsCollected) { @@ -47,7 +47,7 @@ namespace AZ Trace::Output(nullptr, msgBoxMessage.c_str()); Trace::Output(nullptr, "\n==================================================================\n"); - EBUS_EVENT(AZ::NativeUI::NativeUIRequestBus, DisplayOkDialog, "CrySystem Initialization Failed", msgBoxMessage.c_str(), false); + EBUS_EVENT(AZ::NativeUI::NativeUIRequestBus, DisplayOkDialog, "O3DE Initialization Failed", msgBoxMessage.c_str(), false); } } // namespace Debug } // namespace AZ diff --git a/Code/CryEngine/CrySystem/SystemWin32.cpp b/Code/CryEngine/CrySystem/SystemWin32.cpp index a46f080106..974e578f38 100644 --- a/Code/CryEngine/CrySystem/SystemWin32.cpp +++ b/Code/CryEngine/CrySystem/SystemWin32.cpp @@ -605,7 +605,7 @@ void CSystem::DebugStats([[maybe_unused]] bool checkpoint, [[maybe_unused]] bool { if (!dbgmodules[i].handle) { - CryLogAlways("WARNING: CSystem::DebugStats: NULL handle for %s", dbgmodules[i].name.c_str()); + CryLogAlways("WARNING: CSystem::DebugStats: NULL handle for %s", dbgmodules[i].name.c_str()); nolib++; continue; } @@ -642,7 +642,7 @@ void CSystem::DebugStats([[maybe_unused]] bool checkpoint, [[maybe_unused]] bool } else { - CryLogAlways("WARNING: CSystem::DebugStats: could not retrieve function from DLL %s", dbgmodules[i].name.c_str()); + CryLogAlways("WARNING: CSystem::DebugStats: could not retrieve function from DLL %s", dbgmodules[i].name.c_str()); nolib++; }; #endif @@ -1066,7 +1066,7 @@ void CSystem::FatalError(const char* format, ...) if (szSysErrorMessage) { - CryLogAlways(" Last System Error: %s", szSysErrorMessage); + CryLogAlways("Last System Error: %s", szSysErrorMessage); } if (GetUserCallback()) diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index cd9d73421b..36d6a432f5 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -313,7 +313,7 @@ namespace O3DELauncher return "Failed to initialize the CrySystem Interface"; case ReturnCode::ErrCryEnvironment: - return "Failed to initialize the CryEngine global environment"; + return "Failed to initialize the global environment"; case ReturnCode::ErrAssetProccessor: return "Failed to connect to AssetProcessor while the /Amazon/AzCore/Bootstrap/wait_for_connect value is 1\n." diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 6f311fe9ac..dff5b2267c 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -5702,7 +5702,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) int exitCode = 0; BOOL didCryEditStart = CCryEditApp::instance()->InitInstance(); - AZ_Error("Editor", didCryEditStart, "CryEditor did not initialize correctly, and will close." + AZ_Error("Editor", didCryEditStart, "O3DE Editor did not initialize correctly, and will close." "\nThis could be because of incorrectly configured components, or missing required gems." "\nSee other errors for more details."); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index f446c50bd6..15269c1496 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -1931,7 +1931,7 @@ void CCryEditDoc::Fetch(const QString& holdName, const QString& relativeHoldPath if (!LoadXmlArchiveArray(arrXmlAr, holdFilename, holdPath)) { QMessageBox::critical(QApplication::activeWindow(), "Error", "The temporary 'Hold' level failed to load successfully. Your level might be corrupted, you should restart the Editor.", QMessageBox::Ok); - AZ_Error("CryEditDoc", false, "Fetch failed to load the Xml Archive"); + AZ_Error("EditDoc", false, "Fetch failed to load the Xml Archive"); return; } From 9c01e993db61ef10105a131c0cf2033b5d360c15 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 14 Apr 2021 12:58:03 -0700 Subject: [PATCH 044/122] Convert etc2comp to new 3p system (#44) --- cmake/3rdParty/Findetc2comp.cmake | 18 ------------------ .../Platform/Linux/BuiltInPackages_linux.cmake | 1 + .../Platform/Linux/cmake_linux_files.cmake | 1 - .../Platform/Linux/etc2comp_linux.cmake | 12 ------------ .../Platform/Mac/BuiltInPackages_mac.cmake | 1 + .../Platform/Mac/cmake_mac_files.cmake | 3 +-- cmake/3rdParty/Platform/Mac/etc2comp_mac.cmake | 12 ------------ .../Windows/BuiltInPackages_windows.cmake | 1 + .../Platform/Windows/cmake_windows_files.cmake | 1 - .../Platform/Windows/etc2comp_windows.cmake | 13 ------------- cmake/3rdParty/cmake_files.cmake | 1 - 11 files changed, 4 insertions(+), 60 deletions(-) delete mode 100644 cmake/3rdParty/Findetc2comp.cmake delete mode 100644 cmake/3rdParty/Platform/Linux/etc2comp_linux.cmake delete mode 100644 cmake/3rdParty/Platform/Mac/etc2comp_mac.cmake delete mode 100644 cmake/3rdParty/Platform/Windows/etc2comp_windows.cmake diff --git a/cmake/3rdParty/Findetc2comp.cmake b/cmake/3rdParty/Findetc2comp.cmake deleted file mode 100644 index e6fbf0ec24..0000000000 --- a/cmake/3rdParty/Findetc2comp.cmake +++ /dev/null @@ -1,18 +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. -# - -ly_add_external_target( - NAME etc2comp - VERSION 2017_04_24-az.2 - INCLUDE_DIRECTORIES - EtcLib/Etc - EtcLib/EtcCodec -) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 4659c3f03a..9057b5ba1b 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -39,6 +39,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS free ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-linux TARGETS AWSNativeSDK PACKAGE_HASH e69c55682638dc1e7fa571a61a82c8a69d395c74a008543a5188f4bd2b6b10c4) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-linux TARGETS PhysX PACKAGE_HASH e3ca36106a8dbf1524709f8bb82d520920ebd3ff3a92672d382efff406c75ee3) +ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-linux TARGETS GoogleBenchmark PACKAGE_HASH 4038878f337fc7e0274f0230f71851b385b2e0327c495fc3dd3d1c18a807928d) diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index 5303b2b1e8..2b1ba4d0e5 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -15,7 +15,6 @@ set(FILES civetweb_linux.cmake Clang_linux.cmake dyad_linux.cmake - etc2comp_linux.cmake FbxSdk_linux.cmake OpenSSL_linux.cmake Wwise_linux.cmake diff --git a/cmake/3rdParty/Platform/Linux/etc2comp_linux.cmake b/cmake/3rdParty/Platform/Linux/etc2comp_linux.cmake deleted file mode 100644 index a9053a1058..0000000000 --- a/cmake/3rdParty/Platform/Linux/etc2comp_linux.cmake +++ /dev/null @@ -1,12 +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. -# - -set(ETC2COMP_LIBS ${BASE_PATH}/EtcLib/Linux_x64/libEtcLib.a) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 7973eb3303..ef66259e22 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -44,6 +44,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS fre ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-mac TARGETS PhysX PACKAGE_HASH 149f5e9b44bd27291b1c4772f5e89a1e0efa88eef73c7e0b188935ed4d0c4a70) +ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-mac TARGETS googletest PACKAGE_HASH cbf020d5ef976c5db8b6e894c6c63151ade85ed98e7c502729dd20172acae5a8) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-mac TARGETS GoogleBenchmark PACKAGE_HASH ad25de0146769c91e179953d845de2bec8ed4a691f973f47e3eb37639381f665) diff --git a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake index c569886384..f786f80cf7 100644 --- a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake +++ b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake @@ -14,8 +14,7 @@ set(FILES civetweb_mac.cmake Clang_mac.cmake DirectXShaderCompiler_mac.cmake - etc2comp_mac.cmake FbxSdk_mac.cmake OpenSSL_mac.cmake Wwise_mac.cmake -) \ No newline at end of file +) diff --git a/cmake/3rdParty/Platform/Mac/etc2comp_mac.cmake b/cmake/3rdParty/Platform/Mac/etc2comp_mac.cmake deleted file mode 100644 index b48aa27301..0000000000 --- a/cmake/3rdParty/Platform/Mac/etc2comp_mac.cmake +++ /dev/null @@ -1,12 +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. -# - -set(ETC2COMP_LIBS ${BASE_PATH}/EtcLib/OSX_x86/$,Debug,Release>/libEtcLib.a) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index afecb0788c..58050652c0 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -46,6 +46,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS fre ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-windows TARGETS PhysX PACKAGE_HASH 198bed89d1aae7caaf5dadba24cee56235fe41725d004b64040d4e50d0f3aa1a) +ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-windows TARGETS googletest PACKAGE_HASH 7e8f03ae8a01563124e3daa06386f25a2b311c10bb95bff05cae6c41eff83837) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-windows TARGETS GoogleBenchmark PACKAGE_HASH 0c94ca69ae8e7e4aab8e90032b5c82c5964410429f3dd9dbb1f9bf4fe032b1d4) diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index ff65abe10c..2c7890fcc4 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -16,7 +16,6 @@ set(FILES Crashpad_windows.cmake DirectXShaderCompiler_windows.cmake dyad_windows.cmake - etc2comp_windows.cmake FbxSdk_windows.cmake libav_windows.cmake OpenSSL_windows.cmake diff --git a/cmake/3rdParty/Platform/Windows/etc2comp_windows.cmake b/cmake/3rdParty/Platform/Windows/etc2comp_windows.cmake deleted file mode 100644 index 823fc50c23..0000000000 --- a/cmake/3rdParty/Platform/Windows/etc2comp_windows.cmake +++ /dev/null @@ -1,13 +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. -# - -set(ETC2COMP_LIBS ${BASE_PATH}/EtcLib/Windows_x86_64/vc140/$,Debug,Release>/EtcLib.lib) -set(ETC2COMP_LINK_OPTIONS $<$:-Wl,>/ignore:4099) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index 98f8311d3b..3fe15bc0ce 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -16,7 +16,6 @@ set(FILES FindClang.cmake FindDirectXShaderCompiler.cmake Finddyad.cmake - Findetc2comp.cmake FindFbxSdk.cmake Findlibav.cmake FindOpenSSL.cmake From fff97cda3bace16af52335a4856ea7acd95d70b7 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 14 Apr 2021 13:09:21 -0700 Subject: [PATCH 045/122] Cache runtime dependencies for targets to speed up iOS configuration. --- cmake/Platform/iOS/RuntimeDependencies_ios.cmake | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmake/Platform/iOS/RuntimeDependencies_ios.cmake b/cmake/Platform/iOS/RuntimeDependencies_ios.cmake index 37c1d6d976..d558c6f12a 100644 --- a/cmake/Platform/iOS/RuntimeDependencies_ios.cmake +++ b/cmake/Platform/iOS/RuntimeDependencies_ios.cmake @@ -28,6 +28,17 @@ function(ios_get_dependencies_recursive ios_DEPENDENCIES ly_TARGET) return() # Nothing to do endif() + # See if we already have dependencies cached. + get_property(are_dependencies_cached GLOBAL PROPERTY LY_RUNTIME_DEPENDENCIES_${ly_TARGET} SET) + if(are_dependencies_cached) + + # We already walked through this target + get_property(cached_dependencies GLOBAL PROPERTY LY_RUNTIME_DEPENDENCIES_${ly_TARGET}) + set(${ios_DEPENDENCIES} ${cached_dependencies} PARENT_SCOPE) + return() + + endif() + # Collect all direct dependencies. unset(direct_dependencies) unset(dependencies) @@ -102,6 +113,7 @@ function(ios_get_dependencies_recursive ios_DEPENDENCIES ly_TARGET) # Remove duplicate dependencies and return. list(REMOVE_DUPLICATES all_dependencies) + set_property(GLOBAL PROPERTY LY_RUNTIME_DEPENDENCIES_${ly_TARGET} "${all_dependencies}") set(${ios_DEPENDENCIES} ${all_dependencies} PARENT_SCOPE) endfunction() From 4a3d24f189b7fd8ddae597d7829afefe064dac2d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 14:40:42 -0700 Subject: [PATCH 046/122] SPEC-6276 Move ci_build and ci_build_metrics to scripts\build --- .../build/JenkinsScripts/build/PackageEnv.py | 193 --- Tools/build/JenkinsScripts/build/Params.py | 81 -- .../JenkinsScripts/build/cmake_package.py | 358 ------ .../build/cmake_package_env.json | 106 -- .../download_latest_package_from_bucket.py | 80 -- .../JenkinsScripts/build/download_packages.py | 55 - .../build/jenkins_scm_metrics.py | 57 - .../JenkinsScripts/build/utils/__init__.py | 12 - .../build/utils/copy_LAD_3rdParty.xml | 51 - .../build/utils/download_from_s3.py | 102 -- .../build/utils/email_to_lionbridge.py | 129 -- .../build/utils/incremental_build_util.py | 662 ---------- .../build/utils/jenkins_scm_metrics.py | 57 - .../build/utils/lib/__init__.py | 12 - .../JenkinsScripts/build/utils/lib/glob3.py | 174 --- .../build/utils/packaging_version.py | 75 -- .../build/utils/scrubbing_test.py | 212 --- .../build/utils/update_bootstrap_cfg.py | 82 -- .../build/utils/upload_benchmarks.py | 174 --- .../build/utils/upload_metrics_to_kinesis.py | 183 --- .../build/utils/upload_to_s3.py | 107 -- .../build/JenkinsScripts/build/utils/util.py | 65 - .../distribution/AWS_PyTools/LyChecksum.py | 64 - .../AWS_PyTools/LyCloudfrontOps.py | 76 -- .../distribution/AWS_PyTools/__init__.py | 12 - .../update_internal_whitelist.py | 303 ----- .../Installer/BootstrapperLogo.png | 3 - .../distribution/Installer/BuildInstaller.py | 289 ----- .../Installer/BuildInstallerUtils.py | 206 --- .../Installer/BuildInstallerWixUtils.py | 85 -- .../distribution/Installer/Candle.py | 145 --- .../distribution/Installer/Heat.py | 257 ---- .../Installer/HeatDevPackageBase.wxs | 3 - .../Installer/HeatPackageBase.wxs | 3 - .../distribution/Installer/Insignia.py | 67 - .../distribution/Installer/InstallerArgs.py | 115 -- .../Installer/InstallerAutomation.py | 273 ---- .../distribution/Installer/InstallerIcon.ico | 3 - .../Installer/InstallerPackaging.py | 225 ---- .../distribution/Installer/InstallerParams.py | 93 -- .../distribution/Installer/Light.py | 57 - .../Installer/LumberyardBootstrapper.wxs | 3 - .../Installer/LumberyardDevCertSetup.bat | 14 - .../Installer/LumberyardThemeGDC.wxl | 61 - .../Installer/LumberyardThemeGDC.xml | 85 -- .../Installer/PackageExeSigning.py | 29 - .../Installer/Redistributables.wxs | 3 - .../distribution/Installer/SignTool.py | 212 --- .../distribution/Installer/TestInstaller.py | 186 --- .../distribution/Installer/__init__.py | 10 - .../Installer/allowed_empty_folders.json | 23 - .../distribution/Installer/dir_filelist.json | 50 - .../Installer/editor_icon_setup.ico | 3 - .../distribution/Installer/license.rtf | Bin 685 -> 0 bytes .../BuildGameTemplateWhitelist.py | 66 - .../BuildGameTemplateWhitelistArgs.py | 30 - .../ThirdParty/BuildThirdPartyPackages.py | 309 ----- .../ThirdParty/BuildThirdPartyUtils.py | 29 - .../distribution/ThirdParty/SDKPackager.py | 207 --- .../ThirdParty/ThirdPartySDKAWS.py | 76 -- .../JenkinsScripts/distribution/__init__.py | 12 - .../JenkinsScripts/distribution/copyright.txt | 12 - .../distribution/copyright_prepender.py | 83 -- .../copyright_removal/Categorizer.py | 16 - .../copyright_removal/CommentCategory.py | 26 - .../copyright_removal/SlashComment.py | 20 - .../copyright_removal/StarComment.py | 20 - .../copyright_header_manual_tool.py | 580 --------- .../copyright_removal/copyright_update.py | 813 ------------ .../copyright_removal/copyrighttool.py | 473 ------- .../copyright_removal/crytek_3.8.1_source.txt | 0 .../replace_crytek_copyright.py | 126 -- .../distribution/get_changelist_number.py | 20 - .../git_release/GitDailyValidation.py | 143 --- .../distribution/git_release/GitHashList.json | 23 - .../git_release/GitIntegrityChecker.py | 203 --- .../git_release/GitIntegrityCheckerTester.py | 47 - .../git_release/GitMoveDetection.py | 331 ----- .../git_release/GitOpsCodeCommit.py | 75 -- .../distribution/git_release/GitOpsCommon.py | 24 - .../distribution/git_release/GitOpsGitHub.py | 49 - .../distribution/git_release/GitPromotion.py | 417 ------ .../distribution/git_release/GitRelease.py | 217 ---- .../distribution/git_release/GitStaging.py | 825 ------------ .../distribution/git_release/build.xml | 146 --- .../distribution/git_release/git_bootstrap.py | 1136 ----------------- .../git_release/git_bootstrap_test.py | 208 --- .../.github/ISSUE_TEMPLATE/bug_report.md | 26 - .../.github/ISSUE_TEMPLATE/feature_request.md | 17 - .../inject/.github/ISSUE_TEMPLATE/question.md | 20 - .../git_release/inject/CONTRIBUTING.md | 45 - .../distribution/git_release/inject/README.md | 57 - .../distribution/inject_signed_binaries.py | 167 --- .../distribution/ly_dep_version_tool.py | 59 - .../distribution/modify_lylauncherconfig.py | 24 - .../distribution/package_source_assets.bat | 44 - .../distribution/release_automation_tool.py | 47 - .../JenkinsScripts/distribution/s3multiput.py | 379 ------ .../JenkinsScripts/distribution/s3put.py | 450 ------- .../distribution/update_version_strings.py | 66 - .../JenkinsScripts/distribution/web/.htaccess | 5 - .../JenkinsScripts/distribution/web/.htpasswd | 1 - .../distribution/web/config.php | 10 - .../distribution/web/css/fetch.css | 56 - .../distribution/web/css/kappa.css | 154 --- .../distribution/web/css/style.css | 208 --- .../distribution/web/fetch_files.php | 49 - .../distribution/web/images/Favicon.ico | 3 - .../distribution/web/index.html | 29 - .../JenkinsScripts/distribution/web/index.php | 59 - python/get_python.bat | 2 +- python/get_python.sh | 6 +- scripts/build/Jenkins/Jenkinsfile | 2 +- scripts/build/Jenkins/lumberyard.json | 10 +- .../Android/build_and_run_unit_tests.cmd | 4 +- .../build/Platform/Android/build_config.json | 2 +- .../build/Platform/Android/gradle_windows.cmd | 0 .../build/Platform/Android/pipeline.json | 0 .../Android/run_test_on_android_simulator.py | 0 .../build/Platform/Linux/asset_linux.sh | 0 .../build/Platform/Linux/build_asset_linux.sh | 0 .../build/Platform/Linux/build_config.json | 2 +- .../build/Platform/Linux/build_linux.sh | 0 .../build/Platform/Linux/build_test_linux.sh | 0 .../build/Platform/Linux/clean_linux.sh | 0 .../build/Platform/Linux/env_linux.sh | 0 .../build/Platform/Linux/pipeline.json | 0 .../build/Platform/Linux/python_linux.sh | 0 .../build/Platform/Linux/test_linux.sh | 0 .../build/Platform/Mac/asset_mac.sh | 0 .../build/Platform/Mac/build_asset_mac.sh | 0 .../build/Platform/Mac/build_config.json | 2 +- .../build/Platform/Mac/build_mac.sh | 0 .../build/Platform/Mac/build_test_mac.sh | 0 .../build/Platform/Mac/clean_mac.sh | 0 .../build/Platform/Mac/env_mac.sh | 0 .../build/Platform/Mac/pipeline.json | 0 .../build/Platform/Mac/python_mac.sh | 0 .../build/Platform/Mac/test_mac.sh | 0 .../build/Platform/Windows/asset_windows.cmd | 0 .../Platform/Windows/build_asset_windows.cmd | 0 .../build/Platform/Windows/build_config.json | 4 +- .../Platform/Windows/build_ninja_windows.cmd | 0 .../Platform/Windows/build_test_windows.cmd | 0 .../build/Platform/Windows/build_windows.cmd | 0 .../build/Platform/Windows/clean_windows.cmd | 0 .../build/Platform/Windows/env_windows.cmd | 0 .../Windows/package_build_config.json | 0 .../build/Platform/Windows/pipeline.json | 0 .../build/Platform/Windows/python_windows.cmd | 0 .../build/Platform/Windows/test_windows.cmd | 0 .../build/Platform/iOS/build_config.json | 2 +- .../build/Platform/iOS/pipeline.json | 0 .../build/ci_build.py | 2 +- .../build/ci_build_metrics.py | 6 +- scripts/build/package/package.py | 2 +- .../build/submit_metrics.py | 0 .../scrubbing/canary.txt | 0 .../scrubbing}/scrubbing_job.py | 12 +- .../scrubbing/validator.py | 2 +- .../validator_data_LEGAL_REVIEW_REQUIRED.py | 20 +- 161 files changed, 42 insertions(+), 14760 deletions(-) delete mode 100755 Tools/build/JenkinsScripts/build/PackageEnv.py delete mode 100755 Tools/build/JenkinsScripts/build/Params.py delete mode 100755 Tools/build/JenkinsScripts/build/cmake_package.py delete mode 100644 Tools/build/JenkinsScripts/build/cmake_package_env.json delete mode 100755 Tools/build/JenkinsScripts/build/download_latest_package_from_bucket.py delete mode 100755 Tools/build/JenkinsScripts/build/download_packages.py delete mode 100755 Tools/build/JenkinsScripts/build/jenkins_scm_metrics.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/__init__.py delete mode 100644 Tools/build/JenkinsScripts/build/utils/copy_LAD_3rdParty.xml delete mode 100755 Tools/build/JenkinsScripts/build/utils/download_from_s3.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/email_to_lionbridge.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/incremental_build_util.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/jenkins_scm_metrics.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/lib/__init__.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/lib/glob3.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/packaging_version.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/scrubbing_test.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/update_bootstrap_cfg.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/upload_benchmarks.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/upload_metrics_to_kinesis.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/upload_to_s3.py delete mode 100755 Tools/build/JenkinsScripts/build/utils/util.py delete mode 100755 Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyChecksum.py delete mode 100755 Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyCloudfrontOps.py delete mode 100755 Tools/build/JenkinsScripts/distribution/AWS_PyTools/__init__.py delete mode 100755 Tools/build/JenkinsScripts/distribution/AWS_WAF_Updater/update_internal_whitelist.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/BootstrapperLogo.png delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/BuildInstaller.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerUtils.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerWixUtils.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/Candle.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/Heat.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/HeatDevPackageBase.wxs delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/HeatPackageBase.wxs delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/Insignia.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/InstallerArgs.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/InstallerAutomation.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/InstallerIcon.ico delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/InstallerPackaging.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/InstallerParams.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/Light.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/LumberyardBootstrapper.wxs delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/LumberyardDevCertSetup.bat delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.wxl delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.xml delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/PackageExeSigning.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/Redistributables.wxs delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/SignTool.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/TestInstaller.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Installer/__init__.py delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/allowed_empty_folders.json delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/dir_filelist.json delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/editor_icon_setup.ico delete mode 100644 Tools/build/JenkinsScripts/distribution/Installer/license.rtf delete mode 100755 Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelist.py delete mode 100755 Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelistArgs.py delete mode 100644 Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyPackages.py delete mode 100644 Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyUtils.py delete mode 100644 Tools/build/JenkinsScripts/distribution/ThirdParty/SDKPackager.py delete mode 100644 Tools/build/JenkinsScripts/distribution/ThirdParty/ThirdPartySDKAWS.py delete mode 100755 Tools/build/JenkinsScripts/distribution/__init__.py delete mode 100644 Tools/build/JenkinsScripts/distribution/copyright.txt delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_prepender.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/Categorizer.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/CommentCategory.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/SlashComment.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/StarComment.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_header_manual_tool.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_update.py delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/copyrighttool.py delete mode 100644 Tools/build/JenkinsScripts/distribution/copyright_removal/crytek_3.8.1_source.txt delete mode 100755 Tools/build/JenkinsScripts/distribution/copyright_removal/replace_crytek_copyright.py delete mode 100755 Tools/build/JenkinsScripts/distribution/get_changelist_number.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitDailyValidation.py delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/GitHashList.json delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityChecker.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityCheckerTester.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitMoveDetection.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitOpsCodeCommit.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitOpsCommon.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitOpsGitHub.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitPromotion.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitRelease.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/GitStaging.py delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/build.xml delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap.py delete mode 100755 Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap_test.py delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/question.md delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/inject/CONTRIBUTING.md delete mode 100644 Tools/build/JenkinsScripts/distribution/git_release/inject/README.md delete mode 100755 Tools/build/JenkinsScripts/distribution/inject_signed_binaries.py delete mode 100755 Tools/build/JenkinsScripts/distribution/ly_dep_version_tool.py delete mode 100755 Tools/build/JenkinsScripts/distribution/modify_lylauncherconfig.py delete mode 100644 Tools/build/JenkinsScripts/distribution/package_source_assets.bat delete mode 100755 Tools/build/JenkinsScripts/distribution/release_automation_tool.py delete mode 100755 Tools/build/JenkinsScripts/distribution/s3multiput.py delete mode 100755 Tools/build/JenkinsScripts/distribution/s3put.py delete mode 100755 Tools/build/JenkinsScripts/distribution/update_version_strings.py delete mode 100644 Tools/build/JenkinsScripts/distribution/web/.htaccess delete mode 100644 Tools/build/JenkinsScripts/distribution/web/.htpasswd delete mode 100644 Tools/build/JenkinsScripts/distribution/web/config.php delete mode 100644 Tools/build/JenkinsScripts/distribution/web/css/fetch.css delete mode 100644 Tools/build/JenkinsScripts/distribution/web/css/kappa.css delete mode 100644 Tools/build/JenkinsScripts/distribution/web/css/style.css delete mode 100644 Tools/build/JenkinsScripts/distribution/web/fetch_files.php delete mode 100644 Tools/build/JenkinsScripts/distribution/web/images/Favicon.ico delete mode 100644 Tools/build/JenkinsScripts/distribution/web/index.html delete mode 100644 Tools/build/JenkinsScripts/distribution/web/index.php rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Android/build_and_run_unit_tests.cmd (74%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Android/build_config.json (98%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Android/gradle_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Android/pipeline.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Android/run_test_on_android_simulator.py (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/asset_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/build_asset_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/build_config.json (98%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/build_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/build_test_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/clean_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/env_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/pipeline.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/python_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Linux/test_linux.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/asset_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/build_asset_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/build_config.json (98%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/build_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/build_test_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/clean_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/env_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/pipeline.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/python_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Mac/test_mac.sh (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/asset_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/build_asset_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/build_config.json (98%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/build_ninja_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/build_test_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/build_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/clean_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/env_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/package_build_config.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/pipeline.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/python_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/Windows/test_windows.cmd (100%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/iOS/build_config.json (98%) rename {Tools/build/JenkinsScripts => scripts}/build/Platform/iOS/pipeline.json (100%) rename {Tools/build/JenkinsScripts => scripts}/build/ci_build.py (98%) rename {Tools/build/JenkinsScripts => scripts}/build/ci_build_metrics.py (99%) rename {Tools/build/JenkinsScripts => scripts}/build/submit_metrics.py (100%) rename {Tools/build/JenkinsScripts/distribution => scripts}/scrubbing/canary.txt (100%) rename {Tools/build/JenkinsScripts/build => scripts/scrubbing}/scrubbing_job.py (78%) rename {Tools/build/JenkinsScripts/distribution => scripts}/scrubbing/validator.py (99%) rename {Tools/build/JenkinsScripts/distribution => scripts}/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py (87%) diff --git a/Tools/build/JenkinsScripts/build/PackageEnv.py b/Tools/build/JenkinsScripts/build/PackageEnv.py deleted file mode 100755 index 88cc41fe1d..0000000000 --- a/Tools/build/JenkinsScripts/build/PackageEnv.py +++ /dev/null @@ -1,193 +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. -# - -from Params import Params -from utils.util import * - - -class PackageEnv(Params): - def __init__(self, target_platform, json_file): - super(PackageEnv, self).__init__() - self.__cur_dir = os.path.dirname(os.path.abspath(__file__)) - with open(json_file, 'r') as source: - self.__data = json.load(source) - self.__platforms = self.__data.get('platforms') - if target_platform not in self.__platforms: - ly_build_error('Target platform {} is not supported'.format(target_platform)) - self.__target_platform = target_platform - - # visited_platform is used to track the platform reference chain, in order to avoid chain cycle. - visited_platform = [target_platform] - platform_env = self.__platforms.get(target_platform) - # If platform_env starts with @, it means that platform_env references another platform - while isinstance(platform_env, str) and platform_env.startswith('@'): - referenced_platform = platform_env.lstrip('@') - if referenced_platform in visited_platform: - ly_build_error('Found reference chain cycle started from {}.\nSee {}'.format(referenced_platform, json_file)) - visited_platform.append(referenced_platform) - platform_env = self.__platforms.get(referenced_platform) - - self.__platform_env = platform_env - self.__global_env = self.__data.get('global') - - def get_target_platform(self): - return self.__target_platform - - def get_global_env(self): - return self.__global_env - - def get_platform_env(self): - return self.__platform_env - - def __get_global_value(self, key): - key = key.upper() - value = self.__global_env.get(key) - if value is None: - ly_build_error('{} is not defined in global env'.format(key)) - return value - - def __get_platform_value(self, key): - key = key.upper() - value = self.__platform_env.get(key) - if value is None: - ly_build_error('{} is not defined in platform env for {}'.format(key, self.__target_platform)) - return value - - def __evaluate_boolean(self, v): - return str(v).lower() in ['1', 'true'] - - def __get_engine_root(self): - def validate_engine_root(engine_root): - if not os.path.isdir(engine_root): - return False - return os.path.exists(os.path.join(engine_root, 'engine.json')) - - # Jenkins only - workspace = os.getenv('WORKSPACE') - if workspace is not None: - print('Environment variable WORKSPACE={} detected'.format(workspace)) - if validate_engine_root(workspace): - print('Setting ENGINE_ROOT to {}'.format(workspace)) - return workspace - engine_root = os.path.join(workspace, 'dev') - if validate_engine_root(engine_root): - print('Setting ENGINE_ROOT to {}'.format(engine_root)) - return engine_root - print('Cannot locate ENGINE_ROOT with Environment variable WORKSPACE') - # End Jenkins only - - engine_root = os.getenv('ENGINE_ROOT', '') - if validate_engine_root(engine_root): - return engine_root - - print('Environment variable ENGINE_ROOT is not set or invalid, checking ENGINE_ROOT in env json file') - engine_root = self.__global_env.get('ENGINE_ROOT') - if validate_engine_root(engine_root): - return engine_root - - # Set engine_root based on script location - engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(self.__cur_dir)))) - print('ENGINE_ROOT from env json file is invalid, defaulting to {}'.format(engine_root)) - if validate_engine_root(engine_root): - return engine_root - else: - error('Cannot Locate ENGINE_ROOT') - - def __get_thirdparty_home(self): - third_party_home = os.getenv('ENV_3RDPARTY_PATH', '') - if os.path.exists(third_party_home): - print('ENV_3RDPARTY_PATH found, using {} as 3rdParty path.'.format(third_party_home)) - return third_party_home - third_party_home = self.__get_global_value('THIRDPARTY_HOME') - if os.path.isdir(third_party_home): - return third_party_home - - # Set engine_root based on script location - print('THIRDPARTY_HOME is not valid, looking for THIRD_PARTY_HOME') - - # Finding THIRD_PARTY_HOME - cur_dir = self.__get_engine_root() - last_dir = None - while last_dir != cur_dir: - third_party_home = os.path.join(cur_dir, '3rdParty') - print('Cheking THIRDPARTY_HOME {}'.format(third_party_home)) - if os.path.exists(os.path.join(third_party_home, '3rdParty.txt')): - print('Setting THIRDPARTY_HOME to {}'.format(third_party_home)) - return third_party_home - last_dir = cur_dir - cur_dir = os.path.dirname(cur_dir) - error('Cannot locate THIRDPARTY_HOME') - - def __get_package_name_pattern(self): - package_name_pattern = self.__get_global_value('PACKAGE_NAME_PATTERN') - if os.getenv('PACKAGE_NAME_PATTERN') is not None: - package_name_pattern = os.getenv('PACKAGE_NAME_PATTERN') - return package_name_pattern - - def __get_build_number(self): - build_number = self.__get_global_value('BUILD_NUMBER') - if os.getenv('BUILD_NUMBER') is not None: - build_number = os.getenv('BUILD_NUMBER') - return build_number - - def __get_p4_changelist(self): - p4_changelist = self.__get_global_value('P4_CHANGELIST') - if os.getenv('P4_CHANGELIST') is not None: - p4_changelist = os.getenv('P4_CHANGELIST') - return p4_changelist - - def __get_major_version(self): - major_version = self.__get_global_value('MAJOR_VERSION') - if os.getenv('MAJOR_VERSION') is not None: - major_version = os.getenv('MAJOR_VERSION') - return major_version - - def __get_minor_version(self): - minor_version = self.__get_global_value('MINOR_VERSION') - if os.getenv('MINOR_VERSION') is not None: - minor_version = os.getenv('MINOR_VERSION') - return minor_version - - def __get_scrub_params(self): - return self.__get_platform_value('SCRUB_PARAMS') - - def __get_validator_platforms(self): - return self.__get_platform_value('VALIDATOR_PLATFORMS') - - def __get_package_targets(self): - return self.__get_platform_value('PACKAGE_TARGETS') - - def __get_build_targets(self): - return self.__get_platform_value('BUILD_TARGETS') - - def __get_asset_processor_path(self): - return self.__get_platform_value('ASSET_PROCESSOR_PATH') - - def __get_asset_game_folders(self): - return self.__get_platform_value('ASSET_GAME_FOLDERS') - - def __get_asset_platform(self): - return self.__get_platform_value('ASSET_PLATFORM') - - def __get_bootstrap_cfg_game_folder(self): - return self.__get_platform_value('BOOTSTRAP_CFG_GAME_FOLDER') - - def __get_run_launcher_unit_test(self): - run_launcher_unit_test = os.getenv('RUN_LAUNCHER_UNIT_TEST') - if run_launcher_unit_test is None: - run_launcher_unit_test = self.__platform_env.get('RUN_LAUNCHER_UNIT_TEST') - return self.__evaluate_boolean(run_launcher_unit_test) - - def __get_skip_build(self): - skip_build = os.getenv('SKIP_BUILD') - if skip_build is None: - skip_build = self.__platform_env.get('SKIP_BUILD') - return self.__evaluate_boolean(skip_build) \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/Params.py b/Tools/build/JenkinsScripts/build/Params.py deleted file mode 100755 index 3b231bdb94..0000000000 --- a/Tools/build/JenkinsScripts/build/Params.py +++ /dev/null @@ -1,81 +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. -# - -from utils.util import * - - -class Params(object): - def __init__(self): - # Cache params - self.__params = {} - - def get(self, param_name): - param_value = self.__params.get(param_name) - if param_value is not None: - return param_value - # Call __get_${param_name} function - func = getattr(self, '_{}__get_{}'.format(self.__class__.__name__, param_name.lower()), None) - if func is not None: - param_value = func() - # Replace all ${env} in value - if isinstance(param_value, str): - param_value = self.__process_string(param_name, param_value) - elif isinstance(param_value, list): - param_value = self.__process_list(param_name, param_value) - elif isinstance(param_value, dict): - param_value = self.__process_dict(param_name, param_value) - # Cache param - self.__params[param_name] = param_value - return param_value - ly_build_error('method __get_{} is not defined in class {}'.format(param_name.lower(), self.__class__.__name__)) - - def set(self, param_name, param_value): - self.__params[param_name] = param_value - - def exists(self, param_name): - try: - self.get(param_name) - except LyBuildError: - return False - return True - - def __process_string(self, param_name, param_value): - # Find all param with format ${param} - params = re.findall('\${(\w+)}', param_value) - # Avoid using the same param name in value, like 'WORKSPACE': '${WORKSPACE} some string' - if param_name in params: - ly_build_error('The use of same parameter name({}) in value is not allowed'.format(param_name)) - # Replace ${param} with actual value - for param in params: - param_value = param_value.replace('${' + param + '}', self.get(param)) - return param_value - - def __process_list(self, param_name, param_value): - processed_list = [] - for entry in param_value: - if isinstance(entry, str): - entry = self.__process_string(param_name, entry) - elif isinstance(entry, list): - entry = self.__process_list(param_name, entry) - elif isinstance(entry, dict): - entry = self.__process_dict(param_name, entry) - processed_list.append(entry) - return processed_list - - def __process_dict(self, param_name, param_value): - for key in param_value: - if isinstance(param_value[key], str): - param_value[key] = self.__process_string(param_name, param_value[key]) - elif isinstance(param_value[key], list): - param_value[key] = self.__process_list(param_name, param_value[key]) - elif isinstance(param_value[key], dict): - param_value[key] = self.__process_dict(param_name, param_value[key]) - return param_value \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/cmake_package.py b/Tools/build/JenkinsScripts/build/cmake_package.py deleted file mode 100755 index 5f9664d2b1..0000000000 --- a/Tools/build/JenkinsScripts/build/cmake_package.py +++ /dev/null @@ -1,358 +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. -# - -import sys -import glob_to_regex -import zipfile -import timeit -import stat -from optparse import OptionParser -from PackageEnv import PackageEnv -from ci_build import build -from utils.util import * -from utils.lib.glob3 import glob - - -def package(options): - package_platform = options.package_platform - package_env = PackageEnv(package_platform, options.package_env) - engine_root = package_env.get('ENGINE_ROOT') - - # Ask the validator code to tell us which files need to be removed from the package - prohibited_file_mask = get_prohibited_file_mask(package_platform, engine_root) - - # Scrub files. This is destructive, but is necessary to allow the current file existance checks to work properly. Better to copy and then build, or to - # mask on sync, but this is what we have for now - # No need to run scrubbing script since all restricted platform codes are moved to dev/restricted folder - #scrub_files(package_env, prohibited_file_mask) - - # validate files - validate_restricted_files(package_platform, package_env) - - # Override values in bootstrap.cfg for PC package - override_bootstrap_cfg(package_env) - - # Generate GameTemplates whitelist information for metrics reporting - template_whitelist_script = os.path.join(engine_root, 'Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/buildGameTemplateWhitelist.py') - if os.path.exists(template_whitelist_script): - if sys.platform == 'win32': - python = os.path.join(engine_root, 'Tools', 'Python', 'python.cmd') - else: - python = os.path.join(engine_root, 'Tools', 'Python', 'python.sh') - project_templates_folder = os.path.join(engine_root, 'ProjectTemplates') - args = [python, template_whitelist_script, '--projectTemplatesFolder', project_templates_folder] - #execute_system_call(args) - - if not package_env.get('SKIP_BUILD'): - print('SKIP_BUILD is False, running CMake build...') - cmake_build(package_env) - - # TODO Compile Assets - #if package_env.exists('ASSET_PROCESSOR_PATH'): - # compile_assets(package_env) - - #create packages - create_packages(package_env) - - -def override_bootstrap_cfg(package_env): - print('Override values in bootstrap.cfg') - engine_root = package_env.get('ENGINE_ROOT') - bootstrap_path = os.path.join(engine_root, 'bootstrap.cfg') - replace_values = {'project_path':'{}'.format(package_env.get('BOOTSTRAP_CFG_GAME_FOLDER'))} - try: - with open(bootstrap_path, 'r') as bootstrap_cfg: - content = bootstrap_cfg.read() - except: - error('Cannot read file {}'.format(bootstrap_path)) - content = content.split('\n') - new_content = [] - for line in content: - if not line.startswith('--'): - strs = line.split('=') - if len(strs): - key = strs[0].strip(' ') - if key in replace_values: - line = '{}={}'.format(key, replace_values[key]) - new_content.append(line) - try: - with open(bootstrap_path, 'w') as out: - out.write('\n'.join(new_content)) - except: - error('Cannot write to file {}'.format(bootstrap_path)) - print('{} updated with value {}'.format(bootstrap_path, replace_values)) - - -def get_prohibited_file_mask(package_platform, engine_root): - sys.path.append(os.path.join(engine_root, 'Tools', 'build', 'JenkinsScripts', 'distribution', 'scrubbing')) - from validator_data_LEGAL_REVIEW_REQUIRED import get_prohibited_platforms_for_package - - # The list of prohibited platforms is controlled by the validator on a per-package basis - prohibited_platforms = get_prohibited_platforms_for_package(package_platform) - prohibited_platforms.append('all') - excludes_list = [] - for p in prohibited_platforms: - platform_excludes = glob_to_regex.generate_excludes_for_platform(engine_root, p) - excludes_list.extend(platform_excludes) - prohibited_file_mask = re.compile('|'.join(excludes_list), re.IGNORECASE) - return prohibited_file_mask - - -def scrub_files(package_env, prohibited_file_mask): - print('Perform the Code Scrubbing') - engine_root = package_env.get('ENGINE_ROOT') - - success = True - for dirname, subFolders, files in os.walk(engine_root): - for filename in files: - full_path = os.path.join(dirname, filename) - if prohibited_file_mask.match(full_path): - try: - print('Deleting: {}'.format(full_path)) - os.chmod(full_path, stat.S_IWRITE) - os.unlink(full_path) - except: - e = sys.exc_info()[0] - sys.stderr.write('Error: could not delete {} ... aborting.\n'.format(full_path)) - sys.stderr.write('{}\n'.format(str(e))) - success = False - if not success: - sys.stderr.write('ERROR: scrub_files failed\n') - sys.exit(1) - - -def validate_restricted_files(package, package_env): - print('Perform the Code Scrubbing') - engine_root = package_env.get('ENGINE_ROOT') - - # Run validator - success = True - validator_path = os.path.join(engine_root, 'Tools/build/JenkinsScripts/distribution/scrubbing/validator.py') - if sys.platform == 'win32': - python = os.path.join(engine_root, 'Tools', 'Python', 'python3.cmd') - else: - python = os.path.join(engine_root, 'Tools', 'Python', 'python3.sh') - args = [python, validator_path, '--package', package, engine_root] - return_code = safe_execute_system_call(args) - if return_code != 0: - success = False - if not success: - error('Restricted file validator failed.') - print('Restricted file validator completed successfully.') - - -def cmake_build(package_env): - build_targets = package_env.get('BUILD_TARGETS') - for build_target in build_targets: - build(build_target['BUILD_CONFIG_FILENAME'], build_target['PLATFORM'], build_target['TYPE']) - - -def create_packages(package_env): - package_targets = package_env.get('PACKAGE_TARGETS') - for package_target in package_targets: - print('Creating zipfile for package target {}'.format(package_target)) - cur_dir = os.path.dirname(os.path.abspath(__file__)) - filelist = os.path.join(cur_dir, 'package_filelists', '{}.json'.format(package_target['TYPE'])) - with open(filelist, 'r') as source: - data = json.load(source) - lyengine = os.path.dirname(package_env.get('ENGINE_ROOT')) - print('Calculating filelists...') - files = {} - # We have to include 3rdParty in Mac/Console packages until LAD is available for those platforms - # Remove this when LAD is available for those platforms. - if package_target['TYPE'] in ['cmake_consoles', 'consoles']: - files.update(get_3rdparty_filelist(package_env, 'common')) - files.update(get_3rdparty_filelist(package_env, 'vc141')) - files.update(get_3rdparty_filelist(package_env, 'vc142')) - files.update(get_3rdparty_filelist(package_env, 'provo')) - elif package_target['TYPE'] in ['cmake_atom_pc']: - files.update(get_3rdparty_filelist(package_env, 'common')) - files.update(get_3rdparty_filelist(package_env, 'vc141')) - files.update(get_3rdparty_filelist(package_env, 'vc142')) - elif package_target['TYPE'] in ['cmake_all']: - if package_env.get_target_platform() == 'mac': - files.update(get_3rdparty_filelist(package_env, 'common')) - files.update(get_3rdparty_filelist(package_env, 'mac')) - elif package_env.get_target_platform() == 'consoles': - files.update(get_3rdparty_filelist(package_env, 'common')) - files.update(get_3rdparty_filelist(package_env, 'vc141')) - files.update(get_3rdparty_filelist(package_env, 'vc142')) - files.update(get_3rdparty_filelist(package_env, 'provo')) - - if '@lyengine' in data: - if '@engine_root' in data['@lyengine']: - engine_root_basename = os.path.basename(package_env.get('ENGINE_ROOT')) - data['@lyengine'][engine_root_basename] = data['@lyengine']['@engine_root'] - data['@lyengine'].pop('@engine_root') - files.update(filter_files(data['@lyengine'], lyengine)) - if '@3rdParty' in data: - files.update(filter_files(data['@3rdParty'], package_env.get('THIRDPARTY_HOME'))) - package_path = os.path.join(lyengine, package_target['PACKAGE_NAME']) - print('Creating zipfile at {}'.format(package_path)) - start = timeit.default_timer() - - with zipfile.ZipFile(package_path, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as myzip: - for f in files: - if os.path.islink(f): - zipInfo = zipfile.ZipInfo(files[f]) - zipInfo.create_system = 3 - # long type of hex val of '0xA1ED0000L', - # say, symlink attr magic... - #zipInfo.external_attr = 0xA1ED0000L - zipInfo.external_attr |= 0xA0000000 - myzip.writestr(zipInfo, os.readlink(f)) - else: - myzip.write(f, files[f]) - - stop = timeit.default_timer() - total_time = int(stop - start) - print('{} is created. Total time: {} seconds.'.format(package_path, total_time)) - - def get_MD5(file_path): - from hashlib import md5 - chunk_size = 200 * 1024 - h = md5() - with open(file_path, 'rb') as f: - while True: - chunk = f.read(chunk_size) - if len(chunk): - h.update(chunk) - else: - break - return h.hexdigest() - - md5_file = '{}.MD5'.format(package_path) - print('Creating MD5 file at {}'.format(md5_file)) - start = timeit.default_timer() - with open(md5_file, 'w') as output: - output.write(get_MD5(package_path)) - stop = timeit.default_timer() - total_time = int(stop - start) - print('{} is created. Total time: {} seconds.'.format(md5_file, total_time)) - - -def filter_files(data, base, prefix='', support_symlinks=True): - includes = {} - excludes = set() - for key, value in data.items(): - pattern = os.path.join(base, prefix, key) - if not isinstance(value, dict): - pattern = os.path.normpath(pattern) - result = glob(pattern, recursive=True) - files = [x for x in result if os.path.isfile(x) or (support_symlinks and os.path.islink(x))] - if value == "#exclude": - excludes.update(files) - elif value == "#include": - for file in files: - includes[file] = os.path.relpath(file, base) - else: - if value.startswith('#move:'): - for file in files: - file_name = os.path.relpath(file, os.path.join(base, prefix)) - dst_dir = value.replace('#move:', '').strip(' ') - includes[file] = os.path.join(dst_dir, file_name) - elif value.startswith('#rename:'): - for file in files: - dst_file = value.replace('#rename:', '').strip(' ') - includes[file] = dst_file - else: - warn('Unknown directive {} for pattern {}'.format(value, pattern)) - else: - includes.update(filter_files(value, base, os.path.join(prefix, key), support_symlinks)) - - for exclude in excludes: - try: - includes.pop(exclude) - except KeyError: - pass - return includes - - -def get_3rdparty_filelist(package_env, platform, support_symlinks=True): - engine_root = package_env.get('ENGINE_ROOT') - include_pattern_file = 'include_pattern_file' - if os.path.isfile(include_pattern_file): - os.remove(include_pattern_file) - exclude_pattern_file = 'exclude_pattern_file' - if os.path.isfile(exclude_pattern_file): - os.remove(exclude_pattern_file) - versions_file = 'versions_file' - if os.path.isfile(versions_file): - os.remove(versions_file) - - # Generate 3rdParty version file - ly_dep_version_tool = os.path.join(engine_root, 'Tools/build/JenkinsScripts/distribution/ly_dep_version_tool.py') - setup_assistant_config = os.path.join(engine_root, 'SetupAssistantConfig.json') - if sys.platform == 'win32': - python = os.path.join(engine_root, 'Tools', 'Python', 'python.cmd') - else: - python = os.path.join(engine_root, 'Tools', 'Python', 'python.sh') - args = [python, ly_dep_version_tool, '-o', versions_file, '-s', setup_assistant_config] - execute_system_call(args) - - # Generate 3rdParty include pattern and exclude pattern - generate_external_3rdparty_file_list = os.path.join(engine_root, 'Tools/build/JenkinsScripts/distribution/ThirdParty/generate_external_3rdparty_file_list.py') - package_config = os.path.join(engine_root, 'Tools/build/JenkinsScripts/distribution/ThirdParty/CMakePackageConfig.json') - args = [python, generate_external_3rdparty_file_list, '-s', versions_file, '-c', package_config, '-p', platform, '-i', include_pattern_file, '-e', exclude_pattern_file] - execute_system_call(args) - - # Calculate filelist using include pattern and exclude pattern - thirdparty_home = package_env.get('THIRDPARTY_HOME') - filelist = {} - with open(include_pattern_file, 'r') as source: - include_patterns = source.readlines() - for include_pattern in include_patterns: - pattern = os.path.join(thirdparty_home, include_pattern.strip('\n')) - pattern = os.path.normpath(pattern) - result = glob(pattern, recursive=True) - files = [x for x in result if os.path.isfile(x) or (support_symlinks and os.path.islink(x))] - for file in files: - filelist[file] = os.path.join('3rdParty', os.path.relpath(file, thirdparty_home)) - - with open(exclude_pattern_file, 'r') as source: - exclude_patterns = source.readlines() - for exclude_pattern in exclude_patterns: - pattern = os.path.join(thirdparty_home, exclude_pattern.strip('\n')) - pattern = os.path.normpath(pattern) - result = glob(pattern, recursive=True) - files = [x for x in result if os.path.isfile(x) or (support_symlinks and os.path.islink(x))] - for file in files: - try: - filelist.pop(file) - except KeyError: - pass - return filelist - - -def parse_args(): - cur_dir = os.path.dirname(os.path.abspath(__file__)) - parser = OptionParser() - parser.add_option("--release", dest="release", default=False, action='store_true', help="Release build") - parser.add_option("--package_platform", dest="package_platform", default='consoles', help="Target platform to package") - parser.add_option("--package_env", dest="package_env", default=os.path.join(cur_dir, "cmake_package_env.json"), - help="JSON file that defines package environment variables") - parser.add_option("--package_build_configurations_json", dest="package_build_configurations_json", - default=os.path.join(cur_dir, "package_build_configurations.json"), - help="JSON file that defines build parameters") - (options, args) = parser.parse_args() - - if options.package_platform is None: - error('No package platform specified') - return options, args - - -if __name__ == "__main__": - (options, args) = parse_args() - package(options) - - - - diff --git a/Tools/build/JenkinsScripts/build/cmake_package_env.json b/Tools/build/JenkinsScripts/build/cmake_package_env.json deleted file mode 100644 index cd22a88e91..0000000000 --- a/Tools/build/JenkinsScripts/build/cmake_package_env.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "global":{ - "ENGINE_ROOT":"", - "THIRDPARTY_HOME":"", - "PACKAGE_NAME_PATTERN":"lumberyard-${MAJOR_VERSION}.${MINOR_VERSION}-${P4_CHANGELIST}", - "BUILD_NUMBER":"0", - "P4_CHANGELIST":"0", - "MAJOR_VERSION":"0", - "MINOR_VERSION":"0", - "LAD_PACKAGE_STORAGE_URL":"https://d7qxx8qkrwa8l.cloudfront.net" - }, - "platforms":{ - "consoles":{ - "PACKAGE_TARGETS":[ - { - "TYPE": "cmake_all", - "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-consoles-${BUILD_NUMBER}.zip" - }, - { - "TYPE": "symbols", - "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-consoles-symbols-${BUILD_NUMBER}.zip" - } - ], - "BOOTSTRAP_CFG_GAME_FOLDER":"AutomatedTesting", - "SKIP_BUILD": 1, - "BUILD_TARGETS":[ - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "Windows", - "TYPE": "profile_vs2017" - }, - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "Windows", - "TYPE": "profile_vs2019" - }, - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "Provo", - "TYPE": "profile" - } - ] - }, - "cmake_atom_pc":{ - "PACKAGE_TARGETS":[ - { - "TYPE": "cmake_atom_pc", - "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-cmake_atom_pc-${BUILD_NUMBER}.zip" - } - ], - "BOOTSTRAP_CFG_GAME_FOLDER":"AtomSampleViewer;AtomTest", - "SKIP_BUILD": 1, - "BUILD_TARGETS":[ - { - "BUILD_CONFIG_FILENAME": "package_build_config.json", - "PLATFORM": "Windows", - "TYPE": "profile_vs2017_atom" - }, - { - "BUILD_CONFIG_FILENAME": "package_build_config.json", - "PLATFORM": "Windows", - "TYPE": "profile_vs2019_atom" - } - ] - }, - "mac":{ - "PACKAGE_TARGETS":[ - { - "TYPE": "cmake_all", - "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-cmake_mac_all-${BUILD_NUMBER}.zip" - } - ], - "BOOTSTRAP_CFG_GAME_FOLDER":"AutomatedTesting", - "SKIP_BUILD": 1, - "BUILD_TARGETS":[ - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "Mac", - "TYPE": "profile" - }, - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "iOS", - "TYPE": "profile" - } - ] - }, - "linux":{ - "PACKAGE_TARGETS":[ - { - "TYPE": "cmake_all", - "PACKAGE_NAME": "${PACKAGE_NAME_PATTERN}-cmake_linux_all-${BUILD_NUMBER}.zip" - } - ], - "BOOTSTRAP_CFG_GAME_FOLDER":"AutomatedTesting", - "SKIP_BUILD": 1, - "BUILD_TARGETS":[ - { - "BUILD_CONFIG_FILENAME": "build_config.json", - "PLATFORM": "Linux", - "TYPE": "profile" - } - ] - } - } -} diff --git a/Tools/build/JenkinsScripts/build/download_latest_package_from_bucket.py b/Tools/build/JenkinsScripts/build/download_latest_package_from_bucket.py deleted file mode 100755 index bc3043a50f..0000000000 --- a/Tools/build/JenkinsScripts/build/download_latest_package_from_bucket.py +++ /dev/null @@ -1,80 +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. - -Downloads the latest package from a S3 and unzips it to a desired location. -""" -import argparse -import boto3 -import os -import re -import zipfile - - -def download_and_unzip_package(bucket_name, package_regex, build_number_regex, folder_path, destination_path): - """ - Downloads a given package from a S3 and unzips it. - :param bucket_name: S3 bucket - :param package_regex: Regex to find the desired package - :param build_number_regex: Regex to find the build number from the package name - :param folder_path: Folder path to the package - :param destination_path: Where to download the package to - :return: - """ - # Make sure the directory exists - if not os.path.isdir(destination_path): - os.makedirs(destination_path) - - # Sorting function for latest package - def get_build_number(file_name_to_parse): - return re.search(build_number_regex, file_name_to_parse).group(0)[:-4] # [:-4] removes the .zip extension - - s3 = boto3.resource('s3') - bucket = s3.Bucket(bucket_name) - largest_build_number = -1 - latest_file = 'No file found!' - # Find the latest package - print 'Reading files from bucket...' - for bucket_file in bucket.objects.filter(Prefix=folder_path): - file_name = bucket_file.key - if re.search(package_regex, file_name) and get_build_number(file_name) > largest_build_number: - largest_build_number = get_build_number(file_name) - latest_file = file_name - - package_name = latest_file.split('/')[-1] - - # Download the package - print('Downloading package: {0} from bucket {1} to {2}'.format(latest_file, bucket_name, destination_path)) - s3.Bucket(bucket_name).download_file(latest_file, os.path.join(destination_path, package_name)) - - # Unzip the package - with zipfile.ZipFile(os.path.join(destination_path, package_name), 'r') as zip_ref: - print('Unzipping package: {0} to {1}'.format(package_name, destination_path)) - zip_ref.extractall(destination_path) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-b', '--bucket_name', required=True, help='Bucket that holds the package.') - parser.add_argument('-p', '--package_regex', required=True, - help='Regex to identify a package. Such as: lumberyard-0.0-[\d]{6,7}-pc-[\d]{4}.zip\s to find ' - 'the main pc package.') - parser.add_argument('-n', '--build_number_regex', required=True, - help='Regex to identify the build number. Such as [\d]{4,5}.zip$ to find the build number from ' - 'the name of the main pc package') - parser.add_argument('-d', '--destination_path', required=True, help='Destination for the contents of the packages.') - parser.add_argument('-f', '--folder_path', help='Folder that contains the package, must include /.') - - args = parser.parse_args() - download_and_unzip_package(args.bucket_name, args.package_regex, args.build_number_regex, args.folder_path, - args.destination_path) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/download_packages.py b/Tools/build/JenkinsScripts/build/download_packages.py deleted file mode 100755 index a26fa90b43..0000000000 --- a/Tools/build/JenkinsScripts/build/download_packages.py +++ /dev/null @@ -1,55 +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. - -Downloads packages and unzips them. -""" -import argparse -import boto3 -import os -import zipfile - - -def download_and_unzip_packages(bucket_name, package_key, folder_path, destination_path): - """ - Downloads a given package from a S3 and unzips it. - :param bucket_name: S3 bucket - :param package_key: Key for the package - :param folder_path: Folder path to the package - :param destination_path: Where to download the package to - :return: - """ - # Make sure the directory exists - if not os.path.isdir(destination_path): - os.makedirs(destination_path) - - # Download the package - s3 = boto3.resource('s3') - print('Downloading package: {0} from bucket {1} to {2}'.format(package_key, bucket_name, destination_path)) - s3.Bucket(bucket_name).download_file(folder_path + package_key, os.path.join(destination_path, package_key)) - - # Unzip the package - with zipfile.ZipFile(os.path.join(destination_path, package_key), 'r') as zip_ref: - print('Unzipping package: {0} to {1}'.format(package_key, destination_path)) - zip_ref.extractall(destination_path) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-b', '--bucket_name', required=True, help='Bucket that holds the package.') - parser.add_argument('-p', '--package_key', required=True, help='Desired package\'s key.') - parser.add_argument('-d', '--destination_path', required=True, help='Destination for the contents of the packages.') - parser.add_argument('-f', '--folder_path', help='Folder that contains the package, must include /.') - - args = parser.parse_args() - download_and_unzip_packages(args.bucket_name, args.package_key, args.folder_path, args.destination_path) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/jenkins_scm_metrics.py b/Tools/build/JenkinsScripts/build/jenkins_scm_metrics.py deleted file mode 100755 index 0a62bfe40f..0000000000 --- a/Tools/build/JenkinsScripts/build/jenkins_scm_metrics.py +++ /dev/null @@ -1,57 +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. -""" - -''' -All this script is doing is writing grabbing a file that was written previously marking the start of when the Perforce would run -and then getting the current time to find out how long we spent in Perforce -''' - -import time - -from utils.util import * - - -def write_metrics(): - enable_build_metrics = os.environ.get('ENABLE_BUILD_METRICS') - metrics_namespace = os.environ.get('METRICS_NAMESPACE') - if enable_build_metrics == 'true': - scm_end = int(time.time()) - workspace = os.environ.get('WORKSPACE') - metrics_file_name = 'scm_start.txt' - if workspace is None: - safe_exit_with_error('{} must be run in Jenkins job.'.format(os.path.basename(__file__))) - try: - with open(os.path.join(workspace, metrics_file_name), 'r') as f: - scm_start = int(f.readline()) - except: - safe_exit_with_error('Failed to read from {}'.format(metrics_file_name)) - - scm_total = scm_end - scm_start - - script_path = os.path.join(workspace, 'dev/Tools/build/waf-1.7.13/build_metrics/write_build_metric.py') - - build_tag = os.environ.get('BUILD_TAG') - p4_changelist = os.environ.get('P4_CHANGELIST') - - if build_tag is not None and p4_changelist is not None: - os.environ['BUILD_ID'] = '{0}.{1}'.format(build_tag, p4_changelist) - - cwd = os.getcwd() - os.chdir(os.path.join(workspace, 'dev')) - cmd = 'python {} SCMTime {} Seconds --enable-build-metrics {} --metrics-namespace {} --project-spec None'.format(script_path, scm_total, True, metrics_namespace) - # metrics call shouldn't fail the job - safe_execute_system_call(cmd, shell=True) - os.chdir(cwd) - - -if __name__ == "__main__": - write_metrics() diff --git a/Tools/build/JenkinsScripts/build/utils/__init__.py b/Tools/build/JenkinsScripts/build/utils/__init__.py deleted file mode 100755 index e912252f4e..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/__init__.py +++ /dev/null @@ -1,12 +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. -""" - diff --git a/Tools/build/JenkinsScripts/build/utils/copy_LAD_3rdParty.xml b/Tools/build/JenkinsScripts/build/utils/copy_LAD_3rdParty.xml deleted file mode 100644 index 6bd9be6198..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/copy_LAD_3rdParty.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/utils/download_from_s3.py b/Tools/build/JenkinsScripts/build/utils/download_from_s3.py deleted file mode 100755 index 2fe5d315a2..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/download_from_s3.py +++ /dev/null @@ -1,102 +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. -""" - -''' -Usage: -Use EC2 role to download files to %WORKSPACE% folder from bucket bucket_name: -python download_from_s3.py --base_dir %WORKSPACE% --files_to_download "file1,file2" --bucket bucket_name - -Use profile to download files to %WORKSPACE% folder from bucket bucket_name: -python download_from_s3.py --base_dir %WORKSPACE% --profile profile --files_to_download "file1,file2" --bucket bucket_name -''' - - -import os -import json -import boto3 -from optparse import OptionParser -from util import error - - -def parse_args(): - parser = OptionParser() - parser.add_option("--base_dir", dest="base_dir", default=os.getcwd(), help="Base directory to download files, If not given, then current directory is used.") - parser.add_option("--files_to_download", dest="files_to_download", default=None, help="Files to download, separated by comma.") - parser.add_option("--profile", dest="profile", default=None, help="The name of a profile to use. If not given, then the default profile is used.") - parser.add_option("--bucket", dest="bucket", default=None, help="S3 bucket the files are downloaded from.") - parser.add_option("--key_prefix", dest="key_prefix", default='', help="Object key prefix.") - ''' - ExtraArgs used to call s3.download_file(), should be in json format. extra_args key must be one of: ACL, CacheControl, ContentDisposition, ContentEncoding, ContentLanguage, ContentType, Expires, - GrantFullControl, GrantRead, GrantReadACP, GrantWriteACP, Metadata, RequestPayer, ServerSideEncryption, StorageClass, - SSECustomerAlgorithm, SSECustomerKey, SSECustomerKeyMD5, SSEKMSKeyId, WebsiteRedirectLocation - ''' - parser.add_option("--extra_args", dest="extra_args", default=None, help="Additional parameters used to download file.") - parser.add_option("--max_retry", dest="max_retry", default=1, help="Maximum retry times to download file.") - (options, args) = parser.parse_args() - if not os.path.isdir(options.base_dir): - error('{} is not a valid directory'.format(options.base_dir)) - if not options.files_to_download: - error('Use --files_to_download to specify files to download, separated by comma.') - if not options.bucket: - error('Use --bucket to specify bucket that the files are downloaded from.') - return options - - -def get_client(service_name, profile_name=None): - session = boto3.session.Session(profile_name=profile_name) - client = session.client(service_name) - return client - - -def s3_download_file(client, base_dir, file, bucket, key_prefix=None, extra_args=None, max_retry=1): - print 'Downloading file {} from bucket {}.'.format(file, bucket) - key = file if key_prefix is None else '{}/{}'.format(key_prefix, file) - for x in range(max_retry): - try: - client.download_file( - bucket, key, os.path.join(base_dir, file), - ExtraArgs=extra_args - ) - print 'Download succeeded' - return True - except: - print 'Retrying download...' - print 'Download failed' - return False - - -def download_files(base_dir, files_to_download, bucket, key_prefix=None, profile=None, extra_args=None, max_retry=1): - client = get_client('s3', profile) - files_to_download = files_to_download.split(',') - extra_args = json.loads(extra_args) if extra_args else None - - print 'Downloading {} files from bucket {}.'.format(len(files_to_download), bucket) - failure = [] - success = [] - for file in files_to_download: - if not s3_download_file(client, base_dir, file, bucket, key_prefix, extra_args, max_retry): - failure.append(file) - else: - success.append(file) - print '{} files are downloaded successfully:'.format(len(success)) - print '\n'.join(success) - print '{} files failed to download:'.format(len(failure)) - print '\n'.join(failure) - # Exit with error code 1 if any file is failed to download - if len(failure) > 0: - return False - return True - - -if __name__ == "__main__": - options = parse_args() - download_files(options.base_dir, options.files_to_download, options.bucket, options.key_prefix, options.profile, options.extra_args, options.max_retry) diff --git a/Tools/build/JenkinsScripts/build/utils/email_to_lionbridge.py b/Tools/build/JenkinsScripts/build/utils/email_to_lionbridge.py deleted file mode 100755 index 20cbed1185..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/email_to_lionbridge.py +++ /dev/null @@ -1,129 +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. -""" - -""" -This script will be used in https://jenkins.agscollab.com/view/%7ESandbox/job/PACKAGE_COPY_S3/ -PACKAGE_COPY_S3 is a downstream job of nightly packaging job, it copies the nightly packages from Infra S3 bucket to Lionbridge S3 bucket based on the INCLUDE_FILTER passed from packaging job -""" -import os -import re -import json -import requests -from requests.auth import HTTPBasicAuth -import boto3 -from util import error, warn - - -# Write EMAIL_TEMPLATE to a file and inject it into the email sent to Lionbridge -EMAIL_TEMPLATE = '''Packages are uploaded to S3 bucket {} -Package List: -{} - - -Changelists: -{} -''' - - -def get_jenkins_env(key): - try: - return os.environ[key] - except KeyError: - print 'Error: Jenkins parameters {} is not set.'.format(key) - return None - - -JENKINS_USERNAME = get_jenkins_env('JENKINS_USERNAME') -JENKINS_API_TOKEN = get_jenkins_env('JENKINS_API_TOKEN') -JENKINS_URL = get_jenkins_env('JENKINS_URL') -WORKSPACE = get_jenkins_env('WORKSPACE') -S3_TARGET = get_jenkins_env('S3_TARGET') -INCLUDE_FILTER = get_jenkins_env('INCLUDE_FILTER') -EMAIL_TEMPLATE_FILE = get_jenkins_env('EMAIL_TEMPLATE_FILE') -if None in [JENKINS_USERNAME, JENKINS_API_TOKEN, JENKINS_URL, WORKSPACE, S3_TARGET, INCLUDE_FILTER, EMAIL_TEMPLATE_FILE]: - error('Please make sure all Jenkins parameters are set correctly.') - - -def parse_include_filter(include_filter): - try: - res = re.search('^(\w*)-*lumberyard-(\d+)\.(\d+)-(\d+)-(\w+).*\*(\d+)\.\*', include_filter) - branch = res.group(1) - major_version = int(res.group(2)) - minor_version = int(res.group(3)) - changelist_number = res.group(4) - platform = res.group(5) - build_number = res.group(6) - return branch, major_version, minor_version, changelist_number, platform, build_number - except (AttributeError, IndexError): - error('Unable to parse INCLUDE_FILTER, please make sure the INCLUDE_FILTER is set correctly') - - -# Get the changelists that trigger the build -def get_changelists(job_name, build_number): - changelists = [] - headers = {'Content-type': 'application/json', 'Accept': 'application/json'} - try: - res = requests.get('{}/job/{}/{}/api/json'.format(JENKINS_URL, job_name, build_number), - auth=HTTPBasicAuth(JENKINS_USERNAME, JENKINS_API_TOKEN), headers=headers, verify=False) - res = json.loads(res.content) - changelists = res.get('changeSet').get('items') - return changelists - except: - warn('Error: Failed to get changes from build {} in job {}'.format(build_number, job_name)) - return [] - - -def get_packaging_job_name(branch, major_version, minor_version, platform): - if branch == '': - branch = 'ML' if major_version + minor_version == 0 else 'v{}_{}'.format(major_version, minor_version) - job_name = 'PKG_{}_{}'.format(branch, platform.capitalize()) - return job_name - - -# Get package names by looking up S3 bucket -def get_package_names(branch, major_version, minor_version, include_filter, build_number): - package_names = [] - prefix = include_filter[:include_filter.find('*')] - pattern = '.*{}.*{}..*'.format(prefix, build_number) - if branch == '': - bucket_name = 'ly-packages-mainline' if major_version + minor_version == 0 else 'ly-packages-release-candidate' - folder = 'lumberyard-packages' - else: - bucket_name = 'ly-packages-feature-branches' - folder = 'lumberyard-packages/{}'.format(branch) - s3 = boto3.resource('s3') - bucket = s3.Bucket(bucket_name) - for obj in bucket.objects.filter(Prefix='{}/{}'.format(folder, prefix)): - package_name = obj.key - if re.match(pattern, package_name): - package_names.append(package_name.replace('{}/'.format(folder), '')) - return package_names - - -if __name__ == "__main__": - branch, major_version, minor_version, changelist_number, platform, build_number = parse_include_filter(INCLUDE_FILTER) - packaging_job_name = get_packaging_job_name(branch, major_version, minor_version, platform) - changelists = get_changelists(packaging_job_name, build_number) - package_names = get_package_names(branch, major_version, minor_version, INCLUDE_FILTER, build_number) - with open(os.path.join(WORKSPACE, EMAIL_TEMPLATE_FILE), 'w+') as output: - if len(package_names) > 0: - package_list_str = '\n'.join(package_names) - changelists_str = '' - for item in changelists: - changelists_str += '---------------------------------------------------------------------------------------------\n' - try: - changelists_str += 'CL{} by {} on {}\n{}\n'.format(item['changeNumber'], item['author']['fullName'], item['changeTime'], item['msg'].encode('utf-8', 'ignore')) - except KeyError: - error('Internal error, check the output of Jenkins API.') - output.write(EMAIL_TEMPLATE.format(S3_TARGET, package_list_str, changelists_str)) - - diff --git a/Tools/build/JenkinsScripts/build/utils/incremental_build_util.py b/Tools/build/JenkinsScripts/build/utils/incremental_build_util.py deleted file mode 100755 index 36451b2d63..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/incremental_build_util.py +++ /dev/null @@ -1,662 +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. -""" - -import ast -import boto3 -import datetime -import urllib2 -import os -import time -import subprocess -import sys -import tempfile -import traceback -import shutil -import platform -import stat - -IAM_ROLE_NAME = 'ec2-jenkins-node' - -if os.name == 'nt': - import ctypes - import win32api - import collections - import locale - - locale.setlocale(locale.LC_ALL, '') # set locale to default to get thousands separators - - PULARGE_INTEGER = ctypes.POINTER(ctypes.c_ulonglong) # Pointer to large unsigned integer - kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) - kernel32.GetDiskFreeSpaceExW.argtypes = (ctypes.c_wchar_p,) + (PULARGE_INTEGER,) * 3 - - class UsageTuple(collections.namedtuple('UsageTuple', 'total, used, free')): - def __str__(self): - # Add thousands separator to numbers displayed - return self.__class__.__name__ + '(total={:n}, used={:n}, free={:n})'.format(*self) - - def is_dir_symlink(path): - FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 - return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT) - - def get_free_space_mb(path): - if sys.version_info < (3,): # Python 2? - saved_conversion_mode = ctypes.set_conversion_mode('mbcs', 'strict') - else: - try: - path = os.fsdecode(path) # allows str or bytes (or os.PathLike in Python 3.6+) - except AttributeError: # fsdecode() not added until Python 3.2 - pass - - # Define variables to receive results when passed as "by reference" arguments - _, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), ctypes.c_ulonglong() - - success = kernel32.GetDiskFreeSpaceExW( - path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free)) - if not success: - error_code = ctypes.get_last_error() - - if sys.version_info < (3,): # Python 2? - ctypes.set_conversion_mode(*saved_conversion_mode) # restore conversion mode - - if not success: - windows_error_message = ctypes.FormatError(error_code) - raise ctypes.WinError(error_code, '{} {!r}'.format(windows_error_message, path)) - - used = total.value - free.value - - return free.value / 1024 / 1024#for now -else: - def get_free_space_mb(dirname): - st = os.statvfs(dirname) - return st.f_bavail * st.f_frsize / 1024 / 1024 - - -def get_iam_role_credentials(role_name): - security_metadata = None - try: - response = urllib2.urlopen( - 'http://169.254.169.254/latest/meta-data/iam/security-credentials/{0}'.format(role_name)).read() - security_metadata = ast.literal_eval(response) - except: - print 'Unable to get iam role credentials' - print traceback.print_exc() - - return security_metadata - - -def create_volume(ec2_client, availability_zone, project_name, volume_counter): - response = ec2_client.create_volume( - AvailabilityZone=availability_zone, - Size=300, - VolumeType='gp2', - TagSpecifications= - [ - { - 'ResourceType': 'volume', - 'Tags': - [ - { - 'Key': 'Name', - 'Value': '{0}'.format(project_name) - }, - { - 'Key': 'VolumeCounter', - 'Value': str(volume_counter) - } - ] - } - ] - ) - print response - volume_id = response['VolumeId'] - - # give some time for the creation call to complete - time.sleep(1) - - response = ec2_client.describe_volumes(VolumeIds=[volume_id, ]) - while (response['Volumes'][0]['State'] != 'available'): - time.sleep(1) - response = ec2_client.describe_volumes(VolumeIds=[volume_id, ]) - - return volume_id - - -def delete_volume(ec2_client, volume_id): - response = ec2_client.delete_volume(VolumeId=volume_id) - - -def unmount_build_volume_from_node(): - if os.name == 'nt': - f = tempfile.NamedTemporaryFile(delete=False) - f.write(""" - select disk 1 - offline disk - """) - f.close() - - subprocess.call('diskpart /s %s' % f.name) - - os.unlink(f.name) - else: - subprocess.call(['umount', '/data']) - - -def detach_volume_from_node(ec2_client, volume, instance_id, force): - ec2_client.delete_tags(Resources=[volume.volume_id], - Tags=[ - { - 'Key': 'jenkins_attachment_node', - }, - { - 'Key': 'jenkins_attachment_time', - }, - { - 'Key': 'jenkins_attachment_build' - } - ]) - - incremental_keys = ['jenkins_attachment_node', 'jenkins_attachment_time', 'jenkins_attachment_build'] - - volume.load() - - print 'searching for keys adding during incremental build: {}'.format(incremental_keys) - - while len(incremental_keys): - tag_keys = set() - for tag in volume.tags: - tag_keys.add(tag['Key']) - - print 'found tags on instace {}'.format(tag_keys) - - for incremental_key in list(incremental_keys): - if incremental_key not in tag_keys: - print 'incremental key {} has been successfully removed'.format(incremental_key) - incremental_keys.remove(incremental_key) - - volume.load() - - volume.detach_from_instance(Device='xvdf', - Force=force, - InstanceId=instance_id, - VolumeId=volume.volume_id) - - while (len(volume.attachments) and volume.attachments[0]['State'] != 'detached'): - time.sleep(1) - volume.load() - - volume.load() - - if (len(volume.attachments)): - print 'Volume still has attachments' - for attachment in volume.attachments: - print 'Volume {} {} to instance {}'.format(attachment['VolumeId'], attachment['State'], attachment['InstanceId']) - - -def cleanup_node(workspace_name): - if os.name == 'nt': - jenkins_base = os.getenv('BASE') - dev_path = '{}\\workspace\\{}\\dev'.format(jenkins_base, workspace_name) - else: - dev_path = '/home/lybuilder/ly/workspace/{}/dev'.format(workspace_name) - - if os.path.exists(dev_path): - if os.name == 'nt': - if is_dir_symlink(dev_path): - print "removing symlink path {}".format(dev_path) - os.rmdir(dev_path) - else: - # this shouldn't happen, but is here for sanity's sake, if we sync to the build node erroneously we want to clean it up if we can - print "given symlink path was not a symlink, deleting the full tree to prevent future build failures" - retcode = os.system('rmdir /S /Q {}'.format(dev_path)) - if retcode != 0: - raise Exception("rmdir failed to remove directory: {}".format(dev_path)) - return True - else: - if os.path.islink(dev_path): - print "unlinking symlink path {}".format(dev_path) - os.unlink(dev_path) - else: - print "given symlink path was not a symlink, deleting the full tree to prevent future build failures" - os.chmod(dev_path, stat.S_IWUSR) - shutil.rmtree(dev_path, ignore_errors=True) - return True - # check to make sure the directory was actually deleted - if os.path.exists(dev_path): - raise Exception("Failed to remove directory: {}".format(dev_path)) - return False - - -def setup_volume(workspace_name, created): - if os.name == 'nt': - f = tempfile.NamedTemporaryFile(delete=False) - f.write(""" - select disk 1 - online disk - attribute disk clear readonly - """) # assume disk # for now - - if created: - f.write("""create partition primary - select partition 1 - format quick fs=ntfs - assign - active - """) - - f.close() - - subprocess.call(['diskpart', '/s', f.name]) - - time.sleep(2) - - drives_after = win32api.GetLogicalDriveStrings() - drives_after = drives_after.split('\000')[:-1] - - print drives_after - - #drive_letter = next(item for item in drives_after if item not in drives_before) - drive_letter = 'D:\\' - - os.unlink(f.name) - - time.sleep(1) - - dev_path = '{}ly\workspace\{}\dev'.format(drive_letter, workspace_name) - - else: - subprocess.call(['file', '-s', '/dev/xvdf']) - if created: - subprocess.call(['mkfs', '-t', 'ext4', '/dev/xvdf']) - subprocess.call(['mount', '/dev/xvdf', '/data']) - - dev_path = '/data/ly/workspace/{}/dev'.format(workspace_name) - - return dev_path - - -def attach_volume_to_instance(volume, volume_id, instance_id, instance_name): - volume.attach_to_instance(Device='xvdf', - InstanceId=instance_id, - VolumeId=volume_id) - # give a little bit of time for the aws call to process - time.sleep(2) - - # reload the volume just in case - volume.load() - - while (len(volume.attachments) and volume.attachments[0]['State'] != 'attached'): - time.sleep(1) - volume.load() - - volume.create_tags(Tags=[ - { - 'Key':'last_attachment_time', - 'Value':datetime.datetime.utcnow().isoformat() - } - ]) - - volume.create_tags(Tags=[ - { - 'Key':'jenkins_attachment_node', - 'Value':instance_name, - }, - { - 'Key':'jenkins_attachment_time', - 'Value':datetime.datetime.utcnow().isoformat() - }, - { - 'Key':'jenkins_attachment_build', - 'Value':os.getenv('BUILD_TAG') - } - ]) - - -def prepare_incremental_build(workspace_name): - job_name = os.getenv('JOB_NAME', None) - clean_build = os.getenv('CLEAN_BUILD', 'false').lower() == 'true' - - android_home = os.getenv('ANDROID_HOME', None) - if android_home is not None: - path = os.getenv('PATH').split(';') - print path - - java_home = os.getenv('JAVA_HOME', None) - print java_home - - os.environ['LY_NDK_PATH'] = 'C:\\ly\\3rdParty\\android-ndk\\r12' - print os.getenv('LY_NDK_PATH') - - path = [x for x in path if not (java_home in x or android_home in x)] - print path - - path.append(java_home) - path.append(android_home) - path.append(os.getenv('LY_NDK_PATH')) - print path - - os.environ['PATH'] = ';'.join(path) - - credentials = get_iam_role_credentials(IAM_ROLE_NAME) - - aws_access_key_id = None - aws_secret_access_key = None - aws_session_token = None - - if credentials is not None: - keys = ['AccessKeyId', 'SecretAccessKey', 'Token'] - for key in keys: - if key not in credentials: - print 'Unable to find {0} in get_iam_role_credentials response {1}'.format(key, credentials) - return - - aws_access_key_id = credentials['AccessKeyId'] - aws_secret_access_key = credentials['SecretAccessKey'] - aws_session_token = credentials['Token'] - - session = boto3.session.Session() - region = session.region_name - - try: - instance_id = urllib2.urlopen('http://169.254.169.254/latest/meta-data/instance-id').read() - except: - # this likely means we're not an ec2 instance - raise Exception('No EC2 metadata!') - - - try: - availability_zone = urllib2.urlopen( - 'http://169.254.169.254/latest/meta-data/placement/availability-zone').read() - except: - # also likely means we're not an ec2 instance - raise Exception('No EC2 metadata') - - - if region is None: - region = 'us-west-2' - - client = boto3.client('ec2', region_name=region, aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token) - - project_name = job_name - - ec2_resource = boto3.resource('ec2', region_name=region) - instance = ec2_resource.Instance(instance_id) - - volume_counter = 0 - - for volume in instance.volumes.all(): - for attachment in volume.attachments: - print 'attachment device: {}'.format(attachment['Device']) - if 'xvdf' in attachment['Device'] and attachment['State'] != 'detached': - print 'A device is already attached to xvdf. This likely means a previous build failed to detach it\'s' \ - 'build volume. This volume is considered orphaned and will be force detached from this instance.' - unmount_build_volume_from_node() - detach_volume_from_node(client, volume, instance_id, True) - - if cleanup_node(workspace_name): - clean_build = True - - response = client.describe_volumes(Filters= - [ - { - 'Name': 'tag:Name', - 'Values': - [ - '{0}'.format(project_name) - ] - } - ]) - - created = False - - if 'Volumes' in response and not len(response['Volumes']): - print 'Volume for {0} doesn\'t exist creating it...'.format(project_name) - # volume doesn't exist, create it - volume_id = create_volume(client, availability_zone, project_name, volume_counter) - created = True - - elif len(response['Volumes']) > 1: - latest_volume = None - max_counter = 0 - - for volume in response['Volumes']: - for tag in volume['Tags']: - if tag['Key'] == 'VolumeCounter': - if int(tag['Value']) > max_counter: - max_counter = int(tag['Value']) - latest_volume = volume - - volume_counter = max_counter - volume_id = latest_volume['VolumeId'] - else: - volume = response['Volumes'][0] - if len(volume['Attachments']): - # this is bad we shouldn't be attached, we should have detached at the end of a build - attachment = volume['Attachments'][0] - print ('Volume already has attachment {}'.format(attachment)) - print 'Creating new volume for {} and orphaning previous volume'.format(project_name) - - for tag in volume['Tags']: - if tag['Key'] == 'VolumeCounter': - volume_counter = int(tag['Value']) + 1 - break - - volume_id = create_volume(client, availability_zone, project_name, volume_counter) - created = True - else: - volume_id = volume['VolumeId'] - - if clean_build and not created: - print 'CLEAN_BUILD option was set, deleting volume {0}'.format(volume_id) - revert_workspace(job_name) - delete_volume(client, volume_id) - volume_id = create_volume(client, availability_zone, project_name, volume_counter) - created = True - - print 'attaching volume {} to instance {}'.format(volume_id, instance_id) - volume = ec2_resource.Volume(volume_id) - - instance_name = next(tag['Value'] for tag in instance.tags if tag['Key'] == 'Name') - - if os.name == 'nt': - drives_before = win32api.GetLogicalDriveStrings() - drives_before = drives_before.split('\000')[:-1] - - print drives_before - - attach_volume_to_instance(volume, volume_id, instance_id, instance_name) - - dev_path = setup_volume(workspace_name, created) - - dev_existed = True - - if os.name == 'nt': - free_space_path = 'D:\\' - else: - free_space_path = '/data/' - - if get_free_space_mb(free_space_path) < 1024: - print 'Volume is running low on disk space. Recreating volume and running clean build.' - unmount_build_volume_from_node() - detach_volume_from_node(client, volume, instance_id, False) - delete_volume(client, volume_id) - - volume_id = create_volume(client, availability_zone, project_name, volume_counter) - volume = ec2_resource.Volume(volume_id) - attach_volume_to_instance(volume, volume_id, instance_id, instance_name) - setup_volume(workspace_name, True) - - if not os.path.exists(dev_path): - print 'creating directory structure for {}'.format(dev_path) - os.makedirs(dev_path) - if os.name != 'nt': - print 'taking ownership of {}'.format(dev_path) - subprocess.call(['chown', '-R', 'lybuilder:root', dev_path]) - dev_existed = False - - if os.name == 'nt': - jenkins_base = os.getenv('BASE') - try: - symlink_path = '{}\\workspace\\{}\\dev'.format(jenkins_base, workspace_name) - print 'creating symlink to path: {}'.format(symlink_path) - subprocess.call(['cmd', '/c', 'mklink', '/J', symlink_path, dev_path]) - #subprocess.call(['cmd', '/c', 'mklink', '/J', '{}\\3rdParty'.format(jenkins_base), 'E:\\3rdParty']) - except Exception as e: - print e - else: - subprocess.call(['ln', '-s', '-f', dev_path, '/home/lybuilder/ly/workspace/{}'.format(workspace_name)]) - subprocess.call(['ln', '-s', '-f', '/home/lybuilder/ly/workspace/3rdParty', '/data/ly/workspace']) - - if not dev_existed: - print 'flushing perforce #have revision' - subprocess.call(['p4', 'trust']) - subprocess.call(['p4', 'flush', '-f', '//ly_jenkins_{}/dev/...#none'.format(job_name)]) - #subprocess.call(['p4', 'sync', '-f', '//ly_jenkins_{}/dev/...'.format(job_name)]) - - -def revert_workspace(job_name): - try: - # Workaround for LY-86789: Revert bootstrap.cfg checkout. - print "REVERTING workspace {}".format(job_name) - subprocess.check_call(['p4', 'revert', '//ly_jenkins_{}/dev/...'.format(job_name)]) - except subprocess.CalledProcessError as e: - print e.output - raise e - except Exception as e: - print e - raise e - - -def teardown_incremental_build(workspace_name): - job_name = os.getenv('JOB_NAME', None) - - if os.path.isfile('envinject.properties'): - os.remove('envinject.properties') - - credentials = get_iam_role_credentials(IAM_ROLE_NAME) - - aws_access_key_id = None - aws_secret_access_key = None - aws_session_token = None - - if credentials is not None: - keys = ['AccessKeyId', 'SecretAccessKey', 'Token'] - for key in keys: - if key not in credentials: - raise Exception('Unable to find {0} in get_iam_role_credentials response {1}'.format(key, credentials)) - - aws_access_key_id = credentials['AccessKeyId'] - aws_secret_access_key = credentials['SecretAccessKey'] - aws_session_token = credentials['Token'] - - session = boto3.session.Session() - region = session.region_name - - try: - instance_id = urllib2.urlopen('http://169.254.169.254/latest/meta-data/instance-id').read() - except: - # this likely means we're not an ec2 instance - raise Exception('No EC2 metadata!') - - if region is None: - region = 'us-west-2' - - client = boto3.client('ec2', region_name=region, aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token) - - project_name = job_name - response = client.describe_volumes(Filters= - [ - { - 'Name': 'tag:Name', - 'Values': - [ - '{0}'.format(project_name) - ] - } - ]) - - ec2_resource = boto3.resource('ec2', region_name=region) - instance = ec2_resource.Instance(instance_id) - - volume = None - - for attached_volume in instance.volumes.all(): - for attachment in attached_volume.attachments: - print 'attachment device: {}'.format(attachment['Device']) - if attachment['Device'] == 'xvdf': - volume = attached_volume - - if volume is None: - # volume doesn't exist, do nothing - print 'Volume for {} does not exist or is not attached to the current instance. This probably isn\'t an issue but should be reported.'.format(project_name) - return - else: - revert_workspace(job_name) - - unmount_build_volume_from_node() - - detach_volume_from_node(client, volume, instance_id, False) - - cleanup_node(workspace_name) - - -def prepare_incremental_build_mac(workspace_name): - job_name = os.getenv('JOB_NAME', None) - clean_build = os.getenv('CLEAN_BUILD', 'false').lower() == 'true' - - subprocess.call(['mount', '-t', 'smbfs', '//lybuilder:Builder99@gt-sna11-nas-01.local/inc-build/ly', '/data/ly']) - - dev_path = '/data/ly/workspace/{}/dev'.format(workspace_name) - - dev_existed = True - - if clean_build: - print 'cleaning {}'.format(dev_path) - subprocess.call(['rm', '-rf', dev_path]) - if not os.path.exists(dev_path): - print 'creating directory structure for {}'.format(dev_path) - os.makedirs(dev_path) - dev_existed = False - - #subprocess.call(['ln', '-s', '-f', '/data/ly/workspace', '/Users/lybuilder']) - - #subprocess.call(['ln', '-s', '-f', '/Users/lybuilder/workspace/3rdParty', '/data/ly/workspace']) - - if not dev_existed: - print 'flushing perforce #have revision' - subprocess.call(['p4', 'trust']) - subprocess.call(['p4', 'flush', '-f', '//ly_jenkins_{}/dev/...#none'.format(job_name)]) - - -def main(): - action = sys.argv[1] - workspace_name = sys.argv[2] - - if action.lower() == 'prepare': - if platform.system().lower() == 'darwin': - prepare_incremental_build_mac(workspace_name) - else: - prepare_incremental_build(workspace_name) - elif action.lower() == 'teardown': - if platform.system().lower() == 'darwin': - pass - else: - teardown_incremental_build(workspace_name) - else: - 'Invalid command. Valid actions are either "prepare" or "teardown."' - - -if __name__ == '__main__': - main() diff --git a/Tools/build/JenkinsScripts/build/utils/jenkins_scm_metrics.py b/Tools/build/JenkinsScripts/build/utils/jenkins_scm_metrics.py deleted file mode 100755 index 3e91f13264..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/jenkins_scm_metrics.py +++ /dev/null @@ -1,57 +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. -""" - -''' -All this script is doing is writing grabbing a file that was written previously marking the start of when the Perforce would run -and then getting the current time to find out how long we spent in Perforce -''' - -import time - -from util import * - - -def write_metrics(): - enable_build_metrics = os.environ.get('ENABLE_BUILD_METRICS') - metrics_namespace = os.environ.get('METRICS_NAMESPACE') - if enable_build_metrics == 'true': - scm_end = int(time.time()) - workspace = os.environ.get('WORKSPACE') - metrics_file_name = 'scm_start.txt' - if workspace is None: - safe_exit_with_error('{} must be run in Jenkins job.'.format(os.path.basename(__file__))) - try: - with open(os.path.join(workspace, metrics_file_name), 'r') as f: - scm_start = int(f.readline()) - except: - safe_exit_with_error('Failed to read from {}'.format(metrics_file_name)) - - scm_total = scm_end - scm_start - - script_path = os.path.join(workspace, 'dev/Tools/build/waf-1.7.13/build_metrics/write_build_metric.py') - - build_tag = os.environ.get('BUILD_TAG') - p4_changelist = os.environ.get('P4_CHANGELIST') - - if build_tag is not None and p4_changelist is not None: - os.environ['BUILD_ID'] = '{0}.{1}'.format(build_tag, p4_changelist) - - cwd = os.getcwd() - os.chdir(os.path.join(workspace, 'dev')) - cmd = 'python {} SCMTime {} Seconds --enable-build-metrics {} --metrics-namespace {} --project-spec None'.format(script_path, scm_total, True, metrics_namespace) - # metrics call shouldn't fail the job - safe_execute_system_call(cmd, shell=True) - os.chdir(cwd) - - -if __name__ == "__main__": - write_metrics() diff --git a/Tools/build/JenkinsScripts/build/utils/lib/__init__.py b/Tools/build/JenkinsScripts/build/utils/lib/__init__.py deleted file mode 100755 index e912252f4e..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/lib/__init__.py +++ /dev/null @@ -1,12 +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. -""" - diff --git a/Tools/build/JenkinsScripts/build/utils/lib/glob3.py b/Tools/build/JenkinsScripts/build/utils/lib/glob3.py deleted file mode 100755 index ad9e739ead..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/lib/glob3.py +++ /dev/null @@ -1,174 +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. -""" - -""" -Filename globbing utility. -Modified using https://github.com/python/cpython/blob/3.7/Lib/glob.py to be compatible with Python2 -Original file Copyright Python Software Foundation, used under license. -Modifications copyright Amazon.com, Inc. or its affiliates. -""" - -import os -import re -import fnmatch - -__all__ = ["glob", "iglob", "escape"] - -def glob(pathname, recursive=False): - """Return a list of paths matching a pathname pattern. - The pattern may contain simple shell-style wildcards a la - fnmatch. However, unlike fnmatch, filenames starting with a - dot are special cases that are not matched by '*' and '?' - patterns. - If recursive is true, the pattern '**' will match any files and - zero or more directories and subdirectories. - """ - return list(iglob(pathname, recursive=recursive)) - -def iglob(pathname, recursive=False): - """Return an iterator which yields the paths matching a pathname pattern. - The pattern may contain simple shell-style wildcards a la - fnmatch. However, unlike fnmatch, filenames starting with a - dot are special cases that are not matched by '*' and '?' - patterns. - If recursive is true, the pattern '**' will match any files and - zero or more directories and subdirectories. - """ - it = _iglob(pathname, recursive, False) - if recursive and _isrecursive(pathname): - s = next(it) # skip empty string - assert not s - return it - -def _iglob(pathname, recursive, dironly): - dirname, basename = os.path.split(pathname) - if not has_magic(pathname): - assert not dironly - if basename: - if os.path.lexists(pathname): - yield pathname - else: - # Patterns ending with a slash should match only directories - if os.path.isdir(dirname): - yield pathname - return - if not dirname: - if recursive and _isrecursive(basename): - yield _glob2(dirname, basename, dironly) - else: - yield _glob1(dirname, basename, dironly) - return - # `os.path.split()` returns the argument itself as a dirname if it is a - # drive or UNC path. Prevent an infinite recursion if a drive or UNC path - # contains magic characters (i.e. r'\\?\C:'). - if dirname != pathname and has_magic(dirname): - dirs = _iglob(dirname, recursive, True) - else: - dirs = [dirname] - if has_magic(basename): - if recursive and _isrecursive(basename): - glob_in_dir = _glob2 - else: - glob_in_dir = _glob1 - else: - glob_in_dir = _glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename, dironly): - yield os.path.join(dirname, name) - -# These 2 helper functions non-recursively glob inside a literal directory. -# They return a list of basenames. _glob1 accepts a pattern while _glob0 -# takes a literal basename (so it only has to check for its existence). - -def _glob1(dirname, pattern, dironly): - names = list(_iterdir(dirname, dironly)) - return fnmatch.filter(names, pattern) - -def _glob0(dirname, basename, dironly): - if not basename: - # `os.path.split()` returns an empty basename for paths ending with a - # directory separator. 'q*x/' should match only directories. - if os.path.isdir(dirname): - return [basename] - else: - if os.path.lexists(os.path.join(dirname, basename)): - return [basename] - return [] - -# Following functions are not public but can be used by third-party code. - -def glob0(dirname, pattern): - return _glob0(dirname, pattern, False) - -def glob1(dirname, pattern): - return _glob1(dirname, pattern, False) - -# This helper function recursively yields relative pathnames inside a literal -# directory. - -def _glob2(dirname, pattern, dironly): - assert _isrecursive(pattern) - return [pattern[:0]] + list(_rlistdir(dirname, dironly)) - -# If dironly is false, yields all file names inside a directory. -# If dironly is true, yields only directory names. -def _iterdir(dirname, dironly): - if not dirname: - if isinstance(dirname, bytes): - dirname = bytes(os.curdir, 'ASCII') - else: - dirname = os.curdir - try: - for entry in os.listdir(dirname): - yield entry - except OSError: - return - -# Recursively yields relative pathnames inside a literal directory. -def _rlistdir(dirname, dironly): - if not os.path.islink(dirname): - names = list(_iterdir(dirname, dironly)) - for x in names: - yield x - path = os.path.join(dirname, x) if dirname else x - for y in _rlistdir(path, dironly): - yield os.path.join(x, y) -magic_check = re.compile('([*?[])') -magic_check_bytes = re.compile(b'([*?[])') - -def has_magic(s): - if isinstance(s, bytes): - match = magic_check_bytes.search(s) - else: - match = magic_check.search(s) - return match is not None - -def _ishidden(path): - return path[0] in ('.', b'.'[0]) - -def _isrecursive(pattern): - if isinstance(pattern, bytes): - return pattern == b'**' - else: - return pattern == '**' - -def escape(pathname): - """Escape all special characters. - """ - # Escaping is done by wrapping any of "*?[" between square brackets. - # Metacharacters do not work in the drive part and shouldn't be escaped. - drive, pathname = os.path.splitdrive(pathname) - if isinstance(pathname, bytes): - pathname = magic_check_bytes.sub(br'[\1]', pathname) - else: - pathname = magic_check.sub(r'[\1]', pathname) - return drive + pathname \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/utils/packaging_version.py b/Tools/build/JenkinsScripts/build/utils/packaging_version.py deleted file mode 100755 index 0960dbcc0d..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/packaging_version.py +++ /dev/null @@ -1,75 +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. -""" - -import os -import sys -from validate_ly_version import _read_version_from_branch_spec -from argparse import ArgumentParser - - -def main(args): - waf_branch_spec_file_directory = os.path.join(os.environ['WORKSPACE'], 'dev') - waf_branch_spec_file_name = 'waf_branch_spec.py' - - if not os.path.exists(os.path.join(waf_branch_spec_file_directory, waf_branch_spec_file_name)): - raise Exception("Invalid workspace directory: {}".format(waf_branch_spec_file_directory)) - - waf_branch_spec_version = _read_version_from_branch_spec(waf_branch_spec_file_directory, waf_branch_spec_file_name) - if waf_branch_spec_version is None: - raise Exception("Unable to read branch spec version from {}.".format(waf_branch_spec_file_name)) - - if args.version: - waf_branch_spec_version = args.version - - if waf_branch_spec_version=='0.0.0.0' and not args.allow_unversioned: - raise Exception('Version "{}" is invalid. Please specify a valid, non-zero LUMBERYARD_VERSION in {}.'.format( - waf_branch_spec_version, - os.path.join(waf_branch_spec_file_directory, waf_branch_spec_file_name) - )) - - versions = waf_branch_spec_version.split('.') - if len(versions) != 4: - raise Exception("Invalid branch spec version '{}'. Must use format 'X.X.X.X'".format(waf_branch_spec_version)) - - major_version = versions[0] - minor_version = versions[1] - - env_inject_file_path = os.path.join(os.environ['WORKSPACE'], os.environ['ENV_INJECT_FILE']) - - print major_version - print minor_version - - with open(env_inject_file_path, 'w') as env_inject_file: - env_inject_file.write('MAJOR_VERSION={}\n'.format(major_version)) - env_inject_file.write('MINOR_VERSION={}\n'.format(minor_version)) - - -def check_env(*vars): - missing = [] - for var in vars: - if var not in os.environ: - missing += (var,) - if missing: - raise Exception("Missing one or more environment variables: {}".format(", ".join(missing))) - - -if __name__ == "__main__": - parser = ArgumentParser() - parser.add_argument('--allow-unversioned', default=False, action='store_true', - help="Allow version '0.0.0.0'. Default is to fail if an invalid version is found") - parser.add_argument('--version', type=str, - help="Manually specify version to use, instead of scanning dev root.") - args = parser.parse_args() - - check_env("WORKSPACE", "ENV_INJECT_FILE") - - main(args) diff --git a/Tools/build/JenkinsScripts/build/utils/scrubbing_test.py b/Tools/build/JenkinsScripts/build/utils/scrubbing_test.py deleted file mode 100755 index 73ed217fd4..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/scrubbing_test.py +++ /dev/null @@ -1,212 +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. -# - -import requests -from requests.auth import HTTPBasicAuth -from P4 import P4, P4Exception -from util import * -from zipfile import ZipFile -from download_from_s3 import s3_download_file, get_client -from botocore.exceptions import ClientError -from upload_to_s3 import s3_upload_file -import os -import shutil -import json -import urllib - -PACKAGE_NAME_REGEX = r'^lumberyard-\d\.\d-\d+-\w+-\d+\.(zip|tgz)$' -P4_USER = 'lybuilder' -BUCKET = 'ly-scrubbing-test' - -# Scrubber will fail if any of these files is missing, copy these files to scrubbing workspace before the test -SCRUBBING_REQUIRED_FILES = [ -] - -try: - JENKINS_USERNAME = os.environ['JENKINS_USERNAME'] - JENKINS_API_TOKEN = os.environ['JENKINS_API_TOKEN'] - JENKINS_SERVER = os.environ['JENKINS_URL'] - P4_PORT = os.environ['ENV_P4_PORT'] - JOB_NAME = os.environ['JOB_NAME'] - BUILD_NUMBER = int(os.environ['BUILD_NUMBER']) - WORKSPACE = os.environ['WORKSPACE'] - SCRUBBING_WORKSPACE = os.environ['SCRUBBING_WORKSPACE'] -except KeyError: - error('This script has to run on Jenkins') - - -class File: - def __init__(self, path, action): - self.path = path - self.action = action - - -# Get the changelist numbers that trigger the build -def get_changelist_numbers(): - changelist_numbers = [] - changeset = [] - headers = {'Content-type': 'application/json', 'Accept': 'application/json'} - try: - res = requests.get('{}/job/{}/{}/api/json'.format(JENKINS_SERVER, JOB_NAME, BUILD_NUMBER), - auth=HTTPBasicAuth(JENKINS_USERNAME, JENKINS_API_TOKEN), headers=headers, verify=False) - res = json.loads(res.content) - changeset = res.get('changeSet').get('items') - except: - print 'Error: Failed to get changes from build {} in job {}'.format(BUILD_NUMBER, JOB_NAME) - for item in changeset: - changelist_numbers.append(item.get('changeNumber')) - return changelist_numbers - - -# Get file list and actions that trigger the Jenkins job -def get_files(): - p4 = P4() - p4.port = P4_PORT - p4.user = P4_USER - p4.connect() - - files = [] - changelist_numbers = get_changelist_numbers() - for changelist_number in changelist_numbers: - cmd = ['describe', '-s', changelist_number] - try: - res = p4.run(cmd)[0] - file_list = res.get('depotFile') - actions = res.get('action') - for action, file_path in zip(actions, file_list): - # P4 returns file paths that are url encoded - file_path = urllib.unquote(file_path).decode("utf8") - # Ignore files which are not in dev - p = file_path.find('dev') - if p != -1: - files.append(File(file_path[p:], action)) - except P4Exception: - error('Internal error, please contact Build System') - return files - - -def copy_file(src, dst, overwrite=False): - if os.path.exists(dst) and not overwrite: - return - print 'Copying file from {} to {}'.format(src, dst) - dest_file_dir = os.path.dirname(dst) - if not os.path.exists(dest_file_dir): - os.makedirs(dest_file_dir) - shutil.copyfile(src, dst) - - -# Run scrubbing scripts -def scrub(): - print 'Perform the Code Scrubbing' - scrubber_path = os.path.join(WORKSPACE, 'dev/Tools/build/JenkinsScripts/distribution/scrubbing/scrub_all.py') - scrub_params = ["-p", "-d", "-o"] - # Scrub code - args = ['python', scrubber_path, '-p', '-d', '-o', os.path.join(SCRUBBING_WORKSPACE, 'dev/Code'), os.path.join(SCRUBBING_WORKSPACE, 'dev')] - return_code = safe_execute_system_call(args) - if return_code != 0: - print 'ERROR: Code scrubbing failed.' - return False - print 'Code scrubbing complete successfully.' - return True - - -# Run scrubbing validator -def validate(): - # Run validator - print 'Running validator' - validator_platforms = ["provo", "salem", "jasper"] - success = True - for validator_platform in validator_platforms: - validator_path = os.path.join(WORKSPACE, 'dev/Tools/build/JenkinsScripts/distribution/scrubbing/validator.py') - args = ['python', validator_path, '-p', validator_platform, os.path.join(SCRUBBING_WORKSPACE, 'dev')] - if safe_execute_system_call(args): - success = False - if not success: - print 'ERROR: Scrubbing validator failed.' - return False - print 'Scrubbing validator complete successfully.' - return True - - -def scrubbing_test(): - if os.path.exists(SCRUBBING_WORKSPACE): - os.system('rmdir /s /q \"{}\"'.format(SCRUBBING_WORKSPACE)) - os.mkdir(SCRUBBING_WORKSPACE) - - client = get_client('s3') - zip_name = '{}.zip'.format(JOB_NAME) - # Check if zipfile exists in S3 bucket - try: - client.head_object(Bucket=BUCKET, Key=zip_name) - except ClientError as e: - if e.response['Error']['Code'] == '404': - print 'No previous zipfile found in S3 bucket {}'.format(BUCKET) - else: - raise - else: - # Download the zipfile from S3 bucket if the zipfile exists - if not s3_download_file(client, SCRUBBING_WORKSPACE, zip_name, BUCKET, max_retry=3): - warn('Failed to download {} from S3 bucket {}'.format(zip_name, BUCKET)) - - # Unzip the zipfile to SCRUBBING_WORKSPACE - zip_path = os.path.join(SCRUBBING_WORKSPACE, zip_name) - if os.path.exists(zip_path): - zip_file = ZipFile(os.path.join(SCRUBBING_WORKSPACE, zip_name), 'r') - zip_file.extractall(SCRUBBING_WORKSPACE) - zip_file.close() - - # Copy scrubbing required files to SCRUBBING_WORKSPACE, no overwrite - for file in SCRUBBING_REQUIRED_FILES: - src_file = os.path.join(WORKSPACE, file) - dst_file = os.path.join(SCRUBBING_WORKSPACE, file) - copy_file(src_file, dst_file) - - # Get file list and actions that trigger the Jenkins job - files = get_files() - - # Copy or delete each file in SCRUBBING_WORKSPACE - for f in files: - dst_file = os.path.join(SCRUBBING_WORKSPACE, f.path) - if 'delete' in f.action: - if os.path.exists(dst_file): - print 'Deleting {}'.format(dst_file) - os.remove(dst_file) - else: - src_file = os.path.join(WORKSPACE, f.path) - copy_file(src_file, dst_file, overwrite=True) - - # Backup the unmodified files and run scrubber and validator - backup_path = os.path.join(SCRUBBING_WORKSPACE, 'backup') - scrubbing_dev = os.path.join(SCRUBBING_WORKSPACE, 'dev') - success = True - if os.path.exists(scrubbing_dev): - shutil.copytree(scrubbing_dev, os.path.join(backup_path, 'dev')) - success = scrub() and validate() - - if success: - # Delete zipfile from S3 if validator run successfully - try: - print 'Deleting {} from bucket {}'.format(zip_name, BUCKET) - client.delete_object(Bucket=BUCKET, Key=zip_name) - except: - warn('Failed to delete {} from bucket {}'.format(zip_name, BUCKET)) - else: - # Upload backup files to S3 bucket - if os.path.exists(backup_path): - zip_path = os.path.join(SCRUBBING_WORKSPACE, JOB_NAME) - shutil.make_archive(zip_path, 'zip', backup_path) - if not s3_upload_file(client, SCRUBBING_WORKSPACE, zip_name, BUCKET, max_retry=3): - error('Failed to upload {} to S3 bucket {}'.format(zip_name, BUCKET)) - exit(1) - - -if __name__ == "__main__": - scrubbing_test() diff --git a/Tools/build/JenkinsScripts/build/utils/update_bootstrap_cfg.py b/Tools/build/JenkinsScripts/build/utils/update_bootstrap_cfg.py deleted file mode 100755 index a09c22ae3d..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/update_bootstrap_cfg.py +++ /dev/null @@ -1,82 +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. -""" - -''' -This script is to update the configuration in dev/bootstrap.cfg -Usage: python update_bootstrap_cfg.py --bootstrap_cfg file_path --replace key1=value1,key2=value2 -''' - -from optparse import OptionParser -import os -import stat - - -def update_bootstrap_cfg(file, replace_values): - try: - with open(file, 'r') as bootstrap_cfg: - content = bootstrap_cfg.read() - except: - error('Cannot read file {}'.format(file)) - content = content.split('\n') - new_content = [] - for line in content: - if not line.startswith('--'): - strs = line.split('=') - if len(strs): - key = strs[0].strip(' ') - if key in replace_values: - line = '{}={}'.format(key, replace_values[key]) - new_content.append(line) - - try: - with open(file, 'w') as out: - out.write('\n'.join(new_content)) - except: - error('Cannot write to file {}'.format(file)) - print '{} updated with value {}'.format(file, replace_values) - - -def error(msg): - print msg - exit(1) - - -def parse_args(): - parser = OptionParser() - parser.add_option("--bootstrap_cfg", dest="bootstrap_cfg", default=None, help="File path of bootstrap.cfg to be updated.") - parser.add_option("--replace", dest="replace", default=None, help="Target platform to package") - (options, args) = parser.parse_args() - bootstrap_cfg = options.bootstrap_cfg - replace = options.replace - - if not bootstrap_cfg: - error('bootstrap.cfg is not specified.') - if not os.path.isfile(bootstrap_cfg): - error('File {} not found.'.format(bootstrap_cfg)) - replace_values = {} - if replace: - try: - replace = replace.split(',') - for r in replace: - r = r.split('=') - key = r[0].strip(' ') - value = r[1].strip(' ') - replace_values[key] = value - except IndexError: - error('Please check the format of argument --replace.') - - return bootstrap_cfg, replace_values - - -if __name__ == "__main__": - (file, replace_values) = parse_args() - update_bootstrap_cfg(file, replace_values) diff --git a/Tools/build/JenkinsScripts/build/utils/upload_benchmarks.py b/Tools/build/JenkinsScripts/build/utils/upload_benchmarks.py deleted file mode 100755 index 99f1d4d3da..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/upload_benchmarks.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python -# -# 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. -# - -import argparse -from datetime import datetime, timezone -import hashlib -import os -import pathlib -import platform -import re -import sys -import subprocess -import zipfile - -''' -Creates zip file of /BenchmarkResults folder and sends the the zip via email to team email -''' - -def compute_sha256(input_filepath): - ''' - Computes a SHA-2 hash using a digest that is 256 bits - - Args: - input_filepath: File whose content will be hashed using the SHA-2 hash function - - Returns: - bytes: byte array containing hash digest in hex - ''' - hasher = hashlib.sha256() - hash_result = None - - CHUNK_SIZE = 128 * (1 << 10) # Chunk Size for Sha256 hashing reads file in chunks of 128 KiB - with open(input_filepath, 'rb') as hash_file: - buf = hash_file.read(CHUNK_SIZE) - hasher.update(buf) - hash_result = hasher.hexdigest() - - return hash_result - -def create_sha256sums_file(input_filepath): - ''' - Create a sha256sums file from the contents of the input_filepath - The sha256sums file will be named using the input_filepath path with an added - extension of .sha256sums - - Args: - input_filepath: File whose content will be hashed using the SHA-2 hash function - - Returns: - string: Path to sha256sums file - ''' - sha256_hash = compute_sha256(input_filepath) - if not sha256_hash: - print(f'Unable to compute sha256 hash for file {input_filepath}') - return None - - hash_filepath = f'{input_filepath}.sha256sums' - with open(hash_filepath, "wb") as archive_hash_file: - new_hash_contents = f'{sha256_hash} *{os.path.basename(input_filepath)}\n' - archive_hash_file.write(new_hash_contents.encode("utf8")) - - return hash_filepath - -def get_files_to_archive(base_dir, regex): - ''' - Gathers list of filepaths to add to archive file - Files are looked up with the base directory and cross checked against the supplied regular expression - which acts as an inclusion filter - - Args: - base_dir: Directory to scan for files - regex: Regular expression that is matched against each filename to determine if the file should be - added to the archive - ''' - # Get all file names in base directory - with os.scandir(base_dir) as dir_entry: - filepaths = [pathlib.PurePath(entry.path) for entry in dir_entry if entry.is_file()] - # Get all file names matching the regular expression, those file will be added to zip archive - archive_files = [str(filepath) for filepath in filepaths if re.match(regex, filepath.as_posix())] - return archive_files - return None - - -def create_archive_file(archive_file_prefix, input_filepaths, base_dir): - ''' - Creates a zip file using the supplied input files - LZMA compression is used by default for the zip file compression - - Args: - archive_file_prefix: Prefix to use as the name of the zip file that should be created - input_filepaths: List of input file paths that will be added to zip file - base_dir: Directory which is used to create relative paths for each input file path from - ''' - try: - zipfile_name = '{}-{:%Y%m%d_%H%M%S}.zip'.format(archive_file_prefix,datetime.now(timezone.utc)) - # The lzma shared library isn't installed by default on Mac. - compression_type = zipfile.ZIP_LZMA if platform.system() != 'Darwin' else zipfile.ZIP_BZIP2 - with zipfile.ZipFile(zipfile_name, mode='w', compression=compression_type) as benchmark_archive: - zipfile_name = benchmark_archive.filename - for input_filepath in input_filepaths: - # Make input files relative to base_dir when storing them as archived names - input_filepath_relpath = os.path.relpath(input_filepath, start=base_dir) - benchmark_archive.write(input_filepath, input_filepath_relpath) - except OSError as err: - print(f'Failed to write benchmark files to zip archive with error {err}') - sys.exit(1) - except RuntimeError as zip_err: - print(f'Runtime Error in zipfile module {zip_err}') - sys.exit(1) - return zipfile_name - -def upload_to_s3(upload_script_path, base_dir, path_regex, bucket, key_prefix): - ''' - Uploads files which located within the base directory using the upload_to_s3.py script - - Args: - base_dir: The directory to pass as the --base-dir value to the upload_to_s3.py script - path_regex: The regular expression to pass to the upload_to_s3.py script --file-regex parameter - bucket: The s3 bucket to use for the --bucket argument for upload_to_s3.py - key_prefix: The prefix to store the uploaded files to within the s3 bucket, - It is passed --key-prefix argument to upload_to_s3.py - ''' - try: - subprocess.run(['python', upload_script_path, '--base_dir', - base_dir, '--file_regex', path_regex, - '--bucket', bucket, '--key_prefix', key_prefix], - check=True) - except subprocess.CalledProcessError as err: - print(f'{upload_script_path} failed with error {err}') - sys.exit(1) - -def upload_benchmarks(args): - ''' - Main function responsible for determine which files to add to the output zip file and uploading - the results to s3 - - Args: - args: Parse argument list of python command line parameters using the argparse module - ''' - files_to_archive = get_files_to_archive(args.base_dir, args.file_regex) - archive_zip_path = create_archive_file(args.output_prefix, files_to_archive, args.base_dir) - # Create Sha256sum hash file of zip - create_sha256sums_file(archive_zip_path) - - upload_dir = str(pathlib.Path(archive_zip_path).parent) - upload_regex = fr'{pathlib.Path(archive_zip_path).name}.*' - upload_to_s3(args.upload_to_s3_script_path, upload_dir, upload_regex, args.bucket, args.key_prefix) - -def parse_args(): - cur_dir = os.path.dirname(os.path.abspath(__file__)) - parser = argparse.ArgumentParser() - parser.add_argument("--base_dir", default=os.getcwd(), help="Base directory to files which should be archived, If not given, then current directory is used.") - parser.add_argument("--upload-to-s3-script-path", default=os.path.join(cur_dir, 'upload_to_s3.py'), help="Path to upload_to_s3.py script. Script is used for uploading benchmarks to s3") - parser.add_argument("--file_regex", default=r'.*BenchmarkResults/.+\.json', help="Regular expression that used to match file names to archive.") - parser.add_argument("-o", "--output-prefix", default='benchmarks_results', help="Prefix to use to construct the name of the zip file where the benchmark results are zipped." - " A timestamp will be added to the end of filename") - parser.add_argument("--bucket", dest="bucket", default='ly-jenkins-cmake-benchmarks', help="S3 bucket the files are uploaded to.") - parser.add_argument("-k", "--key_prefix", default='user_build', dest="key_prefix", help="Object key prefix.") - args = parser.parse_args() - - return args - -if __name__ == '__main__': - args = parse_args(); - upload_benchmarks(args) diff --git a/Tools/build/JenkinsScripts/build/utils/upload_metrics_to_kinesis.py b/Tools/build/JenkinsScripts/build/utils/upload_metrics_to_kinesis.py deleted file mode 100755 index 62e61a0237..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/upload_metrics_to_kinesis.py +++ /dev/null @@ -1,183 +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. -# -# -# Original file Copyright Crytek GMBH or its affiliates, used under license. -# -######################################################################################## -import ast -import boto3 -from botocore.exceptions import ClientError -from datetime import datetime -import logging -import os -import shutil -import sys -import time -import traceback -import urllib2 -import uuid - -KINESIS_STREAM_NAME = 'lumberyard-metrics-stream' -KINESIS_MAX_RECORD_SIZE = 1048576 # 1 MB -S3_BACKUP_BUCKET = 'infrastructure-build-metrics-backup' -IAM_ROLE_NAME = 'ec2-jenkins-node' -LOG_FILE_NAME = 'kinesis_upload.log' - -MAX_RECORD_SIZE = KINESIS_MAX_RECORD_SIZE - 4 # to account for version header -MAX_RETRIES = 5 -RETRY_EXCEPTIONS = ('ProvisionedThroughputExceededException', - 'ThrottlingException') - -# truncate the log file, eventually we need to send the logs to cloudwatch logs -with open(LOG_FILE_NAME, 'w'): - pass - -logger = logging.getLogger('KinesisUploader') - -fileHdlr = logging.FileHandler(LOG_FILE_NAME) -# uncomment this line and the two below to have logs go to stdout for debugging purposes -#streamHdlr = logging.StreamHandler(sys.stdout) - -formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') -fileHdlr.setFormatter(formatter) -#streamHdlr.setFormatter(formatter) - -logger.addHandler(fileHdlr) -#logger.addHandler(streamHdlr) -logger.setLevel(logging.DEBUG) - -def backup_file_to_s3(s3_client, bucket_name, file_location, s3_file_name): - try: - s3_client.meta.client.upload_file(file_location, bucket_name, s3_file_name) - os.remove(file_location) - except: - logger.error('Failed to upload backup file to S3. This is non-fatal!') - # logger.error(traceback.print_exc()) - - -def get_iam_role_credentials(role_name): - security_metadata = None - try: - response = urllib2.urlopen( - 'http://169.254.169.254/latest/meta-data/iam/security-credentials/{0}'.format(role_name)).read() - security_metadata = ast.literal_eval(response) - except: - logger.error('Unable to get iam role credentials') - logger.error(traceback.print_exc()) - - return security_metadata - - -def splitFileByRecord(stream, maxSize): - version = 1 - - # currently using random GUID for partition key, but in the future we may want to partition by some build id - # or by build host - partition_key = uuid.uuid4() - - entry_size = 0 - put_entries = [] - - current_entry = '' - for line in stream: - line_size_in_bytes = len(line.encode('utf-8')) - entry_size = entry_size + line_size_in_bytes - - if (entry_size > MAX_RECORD_SIZE): - put_entries.append({ - 'Data': str(version) + '\n' + str(current_entry), - 'PartitionKey': str(partition_key) - }) - - current_entry = line - entry_size = line_size_in_bytes - else: - current_entry = current_entry + line - - if current_entry: - put_entries.append({ - 'Data': str(version) + '\n' + str(current_entry), - 'PartitionKey': str(partition_key) - }) - - return put_entries - - -def main(): - credentials = get_iam_role_credentials(IAM_ROLE_NAME) - - aws_access_key_id = None - aws_secret_access_key = None - aws_session_token = None - - if credentials is not None: - keys = ['AccessKeyId', 'SecretAccessKey', 'Token'] - for key in keys: - if key not in credentials: - logger.error('Unable to find {0} in get_iam_role_credentials response {1}'.format(key, credentials)) - return - - aws_access_key_id = credentials['AccessKeyId'] - aws_secret_access_key = credentials['SecretAccessKey'] - aws_session_token = credentials['Token'] - - kinesis_client = boto3.client('kinesis', region_name='us-west-2', aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, aws_session_token=aws_session_token) - s3_client = boto3.resource('s3', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token) - - file_location = sys.argv[1] - filename = os.path.basename(file_location) - backup_file_location = file_location + '.bak' - - try: - if os.path.isfile(backup_file_location): - logger.info('Found pre-existing backup file. Uploading to S3.') - backup_file_to_s3(s3_client, S3_BACKUP_BUCKET, backup_file_location, - '{0}.{1}'.format(filename, datetime.now().isoformat())) - - if os.path.isfile(file_location): - shutil.copyfile(file_location, backup_file_location) - backup_file_to_s3(s3_client, S3_BACKUP_BUCKET, backup_file_location, - '{0}.{1}'.format(filename, datetime.now().isoformat())) - - logger.info('Opening metrics file {0}'.format(file_location)) - with open(file_location, 'r+') as f: - records = splitFileByRecord(f, MAX_RECORD_SIZE) - i = 0 - retries = 0 - while i < len(records): - record = records[i] - try: - logger.info('Uploading {0} bytes of metrics to Kinesis...'.format(len(record))) - kinesis_client.put_record(StreamName=KINESIS_STREAM_NAME, - Data=record['Data'], - PartitionKey=record['PartitionKey']) - retries = 0 - except ClientError as ex: - if ex.response['Error']['Code'] not in RETRY_EXCEPTIONS: - raise - - sleep_time = 2 ** retries - logger.warn('Request throttled by Kinesis, ' - 'sleeping and retrying in {0} seconds'.format(2 ** retries)) - time.sleep(sleep_time) - retries += 1 - i -= 1 - - i += 1 - - f.truncate(0) - except: - logger.error(traceback.print_exc()) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/build/utils/upload_to_s3.py b/Tools/build/JenkinsScripts/build/utils/upload_to_s3.py deleted file mode 100755 index dd1670b08b..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/upload_to_s3.py +++ /dev/null @@ -1,107 +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. -# -''' -Usage: -Use EC2 role to upload all .zip and .MD5 files in %WORKSPACE% folder to bucket ly-packages-mainline: -python upload_to_s3.py --base_dir %WORKSPACE% --file_regex "(.*zip$|.*MD5$)" --bucket ly-packages-mainline - -Use profile to upload all .zip and .MD5 files in %WORKSPACE% folder to bucket ly-packages-mainline: -python upload_to_s3.py --base_dir %WORKSPACE% --profile profile --file_regex "(.*zip$|.*MD5$)" --bucket ly-packages-mainline - -''' - - -import os -import re -import json -import boto3 -from optparse import OptionParser -from util import error - - -def parse_args(): - parser = OptionParser() - parser.add_option("--base_dir", dest="base_dir", default=os.getcwd(), help="Base directory to upload files, If not given, then current directory is used.") - parser.add_option("--file_regex", dest="file_regex", default=None, help="Regular expression that used to match file names to upload.") - parser.add_option("--profile", dest="profile", default=None, help="The name of a profile to use. If not given, then the default profile is used.") - parser.add_option("--bucket", dest="bucket", default=None, help="S3 bucket the files are uploaded to.") - parser.add_option("--key_prefix", dest="key_prefix", default='', help="Object key prefix.") - ''' - ExtraArgs used to call s3.upload_file(), should be in json format. extra_args key must be one of: ACL, CacheControl, ContentDisposition, ContentEncoding, ContentLanguage, ContentType, Expires, - GrantFullControl, GrantRead, GrantReadACP, GrantWriteACP, Metadata, RequestPayer, ServerSideEncryption, StorageClass, - SSECustomerAlgorithm, SSECustomerKey, SSECustomerKeyMD5, SSEKMSKeyId, WebsiteRedirectLocation - ''' - parser.add_option("--extra_args", dest="extra_args", default=None, help="Additional parameters used to upload file.") - parser.add_option("--max_retry", dest="max_retry", default=1, help="Maximum retry times to upload file.") - (options, args) = parser.parse_args() - if not os.path.isdir(options.base_dir): - error('{} is not a valid directory'.format(options.base_dir)) - if not options.file_regex: - error('Use --file_regex to specify regular expression that used to match file names to upload.') - if not options.bucket: - error('Use --bucket to specify bucket that the files are uploaded to.') - return options - - -def get_client(service_name, profile_name): - session = boto3.session.Session(profile_name=profile_name) - client = session.client(service_name) - return client - - -def get_files_to_upload(base_dir, regex): - # Get all file names in base directory - files = [x for x in os.listdir(base_dir) if os.path.isfile(os.path.join(base_dir, x))] - # Get all file names matching the regular expression, those file will be uploaded to S3 - files_to_upload = [x for x in files if re.match(regex, x)] - return files_to_upload - - -def s3_upload_file(client, base_dir, file, bucket, key_prefix=None, extra_args=None, max_retry=1): - print('Uploading file {} to bucket {}.'.format(file, bucket)) - key = file if key_prefix is None else '{}/{}'.format(key_prefix, file) - for x in range(max_retry): - try: - client.upload_file( - os.path.join(base_dir, file), bucket, key, - ExtraArgs=extra_args - ) - print('Upload succeeded') - return True - except Exception as err: - print('exception while uploading: {}'.format(err)) - print('Retrying upload...') - print('Upload failed') - return False - - -if __name__ == "__main__": - options = parse_args() - client = get_client('s3', options.profile) - files_to_upload = get_files_to_upload(options.base_dir, options.file_regex) - extra_args = json.loads(options.extra_args) if options.extra_args else None - - print('Uploading {} files to bucket {}.'.format(len(files_to_upload), options.bucket)) - failure = [] - success = [] - for file in files_to_upload: - if not s3_upload_file(client, options.base_dir, file, options.bucket, options.key_prefix, extra_args, 2): - failure.append(file) - else: - success.append(file) - print('Upload finished.') - print('{} files are uploaded successfully:'.format(len(success))) - print('\n'.join(success)) - if len(failure) > 0: - print('{} files failed to upload:'.format(len(failure))) - print('\n'.join(failure)) - # Exit with error code 1 if any file is failed to upload - exit(1) diff --git a/Tools/build/JenkinsScripts/build/utils/util.py b/Tools/build/JenkinsScripts/build/utils/util.py deleted file mode 100755 index fa5d14caa7..0000000000 --- a/Tools/build/JenkinsScripts/build/utils/util.py +++ /dev/null @@ -1,65 +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. -""" - -import json -import os -import re -import subprocess - - -class LyBuildError(Exception): - def __init__(self, message): - super(LyBuildError, self).__init__(message) - - def __str__(self): - return str(self.message) - - -def ly_build_error(message): - raise LyBuildError(message) - - -def error(message): - print('Error: {}'.format(message)) - exit(1) - - -# Exit with status code 0 means it won't fail the whole build process -def safe_exit_with_error(message): - print('Error: {}'.format(message)) - exit(0) - - -def warn(message): - print('Warning: {}'.format(message)) - - -def execute_system_call(command, **kwargs): - print('Executing subprocess.check_call({})'.format(command)) - try: - subprocess.check_call(command, **kwargs) - except subprocess.CalledProcessError as e: - print(e.output) - error('Executing subprocess.check_call({}) failed with error {}'.format(command, e)) - except FileNotFoundError as e: - error("File Not Found - Failed to call {} with error {}".format(command, e)) - - -def safe_execute_system_call(command, **kwargs): - print('Executing subprocess.check_call({})'.format(command)) - try: - subprocess.check_call(command, **kwargs) - except subprocess.CalledProcessError as e: - print(e.output) - warn('Executing subprocess.check_call({}) failed'.format(command)) - return e.returncode - return 0 diff --git a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyChecksum.py b/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyChecksum.py deleted file mode 100755 index 5a9b7f86b4..0000000000 --- a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyChecksum.py +++ /dev/null @@ -1,64 +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. -""" - -import hashlib -import re - - -def generateFilesetChecksum(filePaths): - filesetHash = hashlib.sha512() - for filePath in filePaths: - updateHashWithFileChecksum(filePath, filesetHash) - return filesetHash - - -def getChecksumForSingleFile(filePath, openMode='rb'): - filesetHash = hashlib.sha512() - updateHashWithFileChecksum(filePath, filesetHash, openMode) - return filesetHash - - -def getMD5ChecksumForSingleFile(filePath, openMode='rb'): - filesetHash = hashlib.md5() - updateHashWithFileChecksum(filePath, filesetHash, openMode) - return filesetHash - - -def updateHashWithFileChecksum(filePath, filesetHash, openMode='rb'): - BLOCKSIZE = 65536 - with open(filePath.strip('\n'), openMode) as file: - buf = file.read(BLOCKSIZE) - while len(buf) > 0: - filesetHash.update(buf) - buf = file.read(BLOCKSIZE) - - -def is_valid_hash_sha1(checksum): - # sha1 hashes are 40 hex characters long. - if len(checksum) is not 40: - return False - sha1_re = re.compile("(^[0-9A-Fa-f]{40}$)") - result = sha1_re.match(checksum) - if not result: - return False - return True - - -def is_valid_hash_sha512(checksum): - # sha512 hashes are 128 hex characters long. - if len(checksum) is not 128: - return False - sha512_re = re.compile("(^[0-9A-Fa-f]{128}$)") - result = sha512_re.match(checksum) - if not result: - return False - return True diff --git a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyCloudfrontOps.py b/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyCloudfrontOps.py deleted file mode 100755 index 0c6270f302..0000000000 --- a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/LyCloudfrontOps.py +++ /dev/null @@ -1,76 +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. -""" - -import os.path -import boto3 -try: - import urllib.parse as urllib_compat -except: - import urlparse as urllib_compat - -def getCloudfrontDistPath(uploadURL): - pathFromDomainName = urllib_compat.urlparse(uploadURL)[2] - # need to remove the first slash, otherwise it will create a nameless directory on S3 - return pathFromDomainName[1:] - - -def getCloudfrontDistribution(cloudfrontUrl, awsCredentialProfileName): - session = boto3.session.Session(profile_name=awsCredentialProfileName) - cloudfront = session.client('cloudfront') - distributionList = cloudfront.list_distributions() - targetDistId = None - for distribution in distributionList["DistributionList"]["Items"]: - if distribution["DomainName"] == urllib_compat.urlparse(cloudfrontUrl)[1]: - targetDistId = distribution["Id"] - pass - assert (targetDistId is not None), "No distribution with the domain name {} found.".format(cloudfrontUrl) - targetDist = cloudfront.get_distribution(Id=targetDistId) - return targetDist - - -def getBucket(cloudfrontDistribution, awsCredentialProfileName): - bucketName = getBucketName(cloudfrontDistribution) - session = boto3.session.Session(profile_name=awsCredentialProfileName) - s3 = session.resource('s3') - return s3.Bucket(bucketName) - - -def getBucketName(cloudfrontDistribution): - s3Info = cloudfrontDistribution["Distribution"]["DistributionConfig"]["Origins"]["Items"][0] - bucketDomainName = s3Info["DomainName"] - return bucketDomainName.split('.')[0] # first part of the domain name is the bucket name - - -def buildBucketPath(cloudfrontUrl, cloudfrontDistribution): - s3Info = cloudfrontDistribution["Distribution"]["DistributionConfig"]["Origins"]["Items"][0] - originPath = s3Info["OriginPath"] - bucketPath = None - if originPath: - # Start originPath after the first character (presumed to be '/') to avoid nameless directory in S3. - bucketPath = str.format("{0}/{1}", originPath[1:], getCloudfrontDistPath(cloudfrontUrl)) - else: - bucketPath = getCloudfrontDistPath(cloudfrontUrl) - return bucketPath - - -def uploadFileToCloudfrontURL(absFilePath, cloudfrontBaseUrl, awsCredentialProfileName, overwrite): - cloudfrontDist = getCloudfrontDistribution(cloudfrontBaseUrl, awsCredentialProfileName) - s3Bucket = getBucket(cloudfrontDist, awsCredentialProfileName) - s3BucketPath = buildBucketPath(cloudfrontBaseUrl, cloudfrontDist) - targetBucketPath = urllib_compat.urljoin(s3BucketPath, os.path.basename(absFilePath)) - - # Check if file already exists in the S3 bucket. - file_exists = len(list(s3Bucket.objects.filter(Prefix=targetBucketPath))) > 0 - if not file_exists or overwrite: - s3Bucket.upload_file(absFilePath, targetBucketPath) - - return targetBucketPath diff --git a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/__init__.py b/Tools/build/JenkinsScripts/distribution/AWS_PyTools/__init__.py deleted file mode 100755 index e912252f4e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/AWS_PyTools/__init__.py +++ /dev/null @@ -1,12 +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. -""" - diff --git a/Tools/build/JenkinsScripts/distribution/AWS_WAF_Updater/update_internal_whitelist.py b/Tools/build/JenkinsScripts/distribution/AWS_WAF_Updater/update_internal_whitelist.py deleted file mode 100755 index 19d3a466f9..0000000000 --- a/Tools/build/JenkinsScripts/distribution/AWS_WAF_Updater/update_internal_whitelist.py +++ /dev/null @@ -1,303 +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. -""" - -import argparse -import boto3 -import hashlib -import json -import math -import netaddr -import time -import urllib2 - -# Order of operations -# 1) Get list of internal IPs from dogfish -# 2) Translate IP ranges into WAF-vaild CIDR Subnets -# 3) Get InternalIPWhitelist rule from WAF -# 4) Get all list of all IP Sets on that rule -# 5) Loop through all IP ranges in all IP sets -# a) If the IP address is not in the set of WAF-valid CIDR Subnets, remove it from the IPSet lists -# b) If the IP address is in the set of WAF-valid CIDR Subnets, remove it from the WAF-valid CIDR subnet list -# 6) Anything left in the WAF-valid CIDR Subnet list needs to be added to IP Sets -# a) create a new IP set if necessary (max 1000 ranges per IP Set) -# 7) Push updates to WAF - -rule_name = "Internal_IP_Whitelist" -ip_set_basename = "Amazon_Internal_IPs" - -# Maximum number of IP descriptors per IP Set -max_ranges_per_ip_set = 1000 - -# Maximum number of IP descriptors updates per call -max_ranges_per_update = 1000 - -ip_version = "IPV4" - - -def parse_args(): - """Handle argument parsing and validate destination folder exists before returning argparse args""" - parser = argparse.ArgumentParser(description='Use AWS CLI to update the Internal IP Whitelist in dev or prod') - - parser.add_argument('-l', '--list', action='store_true', - help="List the WAF Valid IPs that the list of IPs translates to instead of running the update.") - parser.add_argument('-p', '--profile', default='default', help="The name of the AWS CLI profile to use.") - - args = parser.parse_args() - return args - - -def translate_and_apply_to_waf(ip_ranges, args): - subnet_list = list() - for ip_range in ip_ranges: - subnet_list.extend(translate_range_to_subnet_list(ip_range)) - - session = boto3.Session(profile_name=args.profile) - waf = session.client('waf') - change_tokens = apply_updates_to_waf(subnet_list, waf) - - # wait for every change to finish before ending - waiting_on_changes = True - while waiting_on_changes: - change_in_progress = False - time.sleep(.3) - for token in change_tokens: - status = waf.get_change_token_status(ChangeToken=token["ChangeToken"]) - change_in_progress = change_in_progress and (status == "PENDING") - if change_in_progress: - break - waiting_on_changes = change_in_progress - - return not waiting_on_changes - - -def apply_updates_to_waf(ip_list, waf): - white_list_rule = get_ip_whitelist_rule(waf) - ip_set_list, negate_conditions = get_ip_sets_from_rule(white_list_rule, waf) - - ip_to_add = list(ip_list) - adds = list() - - change_tokens = list() - - # for each ip set, get the ip ranges in each descriptor and compare against the ip list - # remove duplicates from the list to add - for ip_set in ip_set_list: - for ip_range_descriptor in ip_set["IPSetDescriptors"]: - ip = netaddr.IPNetwork(ip_range_descriptor["Value"]) - # if an ip in the list is already in an IPSet, then remove it from the list of stuff to add - if ip in ip_list: - ip_to_add.remove(ip) - - # create add operations - for ip in ip_to_add: - adds.append( - { - 'Action': 'INSERT', - 'IPSetDescriptor': { - 'Type': ip_version, - 'Value': str(ip) - } - } - ) - - # make delete operations for anything in a set that isn't in the list of IPs, then populate the rest of the list - # with adds until we hit max of the IPSet - for ip_set in ip_set_list: - removes = list() - - for ip_range_descriptor in ip_set["IPSetDescriptors"]: - ip = netaddr.IPNetwork(ip_range_descriptor["Value"]) - if ip not in ip_list: - removes.append( - { - 'Action': 'DELETE', - 'IPSetDescriptor': ip_range_descriptor - } - ) - - # perform the updates to this set - perform_updates_to_existing_ipset(ip_set, removes, adds, waf, change_tokens) - - # we've done all the removes, and filled all existing ip_sets with adds. if we have leftovers, we need to make a - # new ip_set and add it to the rule - if len(adds) > 0: - num_ip_sets = len(ip_set_list) - rule_updates = list() - while len(adds) > 0: - create_token = waf.get_change_token() - change_tokens.append(create_token) - ip_set = waf.create_ip_set(Name="{0}_{1}".format(ip_set_basename, num_ip_sets), - ChangeToken=create_token["ChangeToken"])["IPSet"] - num_ip_sets += 1 - ip_set_id = ip_set["IPSetId"] - rule_updates.append( - { - 'Action': 'INSERT', - 'Predicate': { - 'Negated': negate_conditions, - 'Type': 'IPMatch', - 'DataId': ip_set_id - } - } - ) - - # populate the new ip_set - batch = move_updates_to_batch(adds) - update_set_token = waf.get_change_token() - change_tokens.append(update_set_token) - waf.update_ip_set(IPSetId=ip_set_id, - ChangeToken=update_set_token["ChangeToken"], - Updates=batch) - - # update the rule with the new ip_lists - update_rule_token = waf.get_change_token() - change_tokens.append(update_rule_token) - waf.update_rule(RuleId=white_list_rule["RuleId"], - ChangeToken=update_rule_token["ChangeToken"], - Updates=rule_updates) - - return change_tokens - - -def perform_updates_to_existing_ipset(ip_set, removes, adds, waf, change_tokens): - # figure out how many adds can be done on this ip_set after all of the removes - space_remaining_in_set = max_ranges_per_ip_set - (len(ip_set["IPSetDescriptors"]) - len(removes)) - - # fill the list of updates to perform with removes and adds until the end result is either a full set or - # all operations have been performed. - updates = list(removes) - updates.extend(list(adds[0:space_remaining_in_set])) - adds[0:space_remaining_in_set] = [] - - # make batches of updates (max per batch = max_ranges_per_update) - update_batches = list() - while len(updates) > 0: - batch = move_updates_to_batch(updates) - update_batches.append(batch) - - # submit an update set request for each batch - for batch in update_batches: - change_token = waf.get_change_token() - change_tokens.append(change_token) - waf.update_ip_set(IPSetId=ip_set["IPSetId"], - ChangeToken=change_token["ChangeToken"], - Updates=batch) - - -def move_updates_to_batch(original_list): - items_to_batch = min(len(original_list), max_ranges_per_update) - batch = list(original_list[0:items_to_batch]) - original_list[0:items_to_batch] = [] - return batch - - -def get_ip_whitelist_rule(waf_client): - rules_list = waf_client.list_rules(Limit=100) - - whitelist_rule_id = None - for rule in rules_list["Rules"]: - if rule["Name"] == rule_name: - whitelist_rule_id = rule["RuleId"] - - if whitelist_rule_id is None: - return None - - return waf_client.get_rule(RuleId=whitelist_rule_id)["Rule"] - - -def get_ip_sets_from_rule(rule, waf_client): - ip_sets = list() - negate_conditions = False - for condition in rule["Predicates"]: - if condition["Type"] == 'IPMatch': - ip_set_id = condition["DataId"] - ip_set = waf_client.get_ip_set(IPSetId=ip_set_id) - - if ip_set is not None and ip_set_basename in ip_set["IPSet"]["Name"]: - ip_sets.append(ip_set["IPSet"]) - else: - print "No IPSet with ID {0}".format(ip_set_id) - - negate_conditions = condition["Negated"] - - return ip_sets, negate_conditions - - -def translate_range_to_subnet_list(ip_range): - """ - - :param ip_range: The IP address + CIDR prefix (IPNetwork object) - :return: A list of all WAF-valid subnets that compose the given IP range - """ - prefix = ip_range.prefixlen - waf_valid_prefix = find_closest_waf_range(prefix) - return list(ip_range.subnet(waf_valid_prefix)) - - -def find_closest_waf_range(cidr_prefix_length): - """ - AWS WAF only accepts CIDR ranges of /8, /16, /24, /32. figure out what the closest safe range we need to convert to. - This will always return a smaller range than what is passed in for security reasons. - - :param cidr_prefix_length: The arbitrary CIDR range to convert to a WAF-valid range - :return: The closest WAF-valid range. i.e. if cidr_prefix_length = 18, this fuction will return 24 - """ - multiple = math.trunc(cidr_prefix_length / 8) - return (multiple + 1) * 8 # needs to be 1 based to get accurate range - - -def list_all_waf_valid_subnets(ip_list): - num_ips = 0 - for ip_range in ip_list: - subnets = translate_range_to_subnet_list(ip_range) - num_ips += len(subnets) - for ip in subnets: - print ip - return num_ips - - -def main(): - # IPs taken from https://w.amazon.com/index.php/PublicIPRanges - ips = ["207.171.176.0/20", # SEA - "205.251.224.0/22", - "176.32.120.0/22", - "54.240.196.0/24", - "54.231.244.0/22", - "52.95.52.0/22", - "205.251.232.0/22", # PDX - "54.240.230.0/23", - "54.240.248.0/21", - "54.231.160.0/19", - "54.239.2.0/23", - "54.239.48.0/22", - "52.93.12.0/22", - "52.94.208.0/21", - "52.218.128.0/17", - "204.246.160.0/22", # SFO - "205.251.228.0/22", - "176.32.112.0/21", - "54.240.198.0/24", - "54.231.232.0/21", - "52.219.20.0/22", - "52.219.24.0/21"] - - args = parse_args() - - ip_objects = list(netaddr.IPNetwork(ip) for ip in ips) - - if args.list: - print list_all_waf_valid_subnets(ip_objects) - else: - return translate_and_apply_to_waf(ip_objects, args) - -if __name__ == '__main__': - main() diff --git a/Tools/build/JenkinsScripts/distribution/Installer/BootstrapperLogo.png b/Tools/build/JenkinsScripts/distribution/Installer/BootstrapperLogo.png deleted file mode 100644 index d2539dd509..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/BootstrapperLogo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45c80fc02c64747d3eb8fe76d89979b573401b92482c27d8c95bd01df22c525f -size 6582 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstaller.py b/Tools/build/JenkinsScripts/distribution/Installer/BuildInstaller.py deleted file mode 100755 index 525a8dd7ad..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstaller.py +++ /dev/null @@ -1,289 +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. -# - -import glob -import shutil -import InstallerParams -from Insignia import * -from InstallerArgs import * -from InstallerPackaging import * -from Light import * -from SignTool import * - - -# Per Installer: -# Heat the includes to build the fragment -# candle + light to build the installer / merge module / whatever -# Collect the results -# If Signing: -# Copy installer and cabs to a clean folder -# Sign the CAB files -# insignia the installer to update its cab file references -# Sign the installer -# For the Bootstrapper: -# Generate S3 links or whatever data we need to shove into the final installer. -# Generate a WXS file if we need to based on the above data -# candle + light generated WXS + pre-built WXS to build the installer (from -# the unsigned files or, if signing, the signed files of the installers) -# If Signing: -# Copy bootstrapper and cabs to a clean folder -# Detach the burn engine from the bootstrapper, and sign it -# Reattach the burn engine to the bootstrapper, and sign the bootstrapper -# After completion, clean up temp files if necessary. - - -class OperationMode: - StepCounting, BuildInstaller = range(2) - - # It's good practice to define an init for a class in Python, but this - # class only exists to serve as an enum for the operation mode. - # Defining the __init__ with just a pass is a way to stub out this function so - # Python IDEs don't get upset that there is a class with no init. - def __init__(self): - pass - - -args = createArgs() -try: - params = InstallerParams.InstallerParams(args) - validateArgs(args, params) -except InstallerParams.InstallerParamError as error: - raise Exception('Installer Params failed to be created with error:\n{}'.format(error)) - -# Tracking this like this to simplify calls to performStep. -# Otherwise, it has to look like this: -# def performStep(mode, stepsTaken, maxSteps, message, operation, *operationArgs): -# return stepsTaken+1, result -# and calls to performStep have to also capture the stepsTaken. -stepsTaken = 0 -maxSteps = 0 -operationMode = OperationMode.StepCounting - - -# The goal of authoring this function is to simplify calls in, which reduces friction when using it. -# Call this when you want to only call a function during full operational mode, and not during step counting. -# This will use the function's name as the message for the printout. -def performStep(operation, *operationArgs): - return performStepWithMessage(operation.__name__, operation, *operationArgs) - - -# Call when you want a message that does not match the function's name. -def performStepWithMessage(message, operation, *operationArgs): - global stepsTaken - result = None - if operationMode == OperationMode.BuildInstaller: - printProgress(message, stepsTaken, maxSteps) - result = operation(*operationArgs) - stepsTaken += 1 - return result - - -# Call when you want to handle branching yourself. Can be used to trigger a branch for the operation mode. -def describeStep(message): - global stepsTaken - if operationMode == OperationMode.BuildInstaller: - printProgress(message, stepsTaken, maxSteps) - stepsTaken += 1 - - -def buildInstaller(): - global stepsTaken - stepsTaken = 0 - # CREATE PACKAGES - if not params.skipMsiAndCabCreation: - performStep(createThirdPartyPackages, args, params) - performStep(createDevPackage, args, params) - performStep(createRootPackage, args, params) - else: - describeStep("Skipping Create Packages (MSIs and Cabs) step, re-using existing packages.") - - if not params.doSigning or not args.bootstrapOnly: - params.msiFileNameList = performStepWithMessage("Gathering MSIs", - get_file_names_in_directory, - params.intermediateInstallerPath, - ".msi") - params.cabFileNameList = performStepWithMessage("Gathering CABs", - get_file_names_in_directory, - params.intermediateInstallerPath, - ".cab") - - # SIGN CABs AND MSIs - if params.doSigning and not args.bootstrapOnly: - # we don't want to modify the original metrics exe, so copy it to where the - # other clean files are, and update the path to it - if params.metricsPath is not params.intermediateInstallerPath: - describeStep("Copying metrics to signing path") - if operationMode == OperationMode.BuildInstaller: - params.metricsPath = params.intermediateInstallerPath - safe_shutil_file_copy(params.fullPathToMetrics, os.path.join(params.metricsPath, params.metricsExe)) - - # copy the clean cab and msi files to a new directory to sign them. - if params.installerPath is not params.intermediateInstallerPath: - describeStep("Copying clean MSI, CAB, and EXE files to signing path") - if operationMode == OperationMode.BuildInstaller: - if os.path.exists(params.installerPath): - verbose_print(args.verbose, "Removing old files from signing path.") - shutil.rmtree(params.installerPath) - shutil.copytree(params.intermediateInstallerPath, params.installerPath) - # don't need the wixpdb files in the signing folder, so get rid of them - for filepath in glob.glob(os.path.join(params.installerPath, "*.wixpdb")): - os.remove(filepath) - - # Sign the Cab files, verify signing was successful - performStep(signtoolSignAndVerifyFiles, - params.cabFileNameList, - params.installerPath, - params.intermediateInstallerPath, - params.signingType, - args.timestampServer, - args.verbose) - - # Run Insignia on the MSI files - performStep(insigniaMSIs, - params.installerPath, - args.verbose, - params.msiFileNameList) - - # Sign the MSIs, verify signing was successful - performStepWithMessage("Signing and verifying MSIs", - signtoolSignAndVerifyFiles, - params.msiFileNameList, - params.installerPath, - params.intermediateInstallerPath, - params.signingType, - args.timestampServer, - args.verbose) - - # Sign the Metrics executable - performStepWithMessage("Signing and verifying metrics.exe", - signtoolSignAndVerifyFile, - params.metricsExe, - params.installerPath, - params.intermediateInstallerPath, - params.signingType, - args.timestampServer, - args.verbose) - - # make sure that the bootstrapper will get the metrics exe from the right place - params.metricsPath = params.installerPath - - # CREATE BOOTSTRAP - packageNameList = "" - if operationMode is OperationMode.BuildInstaller: - for msiName in params.msiFileNameList: - packageName = os.path.splitext(msiName)[0] - packageNameList += '{};'.format(packageName) - # Remove the last semi-colon from the list. - packageNameList = packageNameList[:-1] - - # CANDLE BOOTSTRAP - success = performStep(candleBootstrap, - params.bootstrapWixObjDir, - params.installerPath, - packageNameList, - "LumberyardBootstrapper.wxs Redistributables.wxs", - args.hostURL, - args.verbose, - args.lyVersion, - params.metricsPath, - params.metricsExe, - params.pathTo2015Thru2019Redist, - params.redist2015Thru2019Exe, - create_id('LumberyardBootstrapper', 'BOOTSTRAPPER', args.lyVersion, args.buildId)) - - assert (operationMode is not OperationMode.BuildInstaller or success == 0), \ - "Failed to generate wixobj file for bootstrapper." - - # LIGHT BOOTSTRAP - success = performStep(lightBootstrap, - params.bootstrapOutputPath, - os.path.join(params.bootstrapWixObjDir, "*.wixobj"), - args.verbose, - args.cabCachePath) - - assert (operationMode is not OperationMode.BuildInstaller or success == 0), \ - "Failed to generate executable file for bootstrapper." - - # SIGN ENGINE AND BOOTSTRAPPER - if params.doSigning: - # make sure the c++ redist gets copied from the temp directory to the actual - # installer output path with the bootstrapper. - if operationMode == OperationMode.BuildInstaller: - safe_shutil_file_copy(os.path.join(params.tempBootstrapOutputDir, params.redist2015Thru2019Exe), - os.path.join(params.installerPath, params.redist2015Thru2019Exe)) - - unsignedBootstrapPath = os.path.join(params.installerPath, params.tempBootstrapName) - signingBootstrapPath = os.path.join(params.installerPath, params.bootstrapName) - signingEnginePath = os.path.join(params.installerPath, "engine.exe") - if operationMode == OperationMode.BuildInstaller: - shutil.copy(params.bootstrapOutputPath, unsignedBootstrapPath) - - # copy bootstrapper to installerPath? - if operationMode == OperationMode.BuildInstaller and \ - params.installerPath is not params.intermediateInstallerPath and \ - os.path.exists(signingEnginePath): - os.remove(signingEnginePath) - - # extract the engine from the bootstrapper with Insignia - success = performStep(insigniaDetachBurnEngine, - unsignedBootstrapPath, - signingEnginePath, - args.verbose) - assert (operationMode is not OperationMode.BuildInstaller or success == 0), \ - "Failed to detach burn engine from bootstrapper." - - # sign the engine, verify signing was successful - performStep(signtoolSignAndVerifyFile, - signingEnginePath, - params.installerPath, - params.intermediateInstallerPath, - params.signingType, - args.timestampServer, - args.verbose) - - # attach the engine back to the bootstrapper with Insignia - success = performStep(insigniaAttachBurnEngine, - unsignedBootstrapPath, - signingEnginePath, - signingBootstrapPath, - args.verbose) - assert (operationMode is not OperationMode.BuildInstaller or success == -1 or success == 0), \ - "Failed to reattach burn engine to bootstrapper with error {}.".format(success) - - # delete the stray engine file since it has been reattached to the installer - if operationMode is OperationMode.BuildInstaller: - os.remove(signingEnginePath) - os.remove(unsignedBootstrapPath) - - # sign the bootstrapper, verify the signing was successful - performStep(signtoolSignAndVerifyFile, - signingBootstrapPath, - params.installerPath, - params.intermediateInstallerPath, - params.signingType, - args.timestampServer, - args.verbose) - - if args.buildId is not None: - performStep(create_version_file, args.buildId, params.installerPath) - - if not args.keep: - performStep(cleanTempFiles, params) - describeStep("All steps completed") - - -operationMode = OperationMode.StepCounting -maxSteps = 0 -buildInstaller() - -operationMode = OperationMode.BuildInstaller -maxSteps = stepsTaken -buildInstaller() diff --git a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerUtils.py b/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerUtils.py deleted file mode 100755 index d5973a0cc6..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerUtils.py +++ /dev/null @@ -1,206 +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. -# - -import json -import os -import re -import shutil -import uuid -from urllib.parse import urlparse - - -download_url_base = "http://gamedev.amazon.com/lumberyard/releases/" - - -def set_download_url_base(url): - global download_url_base - download_url_base = url - - -def is_url(potential_url): - return urlparse(potential_url)[0] == 'https' - - -def get_package_name(package_path): - path_to_file = package_path - if is_url(package_path): - # index 2 is everything that isn't a parameter in the URL after the high level domain - # see https://docs.python.org/2/library/urlparse.html#urlparse.urlparse for more info - path_to_file = urlparse(package_path)[2] - return os.path.basename(path_to_file) - - -def get_ly_version_from_package(args, unpacked_location): - version = None - path_to_default_settings = os.path.join(unpacked_location, 'dev/_WAF_/default_settings.json') - verbose_print(args.verbose, 'Searching for Lumberyard version in {}'.format(path_to_default_settings)) - with open(path_to_default_settings) as default_settings_file: - default_settings_data = json.load(default_settings_file) - default_settings_file.close() - for build_option in default_settings_data['Build Options']: - if 'attribute' in build_option and 'default_value' in build_option: - if build_option['attribute'] == 'version': - version = build_option['default_value'] - - if version is None: - verbose_print(args.verbose, 'Version not found in package') - raise Exception('Version was not available in default settings.json') - - return version - - -def append_trailing_slash_to_url(url): - if not url.endswith(tuple(['/', '\\'])): - url += '/' - return url - - -def generate_target_url(base_target_url, version, build_id, suppress_version_in_path, append_build_id): - output_url = base_target_url - if append_build_id: - output_url = append_trailing_slash_to_url(output_url) - output_url += build_id - if not suppress_version_in_path: - output_url = append_trailing_slash_to_url(output_url) - output_url += '{}/installer'.format(version) - return output_url - - -# PRODUCT & UPGRADE/PATCH GUID CREATION -def create_id(name, seed, version, build_id): - """ - Generate the Product GUID using the name, the version, and a changelist value. - @param name - Name of the product. - @param seed - String used to create a unique GUID. - @param version - The version of the product in the form "PRODUCT.MAJOR.MINOR.PATCH". - @param build_id - An optional identifier for the build to be used in GUID generation. - @return - A GUID for this version of the product. - """ - # Temporary. Replace the download_url_base with wherever we pass in to the public host or host url. - uuid_seed = download_url_base + seed + name + version - if build_id is not None: - uuid_seed += build_id - return str(uuid.uuid3(uuid.NAMESPACE_URL, uuid_seed)).upper() -# END PRODUCT & UPGRADE/PATCH GUID CREATION - - -def replace_leading_numbers(source_string): - pattern = re.compile(r'^[0-9]') - return pattern.sub('N', source_string) - - -def strip_special_characters(source_string): - """ - Remove all non-alphanumeric characters from the given sourceString. - @return - A new string that is a copy of the original, containing only - letters and numbers. - """ - if source_string.isalnum(): - return source_string - - pattern = re.compile(r'[\W_]+') - return pattern.sub('', source_string) - - -def check_for_empty_subfolders(package_root, allowed_empty_folders): - # find empty folders - empty_folders_found = [] - for root, dirs, files in os.walk(package_root): - if dirs == [] and files == []: - empty_folders_found.append(os.path.normpath(os.path.relpath(root, package_root))) - if allowed_empty_folders is not None: - whitelist_root = 'Whitelist' - whitelist_folders = [] - assert (os.path.exists(allowed_empty_folders)), 'The whitelist file specified at {} does not exist.'.format(allowed_empty_folders) - with open(allowed_empty_folders, 'r') as source: - json_whitelist = json.load(source) - try: - for allowed_folder in json_whitelist[whitelist_root]: - whitelist_folders.append(os.path.normpath(allowed_folder)) - except KeyError: - print('Unknown json root {}, please check the json root specified.'.format(whitelist_root)) - exit(1) - assert (len(whitelist_folders) > 0), 'The whitelist in the file specified at {} is empty. Either populate the list or omit the argument.'.format(allowed_empty_folders) - for folder in empty_folders_found: - assert (folder in whitelist_folders), 'The empty folder {} could not be found in the whitelist of empty folders.'.format(folder) - - -def get_immediate_subdirectories(root_dir): - """ - Create a list of all directories that exist in the given directory, without - recursing through the subdirectories' children. - @param root_dir - The directory to search for subdirectories. - @return - A list of subdirectories in this directory, excluding their children. - """ - directories = [] - for directory in os.listdir(root_dir): - if os.path.isdir(os.path.join(root_dir, directory)): - directories.append(directory) - - return directories - - -def get_file_names_in_directory(directory, file_extension=None): - """ - Create a list of all files in a directory. If given a file extension, it - will list all files with that extension. - @param directory - The directory to gather files from. - @param file_extension - (Optional) The type of files to find. Must be a - string in the ".extension" format. (Default None) - @retun - A list of names of all files in this directory (that match the given - extension if provided). - """ - file_list = [] - if file_extension: - for file in os.listdir(directory): - if file.endswith(file_extension): - file_list.append(os.path.basename(file)) - else: - for file in os.listdir(directory): - file_list.append(os.path.basename(file)) - - return file_list - - -# VERBOSE RELATED FUNCTIONS - -def verbose_print(isVerbose, message): - if isVerbose: - print(message) - - -def find_file_in_package(packageRoot, fileToFind, pathFilters=None): - """ - Searchs the package path for a file. - @param packageRoot: Path to the root of content. - @param fileToFind: Name of the file to find. - @param pathFilters: Path filter to apply to find. - @return: The full path to the file if found, otherwise None. - """ - for root, dirs, files in os.walk(packageRoot): - if fileToFind in files: - if pathFilters is None or any(pathFilter in root for pathFilter in pathFilters): - return os.path.join(root, fileToFind) - return None - - -def safe_shutil_file_copy(src, dst): - # need to remove the old version of dst if it already exists due to a bug - # in shutil.copy that causes both the src and dst files to be zeroed out - # if they are identical files. - if os.path.exists(dst): - os.remove(dst) - shutil.copy(src, dst) - - -def create_version_file(buildId, installerPath): - with open(os.path.join(installerPath, 'version.txt'), 'w') as versionFile: - versionFile.write(buildId) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerWixUtils.py b/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerWixUtils.py deleted file mode 100755 index 5c5785ef18..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/BuildInstallerWixUtils.py +++ /dev/null @@ -1,85 +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. -# - -import glob -import os -import shutil -from BuildInstallerUtils import * - - -def boolToWixBool(value): - """ - WiX uses strings "yes" and "no" for their boolean values. - @return - "yes" if value == True, otherwise "no". - """ - if value: - return "yes" - else: - return "no" - - -def createPackageInfo(directoryName, rootDirectory, outputDirectory, outputPrefix=""): - """ - Generate commonly used information about a package that is used for WiX functions. - @param directoryName - The name of the directory that will be packaged. - @param rootDirectory - The path to the given package. - @param outputDirectory - The full path (including file name) to the wxs file - generated for this package. - @param outputPrefix - A string to append to the beginning of the name of the - package when creating the output file. (Default = ""). - @return - A dictionary containing the package name, source information, and - output information. - """ - safeDirectoryName = directoryName - if not safeDirectoryName: - safeDirectoryName = "packageRoot" - moduleName = strip_special_characters(safeDirectoryName) - sourceDirectory = os.path.join(rootDirectory, directoryName) - wxsName = '{}{}'.format(outputPrefix, moduleName) - outputPath = os.path.join(outputDirectory, '{}.wxs'.format(wxsName)) - componentGroupRef = '{}CG'.format(replace_leading_numbers(wxsName)) - - packageInfo = { - 'name': moduleName, - 'wxsName': wxsName, - 'wxsPath': outputPath, - 'sourceName': safeDirectoryName, - 'sourcePath': sourceDirectory, - 'componentGroupRefs': componentGroupRef - } - return packageInfo - - -def getVerboseCommand(verboseMode): - if verboseMode: - return " -v" - else: - return "" - - -def printProgress(message, stepCount, maxSteps): - # We want the step count to line up at the end to the total steps, so add one. - print('{}/{}: {}'.format(stepCount + 1, maxSteps, message)) - - -def cleanTempFiles(params): - dirs_to_delete = [ - params.wxsRoot, - params.wixObjOutput, - params.bootstrapWixObjDir, - params.tempBootstrapOutputDir, - ] - - for del_dir in dirs_to_delete: - if os.path.exists(del_dir): - shutil.rmtree(del_dir) - for filepath in glob.glob(os.path.join(params.intermediateInstallerPath, "*.wixpdb")): - os.remove(filepath) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/Candle.py b/Tools/build/JenkinsScripts/distribution/Installer/Candle.py deleted file mode 100755 index 8a115640e5..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/Candle.py +++ /dev/null @@ -1,145 +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. -# - -import os -from BuildInstallerWixUtils import * - -# CANDLE COMMANDLINE TEMPLATES -candleCommandBase = "candle.exe -nologo -o {outputDirectory} {verbose} {preprocessorParams} {wxsFile}" -candlePackagePreprocessor = " -dProductGUID={productGUID} -dProductUpgradeGUID={upgradeCodeGUID}" \ - " -dLumberyardVersion={lumberyardVersion}" \ - " -dCabPrefix={cabPrefix}" \ - " -dComponentGroupRefs={packageComponentGroup}" \ - ' -dComponentRefs={componentRefs} -dPackageName="{packageName}"' -candleDownloadPreprocessor = " -dROOTURL={downloadURL}" -candleBootstrapPreprocessor = "-dLYInstallerPath={installerPath} -dLYInstallerNameList={installerList}" \ - " -dLumberyardVersion={lumberyardVersion}" \ - " -dUseStreaming={useStreaming}" \ - ' -dMetricsSourcePath="{metricsSourcePath}"' \ - ' -dMetricsExeName="{metricsExe}"' \ - ' -dPathTo2015Thru2019Redist="{pathTo2015Thru2019Redist}"' \ - ' -dFilename2015Thru2019Redist="{redist2015Thru2019Exe}"' \ - " -dUpgradeCode={upgradeGUID} -ext WixBalExtension -ext WixUtilExtension" -usedCabPrefixList = set() - - -def candlePackageContent(outputDir, wxsPath, verboseMode): - verboseCmd = getVerboseCommand(verboseMode) - candleCommand = candleCommandBase.format(outputDirectory=os.path.join(outputDir, ''), - verbose=verboseCmd, preprocessorParams="", wxsFile=wxsPath) - - verbose_print(verboseMode, '\n{}\n'.format(candleCommand)) - return os.system(candleCommand) - - -def candleAllPackagesContent(packageInfoMap, wixobjDir, verboseMode): - for packageInfo in packageInfoMap.values(): - outputDir = os.path.join(wixobjDir, packageInfo['wxsName']) - success = candlePackageContent(outputDir, packageInfo['wxsPath'], verboseMode) - assert (success == 0), 'Failed to generate wixobj file for {} content.'.format(packageInfo['name']) - - -# Cab prefixes have to be less than 8 characters, including the sequential numbers for multiple cabs. -# To give room for multiple cabs for an MSI, we're dropping down to 5 characters. -# When we strip some paths in 3rd party to 5 characters, they collide, so we do a little extra -# Logic to help with collisions. -def generateCabPrefix(packageName): - # We want a cab prefix length of five to give room for 100+ cabs for an MSI - cabPrefixLength = 5 - - uniquenessIndex = -1 - uniquenessValue = 0 - cabName = packageName[:cabPrefixLength] - - # If there is a cab name collision when two packages truncate to the same five digit - # value, then we want to fiddle with the cab prefix to get something unique. - # This simple logic starts at the last character in the prefix and replaces it with a numeral - # it keeps trying that, and moving earlier in the string as it does so. - while cabName in usedCabPrefixList: - cabName = cabName[:cabPrefixLength+uniquenessIndex] + str(uniquenessValue) + cabName[cabPrefixLength+uniquenessIndex+1:] - uniquenessValue += 1 - if uniquenessValue > 9: - uniquenessValue = 0 - uniquenessIndex -= 1 - if uniquenessIndex <= -cabPrefixLength: - raise Exception("Could not generate unique cab name for {}".format(packageName)) - - usedCabPrefixList.add(cabName) - return cabName - - -def candlePackage(outputDir, wxsTemplatePath, packageInfo, verboseMode, lyVersion, buildId): - verboseCmd = getVerboseCommand(verboseMode) - - cabPrefix = generateCabPrefix(packageInfo['name']) - productGUID = create_id(packageInfo['name'], 'PRODUCT', lyVersion, buildId) - productUpgradeGUID = create_id(packageInfo['name'], 'PRODUCTUPDATE', lyVersion, buildId) - componentRefs = packageInfo.get('componentRefs', '') - - candlePreprocessor = candlePackagePreprocessor.format(productGUID=productGUID, - upgradeCodeGUID=productUpgradeGUID, - lumberyardVersion=lyVersion, - componentRefs=componentRefs, - cabPrefix=cabPrefix, - packageComponentGroup=packageInfo['componentGroupRefs'], - packageName=packageInfo['sourceName']) - - candleCommand = candleCommandBase.format(outputDirectory=outputDir, - verbose=verboseCmd, - preprocessorParams=candlePreprocessor, - wxsFile=wxsTemplatePath) - - verbose_print(verboseMode, '\n{}\n'.format(candleCommand)) - return os.system(candleCommand) - - -def candlePackages(packageInfoMap, wixobjDir, wxsTemplatePath, verboseMode, lyVersion, buildId): - for packageInfo in packageInfoMap.values(): - outputDir = os.path.join(wixobjDir, packageInfo['wxsName'], 'HeatPackage{}.wixobj'.format(packageInfo['wxsName'])) - success = candlePackage(outputDir, wxsTemplatePath, packageInfo, verboseMode, lyVersion, buildId) - assert (success == 0), 'Failed to generate wixobj file for {}.'.format(packageInfo['name']) - - -def candleBootstrap(outputDir, - installersPath, - installerNameList, - wxsFileName, - downloadURL, - verboseMode, - lyVersion, - metricsSourcePath, - metricsExe, - pathTo2015Thru2019Redist, - redist2015Thru2019Exe, - upgradeCodeGUID): - verboseCmd = getVerboseCommand(verboseMode) - useStreaming = downloadURL is not None - useStreamingText = boolToWixBool(useStreaming) - candlePreprocessor = candleBootstrapPreprocessor.format(installerPath=os.path.join(installersPath, ''), - installerList=installerNameList, - lumberyardVersion=lyVersion, - useStreaming=useStreamingText, - upgradeGUID=upgradeCodeGUID, - metricsSourcePath=metricsSourcePath, - metricsExe=metricsExe, - pathTo2015Thru2019Redist=pathTo2015Thru2019Redist, - redist2015Thru2019Exe=redist2015Thru2019Exe) - if useStreaming: - # The WXS file appends the trailing slash before the package name: "$(var.ROOTURL)/{2}" - # We need to strip the trailing slash here if it was passed in with one. - downloadURL = downloadURL.rstrip('/') - candlePreprocessor += candleDownloadPreprocessor.format(downloadURL=downloadURL) - - candleCommand = candleCommandBase.format(outputDirectory=outputDir, verbose=verboseCmd, - preprocessorParams=candlePreprocessor, wxsFile=wxsFileName) - - verbose_print(verboseMode, '\n{}\n'.format(candleCommand)) - return os.system(candleCommand) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/Heat.py b/Tools/build/JenkinsScripts/distribution/Installer/Heat.py deleted file mode 100755 index b20956df17..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/Heat.py +++ /dev/null @@ -1,257 +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. -# - -import os -import sys -import traceback -import xml.etree.ElementTree as ET - -from BuildInstallerWixUtils import * - -# HEAT COMMANDLINE TEMPLATES -heatCommandBase = 'heat.exe {harvestType} "{harvestSource}" -nologo -sreg -gg' -heatCommandRequiredArgs = " -dr {directoryRef} -cg {componentGroup} -out {outputPath}" - - -def convertToForwardSlashAndLower(pathString): - """ - Used to ensure path strings are formatted in a consistent manner. - """ - return pathString.replace('\\', '/').lower() - - -def lowerDictValues(dictToLower): - """ - Used to lower-case all values in the given dictionary. - """ - for key in dictToLower.keys(): - if isinstance(dictToLower[key], list): - dictToLower[key][:] = [convertToForwardSlashAndLower(valueStr) for valueStr in dictToLower[key]] - - -def removeWxsEntriesWithJsonDirFilelist(wxsFilepath, jsonDirFilelist, directoryKey): - """ - Removes entries from the given *.wxs file with the given jsonDirFilelist. - @param wxsFilepath - Path to *.wxs file to operate the given jsonDirFilelist against - @param jsonDirFilelist - Dictionary populated from given "dirFilelist" JSON. Files - in the *.wxs files that don't have corresponding entries in dirFilelist will be - removed from the *.wxs XML content. - """ - # Without registering the namespace, the ET XML serialized output - # is pretty funky, and WiX will not be happy. - namespaceStr = 'http://schemas.microsoft.com/wix/2006/wi' - ET.register_namespace('', namespaceStr) - tree = ET.ElementTree() - tree.parse(wxsFilepath) - xmlRoot = tree.getroot() - - # Find all Component tags that have File tags - ns = {'wixns': namespaceStr} - componentGroupList = xmlRoot.findall('.//wixns:ComponentGroup', ns) - for componentGroup in componentGroupList: - componentList = componentGroup.findall('.//wixns:Component[wixns:File]', ns) - - for component in componentList: - for childFileTag in component: - # Entries are typically prefixed with an unnecessary 'SourceDir\' string - sourceValue = convertToForwardSlashAndLower(childFileTag.attrib['Source']).replace('sourcedir/', '') - if sourceValue not in jsonDirFilelist[directoryKey]: - component.remove(childFileTag) - - # WXS files generated by our installer typically only have one File tag per - # ComponentGroup, but we'll check that it's empty, just in case. - if len(component.getchildren()) < 1: - componentGroup.remove(component) - - tree.write(wxsFilepath) - - -def heatDirectory(wxsName, sourceDirectory, outputPath, componentGroup, directoryRefName, verbose): - """ - Generate a .wxs file for a given directory, including all subdirectories, - and place it at the given outputPath. - @remarks - Intentionally hardcoding harvest type to "dir" here. For other - types of harvests, a new function should be created. Any logic not - directly related to executing the heat command should exist outside this - function. - """ - verboseCmd = getVerboseCommand(verbose) - - # Intentionally hardcoding harvest type to "dir" here. For other types of harvests, a new - # function should be created. Any logic not directly related to executing - # the heat command should exist outside this function. - heatCommand = heatCommandBase.format(harvestType="dir", - harvestSource=sourceDirectory) - heatCommand += verboseCmd - heatCommand += heatCommandRequiredArgs.format(directoryRef=directoryRefName, - componentGroup=componentGroup, outputPath=outputPath) - - verbose_print(verbose, '\n{}\n'.format(heatCommand)) - return os.system(heatCommand) - - -def heatDirectories(rootDirectory, outputDirectory, directoryRefName, verbose, outputPrefix="", dirFilelist=None): - """ - Generates package info for every directory in the given rootDirectory, and - gathers each package's content information into a .wxs file. - @param rootDirectory - The directory containing the source of many packages. - @param outputDirectory - The directory to put all generated .wxs files. - @param directoryRefName - The ID of the directory for these source files to - be placed when installed. (Must match HeatPackageBase directory ID.) - @param verbose - Running in verbose mode? - @param outputPrefix - A string to append to the beginning of the name of the - package when creating the output file. (Default = ""). - @param dirFilelist - A string that gives a path to a JSON file containing a - list of directories, and for each directory, a list of files. Only the - files listed in the JSON file will be included in the installer output - for the directory specified. This can be used to remove unnecessary - files that aren't needed on a customer's machine, but are included in a - packaged build created by Jenkins, for example. - @return - A dictionary of package names to their associated package information (dictionaries). - """ - - # Attempt to parse jsonDirFilelist JSON. - jsonDirFilelist = {} - if dirFilelist is not None: - assert (os.path.exists(dirFilelist)), 'The "dirFilelist" argument was provided but the JSON file at {} does not exist.'.format(dirFilelist) - with open(dirFilelist, 'r') as source: - try: - jsonDirFilelist = json.load(source) - except ValueError as e: - print(traceback.format_exc()) - print('Error parsing the given JSON file at {} with exception: {}'.format(dirFilelist, e)) - sys.exit() - except: - print(traceback.format_exc()) - print('Unexpected error parsing the given JSON file at {}. Please verify that the file is correctly formatted.'.format(dirFilelist)) - sys.exit() - - combinedWxsResults = {} - jsonValuesLowered = False - - for directoryName in get_immediate_subdirectories(rootDirectory): - packageInfo = createPackageInfo(directoryName, rootDirectory, outputDirectory, outputPrefix) - - moduleName = packageInfo['name'] - sourceDirectory = packageInfo['sourcePath'] - wxsName = packageInfo['wxsName'] - outputPath = packageInfo['wxsPath'] - # There will only be one component group in the reference list at this point. - componentGroup = packageInfo['componentGroupRefs'] - - # check for existence of name collision - if moduleName in combinedWxsResults: - print('ERROR when creating module "{0}" from "{1}". A module with the name "{0}" already exists.'.format(moduleName, sourceDirectory)) - # Passing let us rapidly iterate on this tool, feel free to upgrade to raising an exception. - pass - - combinedWxsResults[moduleName] = packageInfo - success = heatDirectory(wxsName, sourceDirectory, outputPath, componentGroup, directoryRefName, verbose) - assert (success == 0), 'Failed to generate WXS file for {}.'.format(moduleName) - - sourceDirFormatted = convertToForwardSlashAndLower(sourceDirectory) - for key in jsonDirFilelist.keys(): - if sourceDirFormatted.endswith(convertToForwardSlashAndLower(key)): - - # Lower-case all entries to allow case-insensitive compare - if not jsonValuesLowered: - lowerDictValues(jsonDirFilelist) - jsonValuesLowered = True - - # Alter XML contents of WXS file by filtering it against the JSON - # directory list of files. - removeWxsEntriesWithJsonDirFilelist(outputPath, jsonDirFilelist, key) - - return combinedWxsResults - - -def heatFile(file, - directoryRefName, - rootDirectory, - verbose, - componentGroup, - outputPath): - """ - Generates a WXS file for an individual file. - @param file: Full path to the file to heat. - @param directoryRefName: The ID of the directory for these source files to - be placed when installed. (Must match HeatPackageBase directory ID.) - @param verbose: Running in verbose mode? - @param componentGroup: The component group to set in the file. - @param outputPath: Where to output the generated WXS file. - @return: - """ - heatCommand = heatCommandBase.format(harvestType="file", harvestSource=file) - heatCommand += getVerboseCommand(verbose) - # According to Wix's docs ( http://wixtoolset.org/documentation/manual/v3/overview/heat.html ) - # SRD's description implies that it suppresses root directory harvesting, which seems to imply it works only - # in directory harvesting mode. It also implies that it takes in no parameters. - # This is either poor documentation, or incorrect (I'm assuming poor documentation). - # The actual behavior is: - # Normally when harvesting with Heat (directory or file), directories and directory references are generated - # based on the path to the root directory. By calling suppress root directory harvesting and passing in a directory, - # then the generated nested directory path in the generated wxs file will not include pathing based on this. - # This is necessary when harvesting the loose files in a folder's root: Heat's harvesting does not support - # whitelist / blacklist functionality, and all subfolders of the package have been harvested in other ways. - # This means that all of the loose files in the directory roots that weren't included elsewhere need to be - # included in some other installers. If the root directory is not suppressed, then they generate a directory - # hierarchy that collides with each other. - heatCommand += " -srd " + rootDirectory - heatCommand += heatCommandRequiredArgs.format(directoryRef=directoryRefName, - componentGroup=componentGroup, - outputPath=outputPath) - - verbose_print(verbose, '\n{}\n'.format(heatCommand)) - return os.system(heatCommand) - - -def heatFiles(fileList, - rootDirectory, - outputDirectory, - directoryRefName, - verbose, - outputPrefix = ""): - """ - Generates WXS files for every file in the file list, and returns a mapping containing the associated - WXS files and component groups. - @param fileList: The list of files to generate WXS files for. - @param outputDirectory: The directory to put generated WXS files. - @param directoryRefName: The ID of the directory for these source files to - be placed when installed. (Must match HeatPackageBase directory ID.) - @param verbose: Running in verbose mode? - @param outputPrefix: A string to append to the beginning of the name of the - package when creating the output file. (Default = ""). - @return: A dictionary of input files to their associated WXS information (component group, WXS file location). - """ - combinedWxsResults = {} - for file in fileList: - moduleName = strip_special_characters(file) - wxsName = '{}{}'.format(outputPrefix, moduleName) - outputPath = os.path.join(outputDirectory, '{}.wxs'.format(wxsName)) - componentGroup = '{}CG'.format(replace_leading_numbers(strip_special_characters(file))) - - wxsInfo = { - 'name': moduleName, - 'wxsName': wxsName, - 'wxsPath': outputPath, - 'componentGroupRefs': componentGroup - } - combinedWxsResults[file] = wxsInfo - - success = heatFile(os.path.join(rootDirectory,file), - directoryRefName, - rootDirectory, - verbose, - componentGroup, - outputPath) - assert (success == 0), 'Failed to generate WXS file for {}.'.format(moduleName) - - return combinedWxsResults diff --git a/Tools/build/JenkinsScripts/distribution/Installer/HeatDevPackageBase.wxs b/Tools/build/JenkinsScripts/distribution/Installer/HeatDevPackageBase.wxs deleted file mode 100644 index f8636bf10c..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/HeatDevPackageBase.wxs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:92fb31b309b613d1f47feb3a728d4528d11d27d9a5e539b109800e209cab0580 -size 5754 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/HeatPackageBase.wxs b/Tools/build/JenkinsScripts/distribution/Installer/HeatPackageBase.wxs deleted file mode 100644 index 0a8ae95f2e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/HeatPackageBase.wxs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e708bd9a6e9191431ecc5840e6adaf3f4e5ca52f3f994acefa454bb908476c97 -size 5435 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/Insignia.py b/Tools/build/JenkinsScripts/distribution/Installer/Insignia.py deleted file mode 100755 index cf419af687..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/Insignia.py +++ /dev/null @@ -1,67 +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. -# - -import os -from BuildInstallerWixUtils import * - -# Insignia COMMANDLINE TEMPLATES -insigniaCommandBase = "insignia.exe -nologo {verbose} {commandType} {filename} {commandTypeParams}" -insigniaDetachEngineParams = "-o {outputPath}" -insigniaAttachEngineParams = "{bootstrapName} -o {outputPath}" - - -def insigniaMSI(filename, verbose): - verboseCmd = getVerboseCommand(verbose) - insigniaCommand = insigniaCommandBase.format(verbose=verboseCmd, - commandType="-im", filename=filename, commandTypeParams="") - - verbose_print(verbose, '\n{}\n'.format(insigniaCommand)) - return os.system(insigniaCommand) - - -def insigniaMSIs(directory, verbose, fileList=None): - if fileList is None: - for file in os.listdir(directory): - if file.endswith(".msi"): - success = insigniaMSI(file, verbose) - assert (success == 0), "Failed to update {} with the signed CAB files' information.".format(os.path.basename(file)) - else: - for file in fileList: - filepath = os.path.join(directory, file) - success = insigniaMSI(filepath, verbose) - assert (success == 0), "Failed to update {} with the signed CAB files' information.".format(os.path.basename(file)) - - -def insigniaDetachBurnEngine(bootstrapName, engineName, verbose): - verboseCmd = getVerboseCommand(verbose) - - insigniaParams = insigniaDetachEngineParams.format(outputPath=engineName) - insigniaCommand = insigniaCommandBase.format(verbose=verboseCmd, - commandType="-ib", - filename=bootstrapName, - commandTypeParams=insigniaParams) - - verbose_print(verbose, '\n{}\n'.format(insigniaCommand)) - return os.system(insigniaCommand) - - -def insigniaAttachBurnEngine(bootstrapName, engineName, outputName, verbose): - verboseCmd = getVerboseCommand(verbose) - - insigniaParams = insigniaAttachEngineParams.format(outputPath=outputName, - bootstrapName=bootstrapName) - insigniaCommand = insigniaCommandBase.format(verbose=verboseCmd, - commandType="-ab", - filename=engineName, - commandTypeParams=insigniaParams) - - verbose_print(verbose, '\n{}\n'.format(insigniaCommand)) - return os.system(insigniaCommand) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/InstallerArgs.py b/Tools/build/JenkinsScripts/distribution/Installer/InstallerArgs.py deleted file mode 100755 index 5d131dc064..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/InstallerArgs.py +++ /dev/null @@ -1,115 +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. -# - -import argparse -import BuildInstallerUtils -from SignTool import * -import os -import tempfile -import ctypes - - -def createArgs(): - defaultTempLocation = os.path.join(tempfile.gettempdir(), "LYPackage") - - parser = argparse.ArgumentParser(description='Builds the WiX based Lumberyard Installer for Windows.') - # PRIMARY ARGS - many if not all will be used in production - # INPUT/OUTPUT - parser.add_argument('--packageRoot', default=None, help="Path to the root of the package (default None)") - parser.add_argument('--genRoot', default=defaultTempLocation, help="Path for temp data (default Python's temp directory + '/LYPackage')") - parser.add_argument('--allowedEmptyFolders', default=None, help="Path to a JSON file containing a list of empty folders that are allowed to exist in --packageRoot") - # The default is applied in Build - parser.add_argument('--bootstrapName', default=None, help="Bootstrap name (default 'LumberyardInstaller{}.exe'.format(args.lyVersion))") - parser.add_argument('--metricsExe', default=None, help="Override path to metrics executable, if not provided this script will search for LyInstallerMetrics.exe in the package root (default None)") - # VERSION & GUID - parser.add_argument('--lyVersion', default="0.2.2.1", help="Lumberyard Version (default '0.2.2.1')") - parser.add_argument('--buildId', default=None, help="The build number of the package that the installer was made from. If not provided, there will be no version file created in the output. (default None)") - # SIGNING - # more information on the step by step details can be found at: - # https://wiki.labcollab.net/confluence/display/lmbr/Sign+Lumberyard+Binaries - parser.add_argument('--privateKey', default=None, help="The signing private key to use to sign the output of this script. Will only attempt to sign if this switch or --certName is specified. Use only one of these two switches. (default None)") - parser.add_argument('--password', default=None, help="The password for using the signing private key. Must include this if signing should occur. (default None)") - parser.add_argument('--certName', default=None, help="The subject name of the signing certificate to use to sign with. Will only attempt to sign if this switch or --privateKey is specified. Use only one of these two switches. (default None)") - parser.add_argument('--timestampServer', default="http://tsa.starfieldtech.com", help="The timestamp server to use for signing. (default http://tsa.starfieldtech.com)") - # VERBOSE OUTPUT - parser.add_argument('-v', '--verbose', action='store_true', help='Enables logging messages (default False)') - # URL INFO - parser.add_argument('--hostURL', default=None, help='The URL for the installer to download its packages from (msi + cab files). No URL implies the files will be on local disk already. (default None)') - # RAPID ITERATION ARGS - parser.add_argument('--bootstrapOnly', action='store_true', help="Only create a bootstrapper. Will assume packageRoot contains all necessary MSIs and CABs. Ignores cabCachePath if it was provided.") - parser.add_argument('--signOnly', action="store_true", help="Will sign already existing CAB and MSI files. Will then generate a bootstrapper with those signed MSIs, and sign the bootstrapper.") - parser.add_argument('--cabCachePath', default=None, help='Path to a cache of the cab files. Should only be used if no new packages are being added, and everything already has cabs built. (default None)') - parser.add_argument('-k', '--keep', action='store_true', help="Don't delete temp files") - parser.add_argument('--dirFilelist', default=None, help="A list of files (by directory) to include in the install content.") - args = parser.parse_args() - print("Installer arguments:") - print(args) - - # don't allow ambiguity of which way to sign. Have to do this here as we need to only create one SignType to keep in the params object - assert (args.privateKey is None or args.certName is None), "Both a private key and a certificate name was provided, introducing ambiguity. Please only specify one way to sign." - - return args - - -def validateArgs(args, params): - assert (args.hostURL is not None), "No URL to provide to the bootstrapper was given. Please use --hostURL to specify where the bootstrapper will download the MSI and CAB files from." - - # find empty folders - BuildInstallerUtils.check_for_empty_subfolders(args.packageRoot, args.allowedEmptyFolders) - - # BootstrapOnly validation - if args.bootstrapOnly: - assert (not args.cabCachePath), "Error: Ignoring cabCachePath since bootstrapOnly was specified. Please choose one to use." - if args.packageRoot: - print("Warning: Specifying packageRoot with bootstrapOnly. Base package not used in bootstrapOnly builds.") - # make sure there are MSI files in the installer directory - hasInstallerFiles = False - for file in os.listdir(params.intermediateInstallerPath): - hasInstallerFiles = file.endswith(".msi") or file.endswith(".cab") - if hasInstallerFiles: - return - assert hasInstallerFiles, "The packageRoot given ({}) does not contain any MSI or CAB files. When using bootstrapOnly, packageRoot should point to the directory with MSIs and CAB files.".format(params.intermediateInstallerPath) - - # Make sure metrics and Visual Studio 2015-2019 redist exist somewhere - assert (params.fullPathToMetrics is not None), "Metrics executable path was not provided and was not found in the package." - assert (os.path.exists(params.fullPathToMetrics)), "Metrics executable expected at {}, but cannot be found.".format(params.fullPathToMetrics) - assert (params.fullPathTo2015Thru2019Redist is not None), "Visual Studio 2015-2019 redist could not be found in the package." - assert (os.path.exists(params.fullPathTo2015Thru2019Redist)), "Visual Studio 2015-2019 redist expected at {}, but cannot be found.".format(params.fullPathTo2015Thru2019Redist) - - # Signing parameter asserts - if params.doSigning: - # Installation requires administration privileges. - try: - is_admin = os.getuid() == 0 - except AttributeError: - is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0 - assert is_admin, "Administrator privileges must be enabled to sign an installer." - - if args.privateKey is not None: - # make sure that private key is valid and we were given a password to use. - assert (os.path.exists(args.privateKey)), "No private key exists at the given path." - assert (args.privateKey.endswith(".pfx")), "The file at {} is not a signing private key.".format(args.privateKey) - assert (args.password is not None), "Must include the password needed for the signing private key to sign." - # if --certName is specified, the verification of that name being valid must be done prior to this script being run, as it is platform dependent. - - # Make sure that all CABs and MSI files are signed if only the bootstrapper needs to be built. - if args.bootstrapOnly: - for filename in params.msiFileNameList: - signed = signtoolVerifySign(os.path.join(params.installerPath, filename), args.verbose) - assert signed, "Not all MSI and CAB files in {} are verified to have been signed. Please use --signOnly instead.".format(params.installerPath) - for filename in params.cabFileNameList: - signed = signtoolVerifySign(os.path.join(params.installerPath, filename), args.verbose) - assert signed, "Not all MSI and CAB files in {} are verified to have been signed. Please use --signOnly False instead.".format(params.installerPath) - signed = signtoolVerifySign(params.fullPathToMetrics, args.verbose) - assert signed, "Metrics executable at {} is not verified to have been signed. Please either create a signed executable or use --signOnly instead.".format(params.fullPathToMetrics) - - if args.signOnly: - assert params.doSigning, "Cannot specify --signOnly if not given a private key and password, or a certificate name for signing." diff --git a/Tools/build/JenkinsScripts/distribution/Installer/InstallerAutomation.py b/Tools/build/JenkinsScripts/distribution/Installer/InstallerAutomation.py deleted file mode 100755 index 12309533fd..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/InstallerAutomation.py +++ /dev/null @@ -1,273 +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. -# - -import argparse -import os -import re -import shutil -import time -import zipfile -from urllib.parse import urlparse -from urllib.request import urlopen - -import BuildInstallerUtils -import PackageExeSigning -import SignTool -import boto3 - - -def getCloudfrontDistDomain(uploadURL): - return urlparse(uploadURL)[1] - - -def getCloudfrontDistPath(uploadURL): - pathFromDomainName = urlparse(uploadURL)[2] - return pathFromDomainName[1:] # need to remove the first slash, otherwise it will create a nameless directory on S3 - - -def testSigningCredentials(args): - # there are no credentials to test when certName was specified. - if args.certName is not None: - return True - - result = SignTool.signtoolTestCredentials(args.signingType, - args.timestampServer, - False) - return result - - -defaultFilesToSign = ["dev/Tools/LmbrSetup/Win/SetupAssistant.exe", - "dev/Tools/LmbrSetup/Win/SetupAssistantBatch.exe", - "dev/Bin64vc141/ProjectConfigurator.exe", - "dev/Bin64vc141/lmbr.exe", - "dev/Bin64vc141/Lyzard.exe", - "dev/Bin64vc141/Editor.exe", - "dev/Bin64vc142/ProjectConfigurator.exe", - "dev/Bin64vc142/lmbr.exe", - "dev/Bin64vc142/Lyzard.exe", - "dev/Bin64vc142/Editor.exe"] - -defaultFilesToSignHelpText = 'Additional files to sign, if signing. (default {})'.format(', '.join(defaultFilesToSign)) - - -def createArgs(): - parser = argparse.ArgumentParser(description='Builds the WiX based Lumberyard Installer for Windows.') - parser.add_argument('--packagePath', required=True, help="Path to package, can be url or local.") - parser.add_argument('--workingDir', default="%TEMP%/installerAuto", help="Working directory (default '%%TEMP%%/installerAuto')") - parser.add_argument('--allowedEmptyFolders', default=os.path.join(os.path.dirname(os.path.abspath(__file__)), "allowed_empty_folders.json"), help="The JSON file containing the whitelist of empty folders that we expect in the source package.") - parser.add_argument('--targetURL', required=True, help="Target URL to download the installer from.") - parser.add_argument('--awsProfile', default=None, help='The aws cli profile to use to read from from s3 and cloudfront, and upload to s3. (Default None)') # if on a build machine, it will use the IAM role, if local, it will use [default] in aws credentials file. - parser.add_argument('--lyVersion', default=None, help='Specifies the version used to identify the version of LY installed by this installer. Use of this field will ignore the default behavior of reading the value for this field from the default_settings.json file in the package. (DO NOT USE unless you know what you are doing.)') - parser.add_argument('--suppressVersionInPath', action='store_true', help="Suppresses modification to the target paths with a version (default False)") - parser.add_argument('-bi', '--addBuildIdToPath', action='store_true', help="Add the build version to the target paths prepending to the version of Lumberyard, i.e. buildId/version/installer. (default False)") - parser.add_argument('--privateKey', default=None, help="The signing private key to use to sign the output of this script. Will only attempt to sign if this switch or --certName is specified. Use only one of these two switches. (default None)") - parser.add_argument('--certName', default=None, help="The subject name of the signing certificate to use to sign with. Will only attempt to sign if this switch or --privateKey is specified. Use only one of these two switches. (default None)") - parser.add_argument('-v', '--verbose', action='store_true', help='Enables logging messages (default False)') - parser.add_argument('-k', '--keep', action='store_true', help='Keeps temp files (default False)') - parser.add_argument('--timestampServer', default="http://tsa.starfieldtech.com", help="The timestamp server to use for signing. (default http://tsa.starfieldtech.com)") - parser.add_argument('--filesToSign', nargs='+', default=defaultFilesToSign, help=defaultFilesToSignHelpText) - args, unknown = parser.parse_known_args() - print("Installer automation arguments:") - print(args) - return args - - -def validateArgs(args): - args.signingPassword = None - assert (os.path.exists(args.allowedEmptyFolders)), 'The whitelist file specified at {} does not exist.'.format(args.allowedEmptyFolders) - # don't allow ambiguity of which way to sign. Have to do this here as we need to only create one SignType to keep in the params object - assert (args.privateKey is None or args.certName is None), "Both a private key and a certificate name was provided, introducing ambiguity. Please only specify one way to sign." - - args.signingType = None - if args.privateKey is not None: - # get password for signing - import getpass - args.signingPassword = getpass.getpass("Please provide the signing password: ") - args.signingType = SignTool.KeySigning(args.privateKey, args.signingPassword) - elif args.certName is not None: - args.signingType = SignTool.NameSigning(args.certName) - args.doSigning = args.signingType is not None - - if args.doSigning is True: - # Signing requires administration privileges. - import ctypes - try: - is_admin = os.getuid() == 0 - except AttributeError: - is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0 - assert is_admin, "Administrator privileges must be enabled to sign an installer." - assert (testSigningCredentials(args)), "Signing password is incorrect. Failed to sign and verify test file." - - if args.awsProfile: - if args.awsProfile is "": # ANT jobs might pass an empty string to represent None, since ant doesn't have a concept of None or null - args.awsProfile = None - assert (boto3.Session(profile_name=args.awsProfile) is not None), "The AWS CLI profile name specified does not exist on this machine. Please specify an existing AWS CLI profile." - - if args.lyVersion: - # check to make sure the value of lyVersion matches the format #.#.#.# - r = re.compile(r"\d+\.\d+\.\d+\.\d+") - assert (r.match(args.lyVersion) is not None), "The value of lyVersion given is not in the form of '...'. Please input a version with the correct format." - - -def run(args): - expandedWorkingDir = os.path.expandvars(args.workingDir) - expandedPackagePath = os.path.expandvars(args.packagePath) - - unpackedLocation = os.path.join(expandedWorkingDir, 'unpacked') - fileName = BuildInstallerUtils.get_package_name(expandedPackagePath) - downloadFileOnDisk = os.path.join(expandedWorkingDir, fileName) - - # Make sure temp directories exist - BuildInstallerUtils.verbose_print(args.verbose, "Cleaning temp working directories") - if not os.path.exists(expandedWorkingDir): - os.makedirs(expandedWorkingDir) - - if os.path.exists(unpackedLocation): - shutil.rmtree(unpackedLocation) - - os.makedirs(unpackedLocation) - - if os.path.isfile(downloadFileOnDisk): - os.remove(downloadFileOnDisk) - - isDownloadFileTemp = False - # 1. Download zip from S3 if it is an URL - if BuildInstallerUtils.is_url(expandedPackagePath): - isDownloadFileTemp = True - BuildInstallerUtils.verbose_print(args.verbose, "Downloading package {}".format(expandedPackagePath)) - package = urlopen(expandedPackagePath) - with open(downloadFileOnDisk, 'wb') as output: - output.write(package.read()) - elif os.path.isfile(expandedPackagePath): - BuildInstallerUtils.verbose_print(args.verbose, "using on disk package at {}".format(expandedPackagePath)) - downloadFileOnDisk = expandedPackagePath - else: - raise Exception('Could not find package "{}" at path {}'.format(fileName, expandedPackagePath)) - - # 2. Unzip zip file. - BuildInstallerUtils.verbose_print(args.verbose, "Unpacking package to {}".format(unpackedLocation)) - z = zipfile.ZipFile(downloadFileOnDisk, "r") - z.extractall(unpackedLocation) - # Preserver file's original timestamp - for f in z.infolist(): - name, date_time = f.filename, f.date_time - name = os.path.join(unpackedLocation, name) - date_time = time.mktime(date_time + (0, 0, -1)) - os.utime(name, (date_time, date_time)) - z.close() - - # Sign exes in Lumberyard - if args.privateKey is not None or args.certName is not None: - PackageExeSigning.SignLumberyardExes(unpackedLocation, - args.signingType, - args.timestampServer, - args.verbose, - args.filesToSign) - - # 3. Discover Lumberyard version. - buildId = os.path.splitext(fileName)[0] - packageVersion = BuildInstallerUtils.get_ly_version_from_package(args, unpackedLocation) - version = packageVersion - if args.lyVersion: - version = args.lyVersion - BuildInstallerUtils.verbose_print(args.verbose, "Package version is {}, but forcing version to value given for --lyVersion of {}".format(packageVersion, args.lyVersion)) - - BuildInstallerUtils.verbose_print(args.verbose, "Building installer for Lumberyard v{}".format(version)) - - # 4. Build installer. - pathToBuild = os.path.join(expandedWorkingDir, version) - - targetUrl = BuildInstallerUtils.generate_target_url(args.targetURL, version, buildId, args.suppressVersionInPath, args.addBuildIdToPath) - - pathToDirFilelist = os.path.dirname(os.path.realpath(__file__)) + os.sep + 'dir_filelist.json' - - # take the name of the package without the file extension to use as the buildId - buildCommand = "python BuildInstaller.py --packageRoot {} " \ - "--lyVersion {} " \ - "--genRoot {} " \ - "--hostURL {} " \ - "--allowedEmptyFolders {} " \ - "--buildId {} " \ - "--dirFilelist {}".format(unpackedLocation, version, pathToBuild, targetUrl, - args.allowedEmptyFolders, buildId, pathToDirFilelist) - - if args.verbose: - buildCommand += " -v" - if args.keep: - buildCommand += " --keep" - if args.privateKey is not None: - buildCommand += " --privateKey {} --password {}".format(args.privateKey, args.signingPassword) - elif args.certName is not None: - buildCommand += ' --certName "{}"'.format(args.certName) - if args.doSigning: - buildCommand += " --timestampServer {}".format(args.timestampServer) - - BuildInstallerUtils.verbose_print(args.verbose, "Creating build of installer with command:") - BuildInstallerUtils.verbose_print(args.verbose, buildCommand) - build_result = os.system(buildCommand) - assert(build_result == 0), "Running BuildInstaller.py failed with result {}".format(build_result) - BuildInstallerUtils.verbose_print(args.verbose, "Installer creation completed, build is available at {}".format(pathToBuild)) - - # 5. Upload to the proper S3 bucket - # Get the Cloudfront Distribution ID from the URL we expect to download from (targetUrl) - BuildInstallerUtils.verbose_print(args.verbose, "Beginning upload of installer to S3") - session = boto3.Session(profile_name=args.awsProfile) - client = session.client('cloudfront') - targetDomain = getCloudfrontDistDomain(targetUrl) - distributionList = client.list_distributions() - targetDistId = None - for distribution in distributionList["DistributionList"]["Items"]: - if distribution["DomainName"] == targetDomain: - targetDistId = distribution["Id"] - pass - assert (targetDistId is not None), "No distribution with the domain name {} found.".format(targetDomain) - - # Get the s3 bucket info from the Distribution ID, and figure out where we are putting files in the bucket - targetDist = client.get_distribution(Id=targetDistId) - s3Info = targetDist["Distribution"]["DistributionConfig"]["Origins"]["Items"][0] - bucketDomainName = s3Info["DomainName"] - bucketName = bucketDomainName.split('.')[0] # first part of the domain name is the bucket name - BuildInstallerUtils.verbose_print(args.verbose, "S3 bucket associated with targetUrl: {}".format(bucketName)) - originPath = s3Info["OriginPath"] - bucketPath = None - if originPath: - # Start originPath after the first character (presumed to be '/') to avoid nameless directory in S3. - bucketPath = '{}/{}'.format(originPath[1:], getCloudfrontDistPath(targetUrl)) - else: - bucketPath = getCloudfrontDistPath(targetUrl) - BuildInstallerUtils.verbose_print(args.verbose, "Uploading completed installer to S3 location: {}/{}".format(bucketName, bucketPath)) - - # Upload each file to the S3 bucket - s3 = session.resource('s3') - s3Bucket = s3.Bucket(bucketName) - installerOutputDir = None - if args.signingType is not None: - installerOutputDir = os.path.join(pathToBuild, "installer") - else: - installerOutputDir = os.path.join(pathToBuild, "unsignedInstaller") - for file in os.listdir(installerOutputDir): - fullFilePath = os.path.join(installerOutputDir, file) - targetBucketPath = '{}/{}'.format(bucketPath, os.path.basename(file)) - s3Bucket.upload_file(fullFilePath, targetBucketPath) - - if not args.keep: - if os.path.isfile(downloadFileOnDisk) and isDownloadFileTemp: - os.remove(downloadFileOnDisk) - - -def main(): - args = createArgs() - validateArgs(args) - run(args) - - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/Installer/InstallerIcon.ico b/Tools/build/JenkinsScripts/distribution/Installer/InstallerIcon.ico deleted file mode 100644 index 90c6be4582..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/InstallerIcon.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30befe12828ae67d1f3b4a9725c98d910c2190b81caa0f9d919e9c42c432c33a -size 101185 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/InstallerPackaging.py b/Tools/build/JenkinsScripts/distribution/Installer/InstallerPackaging.py deleted file mode 100755 index 6a71900993..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/InstallerPackaging.py +++ /dev/null @@ -1,225 +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. -# - -import os -from Heat import * -from Candle import * -from Light import * -from BuildInstallerWixUtils import * - - -def createLooseFilePackage(args, - params, - packageGroupInfoMap, - path, - wixDirId, - directory, - wixSafePathId): - # DISCOVER LOOSE FILES IN PATH - looseFiles = [] - for (dirpath, dirnames, filenames) in os.walk(path): - looseFiles.extend(filenames) - # Only the files in the root directory need to - # be discovered this way, so break on first result. - break - - # If there are no loose files, there is no package to create. - if not looseFiles: - return False - - # HEAT LOOSE FILES - looseFileMap = heatFiles(looseFiles, - path, - params.wxsRoot, - wixDirId, - args.verbose, - wixSafePathId) - - # CANDLE LOOSE FILES - rootInfo = createPackageInfo(directory, args.packageRoot, params.wxsRoot) - - # There is no general component group for loose files, so clear it out. - rootInfo['componentGroupRefs'] = '' - packageGroupInfoMap[rootInfo['name']] = rootInfo - - candleSubDirectory = directory - if not candleSubDirectory: - candleSubDirectory = wixSafePathId - - for looseFile in looseFileMap: - candlePackageContent(os.path.join(params.wixObjOutput, candleSubDirectory), - looseFileMap[looseFile]['wxsPath'], - args.verbose) - if rootInfo.get('componentGroupRefs', ''): - rootInfo['componentGroupRefs'] += ';' + looseFileMap[looseFile]['componentGroupRefs'] - else: - rootInfo['componentGroupRefs'] = looseFileMap[looseFile]['componentGroupRefs'] - - return True - - -def createThirdPartyPackages(args, params): - """ - Creates a .msi and .cab files for each folder in 3rdParty, and places them at - intermediateInstallerPath to be used when creating the bootstrapper. - @return - A dictionary of the package information that was generated for the - 3rd Party directories. - """ - thirdPartyWixDirId = "THIRDPARTYDIR" - thirdPartyPath = os.path.join(args.packageRoot, "3rdParty") - # HEAT PACKAGE - thirdPartyInfoMap = heatDirectories(thirdPartyPath, params.wxsRoot, - thirdPartyWixDirId, args.verbose, "ThirdParty") - # CANDLE PACKAGE CONTENTS - candleAllPackagesContent(thirdPartyInfoMap, params.wixObjOutput, args.verbose) - - # CREATE PACKAGE INFORMATION FOR LOOSE FILES IN 3RD PARTY ROOT - createLooseFilePackage(args, - params, - thirdPartyInfoMap, - thirdPartyPath, - thirdPartyWixDirId, - "3rdParty", - "ThirdParty") - - # CANDLE PACKAGES - candlePackages(thirdPartyInfoMap, - params.wixObjOutput, - params.heatPackageBase, - args.verbose, - args.lyVersion, - args.buildId) - - # LIGHT PACKAGES - lightPackages(thirdPartyInfoMap, - params.packagesPath, - params.wixObjOutput, - args.verbose, - args.cabCachePath) - - return thirdPartyInfoMap - - -def createRootPackage(args, params): - rootInfoMap = {} - if createLooseFilePackage(args, - params, - rootInfoMap, - os.path.join(args.packageRoot, ""), - "INSTALLDIR", - "", - "packageRoot"): - # CANDLE PACKAGES - candlePackages(rootInfoMap, - params.wixObjOutput, - params.heatPackageBase, - args.verbose, - args.lyVersion, - args.buildId) - rootInfoMap['packageRoot']['sourcePath'] = os.path.abspath(args.packageRoot) - # LIGHT PACKAGES - lightPackages(rootInfoMap, - params.packagesPath, - params.wixObjOutput, - args.verbose, - args.cabCachePath) - - return rootInfoMap - - -def createDevPackage(args, params): - """ - Creates a .msi and .cab files for the dev folder, and places them at - intermediateInstallerPath to be used when creating the bootstrapper. - @return - A dictionary of the package information that was generated for the - dev directory. - """ - devWixDirId = "DEVDIR" - devPath = os.path.join(args.packageRoot, "dev") - - # HEAT PACKAGE - devInfoMap = heatDirectories(devPath, params.wxsRoot, devWixDirId, args.verbose, "dev", args.dirFilelist) - - # CANDLE PACKAGE CONTENTS - candleAllPackagesContent(devInfoMap, params.wixObjOutput, args.verbose) - - # CREATE PACKAGE INFORMATION FOR LOOSE FILES IN DEV ROOT - createLooseFilePackage(args, - params, - devInfoMap, - devPath, - devWixDirId, - "dev", - "dev") - - devInfo = devInfoMap["dev"] - devInfo['componentRefs'] = 'DesktopShortcuts;StartMenuShortcuts;LevelListRegistryKeys' - - # CANDLE PACKAGE - candlePackages(devInfoMap, - params.wixObjOutput, - params.heatPackageBase, - args.verbose, - args.lyVersion, - args.buildId) - - # Build the dev-specific wxs components (for shortcuts) - candlePackage('{}/{}/'.format(params.wixObjOutput, devInfo['name']), - 'HeatDevPackageBase.wxs', - devInfo, - args.verbose, - args.lyVersion, - args.buildId) - - # LIGHT PACKAGE - lightPackages(devInfoMap, - params.packagesPath, - params.wixObjOutput, - args.verbose, - args.cabCachePath) - - return devInfoMap - - -def createRootFolderPackage(args, params, folderName): - """ - Creates a .msi and .cab files for a folder in the package root, like docs, and places them at - intermediateInstallerPath to be used when creating the bootstrapper. - @return - A dictionary of the package information that was generated for the - docs directory. - """ - folderInfo = createPackageInfo(folderName, args.packageRoot, params.wxsRoot) - folderInfoMap = {} - folderInfoMap[folderInfo['name']] = folderInfo - - # HEAT PACKAGE - heatDirectory(folderInfo['wxsName'], folderInfo['sourcePath'], folderInfo['wxsPath'], - folderInfo['componentGroupRefs'], "INSTALLDIR", args.verbose) - - # CANDLE PACKAGE CONTENTS - candleAllPackagesContent(folderInfoMap, params.wixObjOutput, args.verbose) - - # CANDLE PACKAGE - candlePackages(folderInfoMap, - params.wixObjOutput, - params.heatPackageBase, - args.verbose, - args.lyVersion, - args.buildId) - - # LIGHT PACKAGE - lightPackages(folderInfoMap, - params.packagesPath, - params.wixObjOutput, - args.verbose, - args.cabCachePath) - - return folderInfoMap diff --git a/Tools/build/JenkinsScripts/distribution/Installer/InstallerParams.py b/Tools/build/JenkinsScripts/distribution/Installer/InstallerParams.py deleted file mode 100755 index 43259470cf..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/InstallerParams.py +++ /dev/null @@ -1,93 +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. -# - -import os -from SignTool import * - - -class InstallerParamError(Exception): - def __init__(self, value): - self.value = value - - def __str__(self): - return repr(self.value) - - -class InstallerParams(object): - def __init__(self, args): - self.fullPathTo2015Thru2019Redist = None - self.signingType = None - - if args.privateKey is not None: - if not args.password: - import getpass - args.password = getpass.getpass("Please provide the signing password: ") - self.signingType = KeySigning(args.privateKey, args.password) - elif args.certName is not None: - self.signingType = NameSigning(args.certName) - - self.doSigning = self.signingType is not None - - self.wxsRoot = os.path.join(args.genRoot, "wxs") - self.wixObjOutput = os.path.join(args.genRoot, "wixobj_module") - self.heatPackageBase = "HeatPackageBase.wxs" - self.packagesPath = os.path.join(args.genRoot, "unsignedInstaller") - # Wix primarily differentiates between a file and directory by looking for a trailing slash. - # os.path.join with an empty string is a way to guarantee a trailing slash is added to a path. - self.bootstrapWixObjDir = os.path.join(os.path.join(args.genRoot, "wixobj_bootstrap"), '') - self.intermediateInstallerPath = os.path.join(args.genRoot, "unsignedInstaller") - - self.installerPath = self.intermediateInstallerPath - if self.doSigning: - self.installerPath = os.path.join(args.genRoot, "installer") - - self.sourcePath = args.packageRoot - if args.bootstrapOnly: - self.sourcePath = self.installerPath - - self.fullPathToMetrics = args.metricsExe - if self.fullPathToMetrics is None: - self.fullPathToMetrics = find_file_in_package(self.sourcePath, "LyInstallerMetrics.exe", ["InternalSDKs"]) - if self.fullPathToMetrics is None: - raise InstallerParamError('Path to LyInstallerMetrics.exe could not be found underneath the Tools/InternalSDKs folder in the package ') - - # Gather information on the Visual Studio 2015-2019 redistributable. - # Note that this is a hardcoded path, and not a search. This is because there are multiple different redistributables - # with the exact same name, the easiest way to identify which is which is based on the location in the package. - # Also, this VS 2015-2019 redistributable appears multiple times in the package. For consistency, we want to make sure - # the exact same one is used. - self.name2015Thru2019Redist = "VC_redist.x64.exe" - self.fullPathTo2015Thru2019Redist = os.path.join(args.packageRoot, "dev", "Tools", "Redistributables", "Visual Studio 2015-2019", self.name2015Thru2019Redist) - # When rebuilding just the bootstrap for a package, the source package root is a pointer to where the installer was - # generated previously. At this point, the redistributable is already in the package root. - if args.bootstrapOnly: - self.fullPathTo2015Thru2019Redist = find_file_in_package(self.sourcePath, [self.name2015Thru2019Redist]) - - self.skipMsiAndCabCreation = args.signOnly or args.bootstrapOnly - self.metricsPath, self.metricsExe = os.path.split(self.fullPathToMetrics) - self.pathTo2015Thru2019Redist, self.redist2015Thru2019Exe = os.path.split(self.fullPathTo2015Thru2019Redist) - self.tempBootstrapOutputDir = os.path.join(args.genRoot, "buildBootstrap") - - if self.doSigning and args.bootstrapOnly: - self.msiFileNameList = get_file_names_in_directory(self.installerPath, ".msi") - self.cabFileNameList = get_file_names_in_directory(self.installerPath, ".cab") - - # Default to LumberyardInstallerVERSION.exe, unless args.bootstrapName is set - if args.bootstrapName: - self.bootstrapName = args.bootstrapName - else: - self.bootstrapName = "LumberyardInstaller{}.exe".format(args.lyVersion) - - if self.doSigning: - self.tempBootstrapName = "temp" + self.bootstrapName - self.bootstrapOutputPath = os.path.join(self.tempBootstrapOutputDir, self.tempBootstrapName) - else: - self.bootstrapOutputPath = os.path.join(self.installerPath, self.bootstrapName) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/Light.py b/Tools/build/JenkinsScripts/distribution/Installer/Light.py deleted file mode 100755 index d4b34e1337..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/Light.py +++ /dev/null @@ -1,57 +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. -# - -import os -from BuildInstallerWixUtils import * - -# LIGHT COMMANDLINE TEMPLATES -lightCommandBase = 'light.exe -nologo -o {outputPath} -ext WixUIExtension -ext WiXUtilExtension -b "{packageSource}" {verbose} {wixobjFile}' -lightCommandBootstrap = 'light.exe -nologo -o {outputPath} -ext WixBalExtension -ext WiXUtilExtension {verbose} {wixobjFile}' -lightCommandCabCache = " -cc {cabCachePath} -reusecab" - - -def lightPackage(outputPath, sourceDirectory, wixobjFiles, verbose, cabCachePath): - verboseCmd = getVerboseCommand(verbose) - lightCommand = lightCommandBase.format(outputPath=outputPath, - verbose=verboseCmd, - packageSource=sourceDirectory, - wixobjFile=wixobjFiles) - - if cabCachePath is not None: - lightCommand += lightCommandCabCache.format(cabCachePath=cabCachePath) - - verbose_print(verbose, '\n{}\n'.format(lightCommand)) - return os.system(lightCommand) - - -def lightPackages(packageInfoMap, packagesPath, wixobjFiles, verboseMode, cabCachePath): - numPackagesBuilt = 0 - - for packageInfo in packageInfoMap.values(): - outputPath = os.path.join(packagesPath, '{}.msi'.format(packageInfo['wxsName'])) - packageWixObjPath = os.path.join(os.path.join(wixobjFiles, packageInfo['wxsName']), "*.wixobj") - - success = lightPackage(outputPath, packageInfo['sourcePath'], packageWixObjPath, verboseMode, cabCachePath) - assert (success == 0), 'Failed to generate msi and cab files for {}.'.format(packageInfo['name']) - - numPackagesBuilt += 1 - verbose_print(verboseMode, '\nPackages Built: {}\n\n'.format(numPackagesBuilt)) - - -def lightBootstrap(outputPath, wixobjFiles, verbose, cabCachePath): - verboseCmd = getVerboseCommand(verbose) - lightCommand = lightCommandBootstrap.format(outputPath=outputPath, verbose=verboseCmd, wixobjFile=wixobjFiles) - - if cabCachePath is not None: - lightCommand += lightCommandCabCache.format(cabCachePath=cabCachePath) - - verbose_print(verbose, '\n{}\n'.format(lightCommand)) - return os.system(lightCommand) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardBootstrapper.wxs b/Tools/build/JenkinsScripts/distribution/Installer/LumberyardBootstrapper.wxs deleted file mode 100644 index d2f9e5750e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardBootstrapper.wxs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:52fa9d61db7371183e66e422e8f959fd613a6c3e46035a8c1d05a4329445855b -size 5303 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardDevCertSetup.bat b/Tools/build/JenkinsScripts/distribution/Installer/LumberyardDevCertSetup.bat deleted file mode 100644 index 961d8eab57..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardDevCertSetup.bat +++ /dev/null @@ -1,14 +0,0 @@ -REM -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 - -@ECHO off -certutil -user -addstore Root LumberyardDevCA.cer diff --git a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.wxl b/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.wxl deleted file mode 100644 index efe52135e9..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.wxl +++ /dev/null @@ -1,61 +0,0 @@ - - - [WixBundleName] PC Setup - [WixBundleName] PC - Welcome - This setup tool installs the PC version of [WixBundleName] on Local Disk (C:). To change the install directory, click Options. - Version [WixBundleVersion] PC - Are you sure you want to cancel? - Previous version - Setup Help - /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or - creates a complete local copy of the bundle in directory. Install is the default. - -/passive | /quiet - displays minimal UI with no prompts or displays no UI and - no prompts. By default UI and all prompts are displayed. - -/norestart - suppress any attempts to restart. By default UI will prompt before restart. -/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. - &Close - By installing Lumberyard you agree to the <a href="https://aws.amazon.com/agreement">AWS Customer Agreement</a>, <a href="https://aws.amazon.com/service-terms/#57._Amazon_Lumberyard_Engine">Lumberyard Service Terms</a>, and <a href="https://aws.amazon.com/privacy">Privacy Notice</a>. - [WixBundleName] <a href="#">license terms</a>. - I &agree to the license terms and conditions - &Options - &Install - &Cancel - Setup options - Install location: - &Browse - &OK - &Cancel - Setup Progress - Acquiring: - Processing: - Initializing... - &Cancel - Modify Setup - &Repair - &Uninstall - &Close - Repair Successfully Completed - Uninstall Successfully Completed - Installation Successfully Completed - Setup Successful - &Launch Lumberyard Setup Assistant - You must restart your computer before you can use the software. - &Restart - Setup Failed - Setup Failed - Uninstall Failed - Repair Failed - One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. - You must restart your computer to complete the rollback of the software. - &Restart - &Close - Files In Use - The following applications are using files that need to be updated: - Close the &applications and attempt to restart them. - &Do not close applications. A reboot will be required. - &OK - &Cancel - diff --git a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.xml b/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.xml deleted file mode 100644 index 3da9408901..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/LumberyardThemeGDC.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - #(loc.Caption) - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI - - - #(loc.Title) - - - #(loc.HelpHeader) - #(loc.HelpText) - - - - #(loc.InstallHeader) - #(loc.InstallMessage) - #(loc.InstallEulaAgreementText) - #(loc.InstallVersion) - - - - - - #(loc.OptionsHeader) - #(loc.OptionsLocationLabel) - - - - - - - #(loc.FilesInUseHeader) - #(loc.FilesInUseLabel) - - - - - - - - - - #(loc.ProgressHeader) - - #(loc.DownloadLabel) - #(loc.OverallProgressPackageText) - - - #(loc.ProgressLabel) - - - - - - - #(loc.ModifyHeader) - - - - - - #(loc.SuccessHeader) - #(loc.SuccessInstallHeader) - #(loc.SuccessRepairHeader) - #(loc.SuccessUninstallHeader) - - #(loc.SuccessRestartText) - - - - #(loc.FailureHeader) - #(loc.FailureInstallHeader) - #(loc.FailureUninstallHeader) - #(loc.FailureRepairHeader) - #(loc.FailureHyperlinkLogText) - - #(loc.FailureRestartText) - - - - diff --git a/Tools/build/JenkinsScripts/distribution/Installer/PackageExeSigning.py b/Tools/build/JenkinsScripts/distribution/Installer/PackageExeSigning.py deleted file mode 100755 index 5aabc83e80..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/PackageExeSigning.py +++ /dev/null @@ -1,29 +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. -# - -import os -import SignTool - - -def SignLumberyardExes(unpackedLocation, - signingType, - timestampServer, - verbose, - filesToSign): - for file in filesToSign: - fileFullPath = os.path.join(unpackedLocation, file) - - SignTool.signtoolSignAndVerifyFile(fileFullPath, - os.path.dirname(fileFullPath), - os.path.dirname(fileFullPath), - signingType, - timestampServer, - verbose) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/Redistributables.wxs b/Tools/build/JenkinsScripts/distribution/Installer/Redistributables.wxs deleted file mode 100644 index 23daf44613..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/Redistributables.wxs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0782cab23b9ad88124296586afb2ed8e88f2ab4020786efe05da396d8f33e8ec -size 1542 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/SignTool.py b/Tools/build/JenkinsScripts/distribution/Installer/SignTool.py deleted file mode 100755 index ecf6b115af..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/SignTool.py +++ /dev/null @@ -1,212 +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. -# - -import shutil -import subprocess - -from BuildInstallerUtils import * - -# Signing cmd example -# signtool.exe sign /f c:\codesigning\lumberyard.pfx /tr http://tsa.starfieldtech.com /td SHA256 /p thePasswordSeeNotesBelow %f - -# Verify cmd example. -# signtool.exe verify /v /pa %f - -# SignTool COMMANDLINE TEMPLATES -signtoolCommandBase = "signtool.exe {commandType} {verbose} {commandTypeParams} {filename}" -signtoolKeySignParams = "/fd SHA256 /f {certificatePath} /p {password}" -signtoolNameSignParams = '/fd SHA256 /n "{certificateName}"' -signtoolTimestampParams = "/tr {timestampServerURL} /td SHA256" -signtoolVerifyParams = "/pa /tw /hash SHA256" - - -class SignType: - def __init__(self, signParamsString): - self.signtoolParamsTemplate = signParamsString - - def getSigntoolParamsTemplate(self): - return self.signtoolParamsTemplate - - def getSigntoolParams(self): - raise NotImplementedError(self.getSigntoolParams.__name__) - - -class KeySigning(SignType): - def __init__(self, key, password): - SignType.__init__(self, signtoolKeySignParams) - self.privateKey = key - self.password = password - - def getSigntoolParams(self): - return self.getSigntoolParamsTemplate().format(certificatePath=self.privateKey, password=self.password) - - -class NameSigning(SignType): - def __init__(self, name): - SignType.__init__(self, signtoolNameSignParams) - self.certName = name - - def getSigntoolParams(self): - return self.getSigntoolParamsTemplate().format(certificateName=self.certName) - - -def getSignToolVerboseCommand(verboseMode): - if verboseMode: - return " /v" - else: - return "" - - -def buildSignCommand(filename, signingType, verbose): - verboseCmd = getSignToolVerboseCommand(verbose) - - signtoolParams = signingType.getSigntoolParams() - signtoolCommand = signtoolCommandBase.format(commandType="sign", - verbose=verboseCmd, commandTypeParams=signtoolParams, filename = filename) - return signtoolCommand - - -def signtoolTestCredentials(signingType, timestampServer, verbose): - testFileName = "testFile" - if os.path.exists(testFileName): - os.remove(testFileName) - - with open(testFileName, "wb") as testSign: - testSign.seek(1023) - testSign.write("0") - - # error codes for sign tool are only 0 or 1. No way to get a success without - # a valid .exe to sign, so the only way to test is to try to sign a file - # that will be considered an unrecognized format, and parse the output to - # see if the error was with the password. - signtoolCommand = buildSignCommand(testFileName, signingType, verbose) - sp = subprocess.Popen(signtoolCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, error = sp.communicate() - - validPassword = False - if error: - # if find returns -1, it means it couldnt find password incorrect text, - # meaning it is a valid password. - validPassword = error.splitlines()[0].lower().find("password is not correct") == -1 - - os.remove(testFileName) - return validPassword - - -def signtoolSignFile(filename, signingType, verbose): - signtoolCommand = buildSignCommand(filename, signingType, verbose) - - verbose_print(verbose, '\n{}\n'.format(signtoolCommand)) - return os.system(signtoolCommand) == 0 - - -def signtoolTimestamp(filename, timestampServer, verbose): - verboseCmd = getSignToolVerboseCommand(verbose) - - signtoolParams = signtoolTimestampParams.format(timestampServerURL=timestampServer) - signtoolCommand = signtoolCommandBase.format(commandType="timestamp", - verbose=verboseCmd, - commandTypeParams=signtoolParams, - filename=filename) - - verbose_print(verbose, '\n{}\n'.format(signtoolCommand)) - - success = False - while not success: - success = (os.system(signtoolCommand) == 0) - - return success - - -def signtoolVerifySign(filename, verbose): - verboseCmd = getSignToolVerboseCommand(verbose) - - signtoolCommand = signtoolCommandBase.format(commandType="verify", - verbose=verboseCmd, - commandTypeParams=signtoolVerifyParams, - filename=filename) - - verbose_print(verbose, '\n{}\n'.format(signtoolCommand)) - return_result = os.system(signtoolCommand) == 0 - return return_result - - -def signtoolSignAndVerifyFile(filename, - workingDir, - sourceDir, - signingType, - timestampServer, - verbose): - shouldCopy = workingDir is not sourceDir - filePath = os.path.join(workingDir, filename) - - # most of the time that signing fails, it is due to the signing server not responding. - # keep retrying until the signing is successful. - # NOTE: might want to change this to a for loop to limit number of retries per file. - success = False - attemptsMade = 0 - - while not success: - # SIGN THE FILE - success = signtoolSignFile(filePath, signingType, verbose) - assert success, 'Failed to sign file {}. Most likely the password entered is incorrect.'.format(filename) - - # TIMESTAMP THE FILE - success = signtoolTimestamp(filePath, timestampServer, verbose) - assert success, "Failed to contact the timestamp server." - - # VERIFY SUCCESSFUL SIGNING - success = signtoolVerifySign(filePath, verbose) - attemptsMade += 1 - - if not success: - verbose_print(verbose, 'Failed to sign file {}'.format(filename)) - if shouldCopy: - # delete the original file, copy back from source, and re-sign - os.remove(filePath) - shutil.copy(os.path.join(sourceDir, filename), filePath) - - verbose_print(verbose, 'Attempts made to sign file {}: {}\n'.format(filename, attemptsMade)) - - return success - - -def signtoolSignAndVerifyFiles(fileList, - workingDir, - sourceDir, - signingType, - timestampServer, - verbose): - - for filename in fileList: - signtoolSignAndVerifyFile(filename, - workingDir, - sourceDir, - signingType, - timestampServer, - verbose) - - -def signtoolSignAndVerifyType(fileExtension, - workingDir, - sourceDir, - signingType, - timestampServer, - verbose): - # Sign each file in a directory that has the given file extension - for file in os.listdir(workingDir): - if file.endswith(fileExtension): - signtoolSignAndVerifyFile(os.path.basename(file), - workingDir, - sourceDir, - signingType, - timestampServer, - verbose) diff --git a/Tools/build/JenkinsScripts/distribution/Installer/TestInstaller.py b/Tools/build/JenkinsScripts/distribution/Installer/TestInstaller.py deleted file mode 100755 index 5ef0e9604b..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/TestInstaller.py +++ /dev/null @@ -1,186 +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. -# - -import argparse -import ctypes -import filecmp -import os -import os.path -import sys -import tempfile - -parser = argparse.ArgumentParser(description='Tests the Lumberyard Installer bootstrapper.') -parser.add_argument('-v', '--verbose', action='store_true', help='Enables logging messages (default False)') -parser.add_argument('-k', '--keep', action='store_true', help="Don't delete temp files") -parser.add_argument('--packageRoot', default=None, help="Source content to test against, required for use. (default None)") -parser.add_argument('--lyVersion', default="0.0.0.0", help="Version to use when generated artifacts (default '0.0.0.0')") -parser.add_argument('--target', default='%temp%\\installertest\\TestInstall', help='The location to install Lumberyard. Make sure to use backslashes in the path. (default "%%temp%%\\installertest\\TestInstall"') -parser.add_argument('--genRoot', default='%temp%/installertest/', help='Path for temp data (default "%%temp%%/installertest/"') -parser.add_argument('--hostURL', default="https://s3-us-west-2.amazonaws.com/lumberyard-streaming-install-test/releases/JoeInstallTest/", help='The URL for the installer to download its packages from (msi + cab files). (default https://s3-us-west-2.amazonaws.com/lumberyard-streaming-install-test/releases/JoeInstallTest/)') -parser.add_argument('--testName', default=None, help='The name of the test to run (case insensitive). Will cause an error if no test with that name exists. Will run all tests if not specified. (default None)') -bootstrapperName = "automatedTestBootstrapper.exe" - -args = parser.parse_args() - -# Installation requires administration privileges. -try: - is_admin = os.getuid() == 0 -except AttributeError: - is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0 - -if not is_admin: - sys.exit("Administrator privileges must be enabled to install Lumberyard") - -# Search target for forward slash (/) and replace with back slashes (\) -# because the install command doesn't like forward slashes. -installTarget = args.target.replace('/', '\\') - -pfxName = "LumberyardDev.pfx" -signingArgs = "--privateKey {} --password test".format(pfxName) - - -# Creates an installer with the given additional arguments. Will leave temp files -# even if the keep argument for this script is specified, in order to correctly -# perform some tests -def makeInstaller(additionalCommands=None): - buildInstallerCommand = "BuildInstaller.py --packageRoot {} " \ - "--lyVersion {} " \ - "--genRoot {} " \ - "--bootstrapName {} " \ - "--hostURL {}".format(args.packageRoot, - args.lyVersion, - args.genRoot, - bootstrapperName, - args.hostURL) - if args.verbose: - buildInstallerCommand += " -v" - - if additionalCommands: - buildInstallerCommand += " " + additionalCommands - - os.system(buildInstallerCommand) - - -# Will create an installer with the given additional arguments, run the installer, -# and verify contents of the installed lumberyard with the source package. -# Some tests require artifacts of previous installs to exist. If they do not, -# a set of artifacts will be created. -def createAndTestInstaller(installerSubfolder, - additionalCommands, - requiresSigning=False, - requiresArtifacts=False): - if requiresArtifacts: - # Create a set of artifacts if none are available - if not os.path.exists(os.path.join(args.genRoot, installerSubfolder)): - if requiresSigning: - makeInstaller(signingArgs) - else: - makeInstaller() - - makeInstaller(additionalCommands) - bootstrapperPath = os.path.join(args.genRoot, installerSubfolder, bootstrapperName) - installCommand = "{} /silent InstallFolder={}".format(bootstrapperPath, installTarget) - if args.verbose: - print("Running installation command:") - print("\t{}".format(installCommand)) - os.system(installCommand) - - # Validate install was successful - pathToInstalledPackage = os.path.join(installTarget, args.lyVersion) - # filecmp.dircmp failes if you pass in a directory with "%temp%", so %temp% has to be replaced by - # temp dir before calling it. - scrubbedPackagedRoot = args.packageRoot.replace("%temp%", tempfile.gettempdir()) - pathToInstalledPackage = pathToInstalledPackage.replace("%temp%", tempfile.gettempdir()) - installVerifier = filecmp.dircmp(scrubbedPackagedRoot, pathToInstalledPackage) - if args.verbose: - print("Dif between install and source:") - installVerifier.report_full_closure() - if installVerifier.left_only or installVerifier.right_only: - print("Error: Install failed, source and destination do not match") - - # Uninstall Lumberyard - uninstallCommand = "start /WAIT {} /silent /uninstall".format(bootstrapperPath) - if args.verbose: - print("Running uninstallation command:") - print("\t{}".format(uninstallCommand)) - os.system(uninstallCommand) - - # Validate uninstall was successful - if os.path.isdir(args.target): - print("Error: Uninstall failed.") - - -tests = {} - - -def makeTest(testName, - installerSubfolder, - additionalCommands, - requiresSigning=False, - requiresArtifacts=False): - - def _makeTestArgs(testName, *testArgs): - tests[testName] = testArgs - - _makeTestArgs(testName, installerSubfolder, additionalCommands, requiresSigning, requiresArtifacts) - - -def listTests(): - print('Tests with the following names have been defined:') - for testName in tests.keys(): - print(testName) - - -def runTest(testName): - if args.verbose: - print('Performing test "{}"'.format(testName)) - testArgs = tests[testName] - if testArgs is not None and len(testArgs) > 0: - createAndTestInstaller(*testArgs) - - -def runAllTests(): - for testName in tests.keys(): - runTest(testName) - - -# DEFINE TEST CASES - -# Test success cases -# Unsigned -makeTest("unsigned installer", "unsignedInstaller", None) -makeTest("unsigned bootstrap only", "unsignedInstaller", "--bootstrapOnly", False, True) -# Signed -makeTest("signed installer", "installer", signingArgs, True) -makeTest("signed sign only", "installer", signingArgs + " --signOnly", True, True) -makeTest("signed bootstrap only", "installer", signingArgs + " --bootstrapOnly", True, True) - -# END DEFINE TEST CASES - - -# RUN TEST(S) -if args.testName is not None: - if args.testName.lower() in tests: - runTest(args.testName.lower()) - else: - print('Test with the name "{}" does not exist.'.format(args.testName)) - listTests() -else: - runAllTests() -# END RUN TEST(S) - - -# CLEAN-UP -if not args.keep: - import shutil - if os.path.exists(args.genRoot): - shutil.rmtree(args.genRoot) -# END CLEAN-UP diff --git a/Tools/build/JenkinsScripts/distribution/Installer/__init__.py b/Tools/build/JenkinsScripts/distribution/Installer/__init__.py deleted file mode 100755 index 4d5680a30d..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/__init__.py +++ /dev/null @@ -1,10 +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. -# diff --git a/Tools/build/JenkinsScripts/distribution/Installer/allowed_empty_folders.json b/Tools/build/JenkinsScripts/distribution/Installer/allowed_empty_folders.json deleted file mode 100644 index 1d1e4353e6..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/allowed_empty_folders.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Whitelist": [ - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrenvmap/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrenvmap/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrheader/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrheader/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrmakepreview/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrmakepreview/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrmaketiled/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/exrstdattr/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImf/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImf/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImfExamples/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImfExamples/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImfTest/Debug", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/IlmImfTest/Release", - "3rdParty/OpenEXR/2.0/src/openexr-2.0.0/vc/vc7/OpenEXR/release", - "dev/Bin64/EditorPlugins", - "dev/SamplesProject/Levels/Samples/Gems_Samples", - "dev/Cache/StarterGame/pc/user/log" - ] -} diff --git a/Tools/build/JenkinsScripts/distribution/Installer/dir_filelist.json b/Tools/build/JenkinsScripts/distribution/Installer/dir_filelist.json deleted file mode 100644 index 2682420469..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/dir_filelist.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "_comment": "Folders listed here will only include the content listed. All other content within the folder will be omitted from the installer.", - "dev/Bin64vc141": [ - "EditorPlugins/ProceduralMaterialEditorPlugin.dll", - "EditorPlugins/ProceduralMaterialEditorPlugin.exp", - "EditorPlugins/ProceduralMaterialEditorPlugin.lib", - "EditorPlugins/ProceduralMaterialEditorPlugin.dll.manifest", - "rc/d3dcompiler_47.dll", - "rc/d3dcsx_47.dll", - "rc/d3dx11_43.dll", - "rc/dbghelp.dll", - "rc/opengl32sw.dll", - "rc/PVRTexLib_License.txt", - "rc/xinput1_3.dll", - "D3DCompiler_43.dll", - "d3dcompiler_46.dll", - "d3dcompiler_47.dll", - "d3dcsx_46.dll", - "d3dcsx_47.dll", - "d3dx11_43.dll", - "dbghelp.dll", - "glut32.dll", - "imguilib.dll", - "imguilib.dll.manifest", - "imguilib.exp", - "imguilib.lib", - "libeay32.dll", - "LuaCompiler.exe", - "Microsoft.VC90.CRT.manifest", - "msvcr90.dll", - "nvToolsExt64_1.dll", - "PhysX3CharacterKinematicPROFILE_x64.dll", - "PhysX3CommonPROFILE_x64.dll", - "PhysX3CookingPROFILE_x64.dll", - "PhysX3GpuPROFILE_x64.dll", - "PhysX3PROFILE_x64.dll", - "PhysXDevice64.dll", - "PVRTexLib_License.txt", - "PxFoundationPROFILE_x64.dll", - "PxPvdSDKPROFILE_x64.dll", - "SDL2.dll", - "ssleay32.dll", - "substance_d3d11pc_blend.dll", - "substance_linker.dll", - "substance_sse2_blend.dll", - "ToolsCrashUploader.exe", - "ToolsCrashUploader.exe.manifest", - "xinput1_3.dll" - ] -} diff --git a/Tools/build/JenkinsScripts/distribution/Installer/editor_icon_setup.ico b/Tools/build/JenkinsScripts/distribution/Installer/editor_icon_setup.ico deleted file mode 100644 index 72b5db1a55..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Installer/editor_icon_setup.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2f464626a1ce6148798c6c378865a66fceefe0e8541c904730485e38d21203b6 -size 43973 diff --git a/Tools/build/JenkinsScripts/distribution/Installer/license.rtf b/Tools/build/JenkinsScripts/distribution/Installer/license.rtf deleted file mode 100644 index 37564ba049c5486224f68f4da41ed7db8e4338eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 685 zcmbV~O-m#(5QaSq{)b|YqWz`4usf$&5fncVM_7ac$#g0`Vbe*QRL?Lr{ohUZun_11Lo*SW>|Y7o8iiIRFvg>(i~$=mb_r+;Vvj9 zsTs=TJWqX{nhis<>T%3{SD04%x(CUreYfs(TF!^lgc&el%XNZ>1-Hc z1|xki9D9o+>>Bd07^{uiVHlzyivsH`{l`4{9zr0$(G{IC`6i?@z_<*| z${)$gVgh~nX!}#hk1#Cvx!`Hc^(CgTa_a0`6KlQRh-&xwydL&JxOW^|`T`&s-}vY- H{*QxqE|2u` diff --git a/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelist.py b/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelist.py deleted file mode 100755 index 5e58cf7f92..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelist.py +++ /dev/null @@ -1,66 +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. -# - -import BuildGameTemplateWhitelistArgs -import json -import os -import sys - -# Generates a whitelist of project template names we can include in metrics. -# Input is a path to the project templates folder for a Lumberyard install. -# Output is a JSON formatted file in that directory, that will be included in the package. -# A template is defined by a templatedefinition.json file inside of a folder, the template name is the folder containing this file. -# Output should look like: -# { -# "TemplateListDescription": "This is a list of Amazon provided templates. This is a white list of project template names that are included in usage event tracking. If a template name is not in this list, the name will not be included in the event.", -# "TemplateNameWhitelist": [ -# "SimpleTemplate", -# "EmptyTemplate" -# ] -# } -def main(): - print "Generating Game Template Whitelist" - args = BuildGameTemplateWhitelistArgs.createArgs() - - validTemplates = [] - # Search for project templates. - for root, dirnames, filenames in os.walk(args.projectTemplatesFolder): - templateRoot = os.path.basename(root) - for file in filenames: - if file == args.templateDefinitionFileName: - fullPath = os.path.join(templateRoot, file) - print "Found template definition: " + fullPath - validTemplates.append(templateRoot) - - templateDescriptionKey = "TemplateListDescription" - templatedescriptionValue = "This is a white list of project template names that are included in usage event tracking. " - templatedescriptionValue += "If a template name is not in this list, the name will not be included in the event." - - TemplateNameWhitelistKey = "TemplateNameWhitelist" - jsonString = json.dumps({templateDescriptionKey: templatedescriptionValue, - TemplateNameWhitelistKey: validTemplates}, - sort_keys=True, - indent=4, - separators=(',', ': ')) - - - templateWhitelistFilePath = os.path.join(args.projectTemplatesFolder, args.templateWhitelistFilename) - try: - whitelistFile = open(templateWhitelistFilePath, 'w') - whitelistFile.write(jsonString) - whitelistFile.close() - except: - print "Error writing template whitelist to file " + templateWhitelistFilePath - return 1 - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelistArgs.py b/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelistArgs.py deleted file mode 100755 index af5771b0e9..0000000000 --- a/Tools/build/JenkinsScripts/distribution/Metrics/GameTemplates/BuildGameTemplateWhitelistArgs.py +++ /dev/null @@ -1,30 +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. -# - -import argparse - -def createArgs(): - parser = argparse.ArgumentParser(description='Builds a whitelist of Game Templates to include in reported metrics.') - parser.add_argument('--projectTemplatesFolder', - default=None, - required=True, - help='Path to the templates folder. Expected: dev\\ProjectTemplates\\') - parser.add_argument('--templateDefinitionFileName', - default='templatedefinition.json', - help='Template definition file name (default templatedefinition.json)') - parser.add_argument('--templateWhitelistFilename', - default='TemplateListForMetrics.json', - help='Template whitelist file name (default TemplateListForMetrics.json)') - args = parser.parse_args() - print "Building game template whitelist with the following arguments" - print(args) - return args - diff --git a/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyPackages.py b/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyPackages.py deleted file mode 100644 index 05ffd61640..0000000000 --- a/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyPackages.py +++ /dev/null @@ -1,309 +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. -""" - -import BuildThirdPartyArgs -import BuildThirdPartyUtils -import SDKPackager -import ThirdPartySDKAWS -import json -import os -import re -import sys -import urlparse - -importDir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(importDir, "..")) #Required for AWS_PyTools -from AWS_PyTools import LyChecksum -from AWS_PyTools import LyCloudfrontOps - -# Some files are in the 3rd party folder and not associated with any SDK/Versions. -fileIgnorelist = [ - "boost/Boost_Autoexp.dat", - "boost/CryEngine Customizations.txt", - "boost/CryREADME.txt", - "boost/LICENSE_1_0.txt", - "boost/lumberyard-1.61.0.patch", - "Qwt/license.txt", - "lz4/git checkout.txt" - "3rdParty.txt" -] - - -class SDK(object): - - def __init__(self): - self.fileList = [] - self.path = "" - self.versionFolder = "" - - -def getListFromFile(file): - openFile = open(file, 'r') - filePaths = openFile.readlines() - openFile.close() - return filePaths - - -def addUntrackedSDKs(sdks): - # Not all SDKs are represented in SetupAssistantConfig.json yet. - - untrackedSDKs = { - "OpenEXR20": ["OpenEXR/2.0", "2.0"], - "OpenEXR22": ["OpenEXR/2.2", "2.2"], - } - - for sdkName, untrackedSDK in untrackedSDKs.iteritems(): - sdk = SDK() - sdk.path = untrackedSDK[0] - sdk.versionFolder = untrackedSDK[1] - sdks[sdkName] = sdk - - -def getSDKsToPathsDict(thirdPartyVersionsFile): - versionsList = getListFromFile(thirdPartyVersionsFile) - sdks = {} - for version in versionsList: - match = re.match(r"(.*)(\.package.dir=)(.*)", version) - if not match: - BuildThirdPartyUtils.printError('SDK version file {0} has invalid formatting on line {1}'.format( - thirdPartyVersionsFile, - version)) - - sdkName = match.group(1) - # Store the SDK Path with forward slashes to make matching easier. - sdkPath = match.group(3).replace('\\', '/') - sdk = SDK() - sdk.path = sdkPath - - versionMatch = re.search(r"([^/\\\\]*)$", sdkPath) - if not versionMatch: - BuildThirdPartyUtils.printError('SDK version file {0} has invalid formatting on line {1}'.format( - thirdPartyVersionsFile, - version)) - - sdk.versionFolder = versionMatch.group(1) - sdks[sdkName] = sdk - - addUntrackedSDKs(sdks) - return sdks - - -def populateSDKFilePaths(sdks, sdkFileListFile): - fileList = getListFromFile(sdkFileListFile) - lastSDKName = "" - for file in fileList: - slashesFixed = file.replace('\\', '/') - match = re.search("3rdParty/(.*)", slashesFixed) - if not match: - BuildThirdPartyUtils.printError("Could not find third party folder in file path {0}".format(file)) - - localPath = match.group(1) - sdkFound = False - - # Files are generally grouped by SDK in the file list, - # caching the last SDK used can save a search through the loop. - if lastSDKName: - if localPath.startswith(sdks[lastSDKName].path): - sdk.fileList.append(file) - sdkFound = True - continue - - for sdkName, sdk in sdks.iteritems(): - if localPath.startswith(sdk.path): - sdk.fileList.append(file) - sdkFound = True - lastSDKName = sdkName - break - - # Some files are loose and not trackable within the current system. For now we're going to ignore them, - # and they will need to be included in the package manually. - for ignore in fileIgnorelist: - if localPath == ignore: - sdkFound = True - break - - if not sdkFound: - BuildThirdPartyUtils.printError("File {0} is not associated with any known SDKs".format( - file, - sdkFileListFile)) - - -def checkForSDKStagingErrors(bucket, baseBucketPath, sdkPath, sdkPlatform, filesetHash): - tmpDirPath = SDKPackager.getTempDir(sdkPath, sdkPlatform) - - filelistFileName = SDKPackager.getFilelistFileName(sdkPlatform) - filelistLocalPath = os.path.join(tmpDirPath, filelistFileName) - filelistStagingPath = ThirdPartySDKAWS.getS3StagingPath(baseBucketPath, sdkPath) + filelistFileName - - if not os.path.exists(tmpDirPath): - os.makedirs(tmpDirPath) - bucket.download_file(filelistStagingPath, filelistLocalPath) - - filelistData = open(filelistLocalPath, 'r') - filelistJsonData = json.load(filelistData) - filelistData.close() - - assert(filelistData != ""), "Failed to load from " + filelistLocalPath - - filelistChecksum = filelistJsonData["filelist"]["checksum"] - - if filelistChecksum != filesetHash.hexdigest(): - # If the checksums don't match, then the SDK has been modified without changing the version. This is an error. - return True - return False - - -def checkForExistingSDK(ignoreExisting, - bucket, - baseBucketPath, - sdkName, - versionFolder, - sdkPath, - sdkPlatform, - filesetHash): - returnCode = 0 - statusMessage = None - # Check for existing manifest - manifestExists, filelistExists = ThirdPartySDKAWS.getSDKStagingStatus(bucket, - baseBucketPath, - sdkPath, - sdkPlatform) - if ignoreExisting: - return statusMessage, returnCode - - # If the manifest or filelist is missing, but one is available, then the SDK likely failed to upload. - # In this case, just continue on and generate the SDK package. - if manifestExists and filelistExists: - # If the manifest and filelist both exist, this SDK.version.package has been uploaded already. - stagingError = checkForSDKStagingErrors(bucket, - baseBucketPath, - sdkPath, - sdkPlatform, - filesetHash) - - if stagingError: - statusMessage = "ERROR: The file list manifests do not match for SDK {0}, Version {1}, Platform {2}".format(sdkName, - versionFolder, - sdkPlatform) - returnCode = 1 - else: - statusMessage = "\tEverything is up to date for SDK {0}, Version {1}, Platform {2}".format(sdkName, - versionFolder, - sdkPlatform) - if statusMessage: - print statusMessage - return statusMessage, returnCode - - -def getListFromJsonFile(jsonFile, root): - if not jsonFile: - return [] - if not os.path.isfile(jsonFile): - print "{} is not a valid file, please check the filename specified.".format(jsonFile) - exit(1) - with open(jsonFile, 'r') as source: - source_json = json.load(source) - try: - sdks_list = source_json[root] - return sdks_list - except KeyError: - print "Unknown json root {}, please check the json root specified.".format(root) - exit(1) - - -############################ - - -def main(): - print "Building third party packages" - args = BuildThirdPartyArgs.createArgs() - - print "Parsing file lists" - ignoreExistingSDKList = getListFromJsonFile(args.ignoreExistingList, args.sdkPlatform) - sdkBlacklist = getListFromJsonFile(args.sdkBlacklist, "Blacklist") - sdks = getSDKsToPathsDict(args.thirdPartyVersions) - populateSDKFilePaths(sdks, args.sdkFilelist) - - cloudfrontDist = LyCloudfrontOps.getCloudfrontDistribution(args.cloudfrontDomain, args.awsProfile) - bucket = LyCloudfrontOps.getBucket(cloudfrontDist, args.awsProfile) - baseBucketPath = LyCloudfrontOps.buildBucketPath(urlparse.urljoin(args.cloudfrontDomain, args.stagingFolderPath), cloudfrontDist) - baseCloudfrontUrl = args.cloudfrontDomain # we assume that the domain ends in a trailing '/' - if args.stagingFolderPath: - baseCloudfrontUrl += args.stagingFolderPath # we assume that the folder path ends in a trailing '/' - - returnCode = 0 - sdksGenerated = [] - - sdkCount = len(sdks) - currentSDK = -1 - for sdkName, sdk in sdks.iteritems(): - currentSDK += 1 - print "{0}/{1} - Processing {2}".format(currentSDK, sdkCount, sdkName) - - # Don't process SDKs in the blacklist. - if sdkName in sdkBlacklist: - print "\tSkipping blacklist SDK {0}".format(sdkName) - continue - # Hash all files for the SDK - filesetHash = LyChecksum.generateFilesetChecksum(sdk.fileList) - - if args.internalPackage: - ignoreExisting = True - else: - ignoreExisting = sdkName in ignoreExistingSDKList - - statusMessage, sdkReturnCode = checkForExistingSDK(ignoreExisting, - bucket, - baseBucketPath, - sdkName, - sdk.versionFolder, - sdk.path, - args.sdkPlatform, - filesetHash) - # The final return should be the highest reported return code. - returnCode = max(returnCode, sdkReturnCode) - if statusMessage: - continue - manifestPath, filelistPath, zipFiles = SDKPackager.generateSDKPackage(baseCloudfrontUrl, - sdkName, - sdk.versionFolder, - sdk.path, - args.sdkPlatform, - filesetHash, - sdk.fileList, - args.archiveMaxSize) - if not args.skipUpload: - ThirdPartySDKAWS.uploadSDKToStaging(bucket, - baseBucketPath, - sdkName, - sdk.versionFolder, - sdk.path, - args.sdkPlatform, - manifestPath, - filelistPath, - zipFiles) - print "{0}/{1} - Completed Processing {2}".format(currentSDK+1, sdkCount, sdkName) - sdksGenerated.append(sdkName) - - # If any SDKs were updated, and we were told to make a file to output - # the list of updated SDKs to, then make said file and write out the list - if len(sdksGenerated) > 0 and args.updatesFile: - try: - with open(args.updatesFile, 'w') as out: - out.writelines('\n'.join(sdksGenerated)) - except: - BuildThirdPartyUtils.printError("Failed to write list of updated SDKs to {0}. Backup zip files will not be created properly for this build.".format(args.updatesFile)) - - return returnCode - -if __name__ == "__main__": - sys.exit(main()) diff --git a/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyUtils.py b/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyUtils.py deleted file mode 100644 index 865c45d47d..0000000000 --- a/Tools/build/JenkinsScripts/distribution/ThirdParty/BuildThirdPartyUtils.py +++ /dev/null @@ -1,29 +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. -""" - -import sys - -def printError(message): - print(message) - sys.exit(1) - - -def reportIterationStatus(index, count, reportFrequency, message): - # Reporting on the first, last, and at a frequency that is a good balance of not spamming the logs - frequency = count / reportFrequency - lastPercent = float(index-1) / float(count) - percentComplete = float(index) / float(count) - lastReportSlice = int(lastPercent * frequency) - thisReportSlice = int(percentComplete * frequency) - shouldPrint = lastReportSlice != thisReportSlice or index == 1 or index == count - if shouldPrint: - print "\t{0}% complete, {1}/{2} {3}".format(int(percentComplete*100), index, count, message) diff --git a/Tools/build/JenkinsScripts/distribution/ThirdParty/SDKPackager.py b/Tools/build/JenkinsScripts/distribution/ThirdParty/SDKPackager.py deleted file mode 100644 index 32c51f6302..0000000000 --- a/Tools/build/JenkinsScripts/distribution/ThirdParty/SDKPackager.py +++ /dev/null @@ -1,207 +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. -""" - -import zipfile -import os.path -import re -import json -import sys -import ThirdPartySDKAWS -import BuildThirdPartyUtils -import tempfile - -importDir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(importDir, "..")) #Required for AWS_PyTools -from AWS_PyTools import LyChecksum - -class SDKZipFile(object): - def __init__(self): - self.file = None - self.filePath = None - self.contents = [] - self.compressedSize = 0 - self.uncompressedSize = 0 - self.compressedHash = 0 - - -def getFilelistVersion(): - return "1.0.0" - - -def getFilelistFileName(sdkPlatform): - return "filelist." + getFilelistVersion() + "." + sdkPlatform + ".json" - - -def getManifestVersion(): - return "1.0.0" - - -def getManifestFileName(sdkPlatform): - return "manifest." + getManifestVersion() + "." + sdkPlatform + ".json" - - -def toArchivePath(filePath): - # Archives are generated relative to 3rdParty folder, so strip everything before that in the path. - # zipfile is very particular in how paths to files within it are formatted. - slashesFixed = filePath.replace('\\', '/') - match = re.search("3rdParty/(.*)", slashesFixed) - if not match: - BuildThirdPartyUtils.printError("Could not find third party folder in file path {0}".format(filePath)) - archivePath = match.group(1).strip("/").strip("\n") - return archivePath - - -def prepFilesystemForFile(filePath): - directory = os.path.dirname(filePath) - if not os.path.exists(directory): - os.makedirs(directory) - if os.path.isfile(filePath): - os.remove(filePath) - -def createJSONString(dataToFormat): - return json.dumps(dataToFormat, sort_keys=True, indent=4, separators=(',', ': ')) - - -def generateSDKPackage(baseCloudfrontUrl, - sdkName, - sdkVersion, - sdkPath, - sdkPlatform, - filesetHash, - filePaths, - archiveMaxSize): - zipFiles = zipPackage(sdkName, sdkVersion, sdkPath, sdkPlatform, filePaths, archiveMaxSize) - filelistPath = buildFilelistJSON(sdkPath, sdkPlatform, filesetHash, filePaths) - manifestPath = buildManifestJSON(baseCloudfrontUrl, - sdkName, - sdkPath, - sdkPlatform, - zipFiles, - filelistPath) - return manifestPath, filelistPath, zipFiles - - -def getTempDir(sdkPath, sdkPlatform): - tempDir = os.path.join(tempfile.tempdir, "LY", "3rdPartySDKs", sdkPath, sdkPlatform) - return os.path.expandvars(tempDir) - - -def zipPackage(sdkName, sdkVersion, sdkPath, sdkPlatform, filePaths, archiveMaxSize): - try: - import zlib - compression = zipfile.ZIP_DEFLATED - except: - compression = zipfile.ZIP_STORED - - tempDir = getTempDir(sdkPath, sdkPlatform) - zipFiles = [] - currentZipFile = None - - fileIndex = 0 - fileCount = len(filePaths) - - for filePath in filePaths: - - filePath = filePath.strip("\n") - archivePath = toArchivePath(filePath) - if currentZipFile is None or currentZipFile.file is None or currentZipFile.compressedSize > archiveMaxSize: - if currentZipFile and currentZipFile.file: - currentZipFile.file.close() - currentZipFile = SDKZipFile() - zipFiles.append(currentZipFile) - currentZipFile.filePath = os.path.join(tempDir, sdkName + "." + str(sdkPlatform) + "." + str(len(zipFiles)) + ".zip") - prepFilesystemForFile(currentZipFile.filePath) - currentZipFile.file = zipfile.ZipFile(currentZipFile.filePath, mode='w') - currentZipFile.file.write(filePath, compress_type=compression, arcname=archivePath) - fileInfo = currentZipFile.file.getinfo(archivePath) - currentZipFile.compressedSize += fileInfo.compress_size - currentZipFile.uncompressedSize += fileInfo.file_size - currentZipFile.contents.append(filePath) - - fileIndex += 1 - BuildThirdPartyUtils.reportIterationStatus(fileIndex, fileCount, 25, "files zipped") - - if currentZipFile and currentZipFile.file: - currentZipFile.file.close() - - for zipFile in zipFiles: - zipFile.compressedHash = LyChecksum.getChecksumForSingleFile(zipFile.filePath) - - return zipFiles - - -def buildFilelistJSON(sdkPath, sdkPlatform, filesetHash, filePaths): - jsonFormatFiles = [] - for filePath in filePaths: - scrubbedFile = toArchivePath(filePath) - jsonFormatFiles.append(scrubbedFile) - - filelistInfo = { - "filelist": { - "filelistVersion": getFilelistVersion(), - "checksum": filesetHash.hexdigest(), - "files": jsonFormatFiles, - } - } - filelistJSON = createJSONString(filelistInfo) - filelistName = getFilelistFileName(sdkPlatform) - filelistPath = getTempDir(sdkPath, sdkPlatform) - filelistFullPath = os.path.join(filelistPath, filelistName) - - prepFilesystemForFile(filelistFullPath) - - outputFile = open(filelistFullPath, 'w') - outputFile.write(filelistJSON) - outputFile.close() - return filelistFullPath - - -def buildManifestJSON(baseCloudfrontUrl, sdkName, sdkPath, sdkPlatform, zipFiles, filelistPath): - uncompressedSize = 0 - packageArchives = [] - for zipFile in zipFiles: - uncompressedSize += zipFile.uncompressedSize - archiveUrl = ThirdPartySDKAWS.getProductionUrl(baseCloudfrontUrl, sdkPath, zipFile.filePath) - packageArchive = { - "archiveUrl": archiveUrl, - "archiveSize": str(zipFile.compressedSize), - "archiveChecksum": zipFile.compressedHash.hexdigest() - } - packageArchives.append(packageArchive) - - filelistChecksum = LyChecksum.getChecksumForSingleFile(filelistPath) - - filelistUrl = ThirdPartySDKAWS.getProductionUrl(baseCloudfrontUrl, sdkPath, filelistPath) - packageInfo = { - "package": - { - "manifestVersion": getManifestVersion(), - "identifier": sdkName, - "platform": sdkPlatform, - "uncompressedSize": str(uncompressedSize), - "filelistUrl": filelistUrl, - "filelistChecksum": filelistChecksum.hexdigest(), - "archives": packageArchives - - } - } - manifestJSON = createJSONString(packageInfo) - manifestName = getManifestFileName(sdkPlatform) - manifestPath = getTempDir(sdkPath, sdkPlatform) - manifestFullPath = os.path.join(manifestPath, manifestName) - - prepFilesystemForFile(manifestFullPath) - - outputFile = open(manifestFullPath, 'w') - outputFile.write(manifestJSON) - outputFile.close() - return manifestFullPath diff --git a/Tools/build/JenkinsScripts/distribution/ThirdParty/ThirdPartySDKAWS.py b/Tools/build/JenkinsScripts/distribution/ThirdParty/ThirdPartySDKAWS.py deleted file mode 100644 index c143195655..0000000000 --- a/Tools/build/JenkinsScripts/distribution/ThirdParty/ThirdPartySDKAWS.py +++ /dev/null @@ -1,76 +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. -""" - -import os.path -import sys -import urlparse -import SDKPackager -import BuildThirdPartyUtils - -importDir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(importDir, "..")) #Required for AWS_PyTools -from AWS_PyTools import LyCloudfrontOps - -def getS3StagingPath(stagingFolderPath, sdkPath): - # The staging path is used for the build machines to upload new builds of 3rd party packages. - # The Setup Assistant supports a global override so Lumberyard team members can pull from the staging location. - return urlparse.urljoin(stagingFolderPath, sdkPath.replace(' ', '_')) + '/' - -def getProductionUrl(cloudfrontUrl, sdkPath, filePath): - # The production path is the final path customers will download the SDK from. - # These links get baked into the manifest, which the Setup Assistant executable uses to acquire these SDKs. - # TODO : Generate an actual cloudfront production link. - #return cloudfrontUrl + getS3StagingPath(stagingFolderPath, sdkPath.replace(' ', '_')) + os.path.basename(filePath) - # we assume that the cloudfront url and the result of getS3stagingPath have a trailing '/' - return getS3StagingPath(cloudfrontUrl, sdkPath) + os.path.basename(filePath) - -def getSDKStagingStatus(bucket, baseBucketPath, sdkPath, sdkPlatform): - - pathToSDK = getS3StagingPath(baseBucketPath, sdkPath) - pathToFilelist = pathToSDK + SDKPackager.getFilelistFileName(sdkPlatform) - pathToManifest = pathToSDK + SDKPackager.getManifestFileName(sdkPlatform) - manifestExists = False - filelistExists = False - - objs = list(bucket.objects.filter(Prefix=pathToManifest)) - if len(objs) > 0 and objs[0].key == pathToManifest: - manifestExists = True - else: - manifestExists = False - - objs = list(bucket.objects.filter(Prefix=pathToFilelist)) - if len(objs) > 0 and objs[0].key == pathToFilelist: - filelistExists = True - else: - filelistExists = False - - return manifestExists, filelistExists - -def uploadSDKToStaging(bucket, baseBucketPath, sdkName, sdkVersion, sdkPath, sdkPlatform, manifestPath, filelistPath, zipFiles): - print "\tUploading SDK: {0} ({1},{2})".format(sdkName, sdkVersion, sdkPlatform) - - manifestStagingPath = getS3StagingPath(baseBucketPath, sdkPath) + os.path.basename(manifestPath) - bucket.upload_file(manifestPath, manifestStagingPath) - print "\tUploaded manifest" - - filelistStagingPath = getS3StagingPath(baseBucketPath, sdkPath) + os.path.basename(filelistPath) - bucket.upload_file(filelistPath, filelistStagingPath) - print "\tUploaded filelist" - - filesUploaded = 0 - totalFilesCount = len(zipFiles) - for zipFile in zipFiles: - fileLocalPath = zipFile.filePath - fileStagingPath = getS3StagingPath(baseBucketPath, sdkPath) + os.path.basename(zipFile.filePath) - bucket.upload_file(fileLocalPath, fileStagingPath) - filesUploaded += 1 - BuildThirdPartyUtils.reportIterationStatus(filesUploaded, totalFilesCount, 5, "files uploaded") diff --git a/Tools/build/JenkinsScripts/distribution/__init__.py b/Tools/build/JenkinsScripts/distribution/__init__.py deleted file mode 100755 index e912252f4e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/__init__.py +++ /dev/null @@ -1,12 +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. -""" - diff --git a/Tools/build/JenkinsScripts/distribution/copyright.txt b/Tools/build/JenkinsScripts/distribution/copyright.txt deleted file mode 100644 index 5ea6c40c55..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright.txt +++ /dev/null @@ -1,12 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -* a third party where indicated. -* -* 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. -* -*/ - diff --git a/Tools/build/JenkinsScripts/distribution/copyright_prepender.py b/Tools/build/JenkinsScripts/distribution/copyright_prepender.py deleted file mode 100755 index dfb22210db..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_prepender.py +++ /dev/null @@ -1,83 +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. -""" - -import os -import stat -import shutil -import argparse - -flagged_extensions = ['.c', '.cpp', '.h', '.hpp', '.inl'] -skippable_extensions = ['.log', '.p4ignore', '.obj', '.dll', '.png', '.pdb', '.dylib', '.lib',\ - '.exe', '.flt', '.asi', '.exp', '.ilk', '.pch', '.res', '.bmp', '.cur',\ - '.ico', '.resx', '.jpg', '.psd', '.gif', '.a', '.fxcb', '.icns', '.cab',\ - '.chm', '.hxc', '.xsd', '.tif'] - -copyright_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'copyright.txt') - -prepend_yes_log = open('prepend_yes.log', 'w') -prepend_no_log = open('prepend_no.log', 'w') -prepend_skip_log = open('prepend_skip.log', 'w') - -gQuietMode = False - -def prepend_copyrights(): - for dirname, dirnames, filenames in os.walk('.'): - for filename in filenames: - full_filename = os.path.join(dirname, filename) - if copyright_required(filename): - apply_copyright(full_filename) - elif skippable(filename): - if not gQuietMode: - print 'Skipping ' + full_filename - prepend_skip_log.write('Skipping ' + full_filename + '\n') - else: - if not gQuietMode: - print 'Not prepending to ' + full_filename - prepend_no_log.write('Not prepending to ' + full_filename + '\n') - -def apply_copyright(full_filename): - if not gQuietMode: - print 'Prepending copyright to ' + full_filename - prepend_yes_log.write('Prepending copyright to ' + full_filename + '\n') - temp_file = full_filename + '_temp' - os.rename(full_filename, temp_file) - shutil.copyfile(copyright_path, full_filename) - with open(full_filename, 'a') as f: - with open(temp_file) as t: - for line in t: - f.write(line) - os.chmod(temp_file, stat.S_IWRITE) - os.remove(temp_file) - -def copyright_required(filename): - return os.path.splitext(filename)[1] in flagged_extensions - -def skippable(filename): - return os.path.splitext(filename)[1] in skippable_extensions - - -def main(): - prepend_copyrights() - prepend_yes_log.close() - prepend_no_log.close() - prepend_skip_log.close() - - -if __name__ =="__main__": - parser = argparse.ArgumentParser() - parser.add_argument( '-q', '--quiet', dest='quiet', help='quiet mode - only print output to logs', action='store_true') - - args = parser.parse_args() - gQuietMode = args.quiet - - main() - diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/Categorizer.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/Categorizer.py deleted file mode 100755 index 6f55b5fe82..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/Categorizer.py +++ /dev/null @@ -1,16 +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. -""" - -class Categorizer(): - def __init__(): - self.StarComment = StarComment() - self.SlashComment = SlashComment() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/CommentCategory.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/CommentCategory.py deleted file mode 100755 index 51238035da..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/CommentCategory.py +++ /dev/null @@ -1,26 +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. -""" - -class CommentCategory: - def __init__(): - self.start = -1 - self.end = -1 - self.type = None - - def find_start(): - pass - - def find_end(): - pass - - def find_type(): - pass \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/SlashComment.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/SlashComment.py deleted file mode 100755 index 50179afa4f..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/SlashComment.py +++ /dev/null @@ -1,20 +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. -""" - -class SlashComment(CommentCategory): - def find_start(): - pass - def find_end(): - pass - - def find_type(): - pass \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/StarComment.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/StarComment.py deleted file mode 100755 index 0ffb87bea8..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/StarComment.py +++ /dev/null @@ -1,20 +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. -""" - -class StarComment(CommentCategory): - def find_start(): - pass - def find_end(): - pass - - def find_type(): - pass \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_header_manual_tool.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_header_manual_tool.py deleted file mode 100755 index f14688fb44..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_header_manual_tool.py +++ /dev/null @@ -1,580 +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. -""" - -# One-time script to inspect pre-copyright script headers against the a particular branch@latest and optionally make -# corrections - - -import re -import os -import codecs -import stat -import subprocess -import argparse -import tempfile -import hashlib - -# The path to beyond compare local to the machine -BEYOND_COMPARE_PATH="\"C:\\Program Files (x86)\\Beyond Compare 3\\BCompare.exe\"" - -# The P4 Path to mainline to get the previous revision -P4_MAINLINE = '//lyengine/dev' - -# The revision number in mainline just before the original copyright header script was applied -PRECOPYRIGHT_REV = 130741 - -# The name of the file to keep track of files that were intentionally skipped -MANUAL_SKIP_FILE = 'manual_skipped.txt' - -# The extension of files to analyze -DEFAULT_FILTERED_EXTENSIONS = ['CS','H','HPP','HXX','INL','C','CPP', 'EXT','PY', 'LUA', 'BAT', 'CFX', 'CFI'] - -# Words that we will ignore when analyzing the original copyright header for anything meaningful -TALLY_IGNORE_WORDS = ['COMPILERS', - 'VISUAL', - 'STUDIO', - 'VERSION', - 'CREATED', - 'STUDIOS', - 'FILE', - 'SOURCE', - 'COPYRIGHT', - 'CRYTEK', - 'C', - 'CREATED', - 'HISTORY'] -# The word threshold to use to flag previous revisions for the number of non-ignore words that were detected. -WORD_THRESHOLD = 10 - -# Folders to skip during the process -SKIP_FOLDERS = ['/Code/SDKs', - '/Code/Sandbox/SDKs', - '/Code/Tools/SDKs', - '/Code/Tools/waf-1.7.13', - '/Code/Tools/MaxCryExport/Skin/12', - '/Code/Tools/MaxCryExport/Skin/13', - '/Code/Tools/MaxCryExport/Skin/14', - '/Code/Tools/MaxCryExport/Skin/15', - '/Code/Tools/MaxCryExport/Skin/16', - '/Code/Tools/MaxCryExport/Skin/17', - '/Code/Tools/MaxCryExport/Skin/18', - '/Code/Tools/HLSLCrossCompiler', - '/Code/Tools/HLSLCrossCompilerMETAL', - '/BinTemp'] - -# Particular files to skip -SKIP_FILES = ['resource.h', - '__init__.py'] - - -def calculate_hash(file_contents): - m = hashlib.md5() - for line in file_contents: - m.update(line) - return m.hexdigest() - - -def calculate_file_hash(file_path): - with open(file_path,'r') as f: - file_content = f.readlines() - return calculate_hash(file_content) - - -# Compare 2 files with beyond compare -def compare_files(left,right): - subprocess.call('{} \"{}\" \"{}\"'.format(BEYOND_COMPARE_PATH,left,right)) - - -# Check the read-only flag of a file (assume it represents if a file is checked out or not) -def check_file_status(filepath): - st = os.stat(filepath) - return bool(st.st_mode & (stat.S_IWGRP|stat.S_IWUSR|stat.S_IWOTH)) - - -# Checkout a file into a ChangeList -def checkout_file(root_code_path,filepath, p4_path_root, cl_number): - p4_file_path = filepath.replace(root_path,'') - p4_path = p4_path_root + p4_file_path - p4_path = p4_path.replace('\\','/') - - try: - result = subprocess.call('p4 edit -c {} \"{}\"'.format(cl_number,p4_path)) - if result < 0: - print('[ABORT] Process terminated by signal') - return False - except OSError as e: - print('[ERROR] p4 call error:{}'.format(e)) - return False - - return check_file_status(filepath) - - -def replace_source_with_update_temp(source_original_file,source_temp_file): - with open(source_temp_file,'r') as rf: - file_content = rf.readlines() - with open(source_original_file,'w') as wf: - skipped_first = False - for line in file_content: - if not skipped_first: - skipped_first = True - else: - wf.write(line) - - -def pull_source_revision(root_code_path, file_path, p4_path_root, rev_number): - - # Calculate the p4 root pathg - p4_path = p4_path_root + '/' + file_path.replace(root_code_path, '') - p4_path = p4_path.replace('\\','/') - p4_path = '//' + p4_path[2:].replace('//','/') - - # If the rev number is greater than zero, then this is a specific version - if rev_number>0: - filename_only = os.path.split(file_path)[1] + '#{}'.format(rev_number) - temp_file_path = os.path.join(tempfile.gettempdir(), filename_only) - p4_command = ['p4','print','{}@{}'.format(p4_path, rev_number)] - else: - filename_only = os.path.split(file_path)[1] - temp_file_path = os.path.join(tempfile.gettempdir(), filename_only) - p4_command = ['p4','print','{}'.format(p4_path)] - try: - with open(temp_file_path,'w') as f: - result = subprocess.call(p4_command, stdout=f) - if result < 0: - print('[ABORT] Process terminated by signal') - return False - except OSError as e: - print('[ERROR] p4 call error:{}'.format(e)) - return False - - return temp_file_path - - -# Auto insert descriptions into a file if the file doesnt already have a description section -def auto_insert_description(file_to_modify,description_lines): - file_contents = [] - with open(file_to_modify,'r') as r: - file_contents = r.readlines() - - line_count = len(file_contents) - line_index = 0 - insert_index = -1 - comment_block_end_index = -1 - has_description = False - while line_index0: - file_contents.insert(insert_index,'\n') - insert_index += 1 - for insert_description_line in description_lines: - file_contents.insert(insert_index,insert_description_line+'\n') - insert_index += 1 - file_contents.insert(insert_index,'\n') - - # update the working file - with open(file_to_modify,'w') as w: - w.writelines(file_contents) - - return file_to_modify - - -def _is_skip_file(filepath): - if filepath.endswith('.Designer.cs'): - return True - normalized = os.path.dirname(filepath).replace('\\','/').upper() - for skip_file in SKIP_FILES: - if normalized.endswith('/'+skip_file.upper()): - return True - return False - - -def _is_skip_folder(root_code_path,dirname): - - normalized = '/'+dirname.replace(root_code_path,'').replace('\\','/').upper() - for skip_path in SKIP_FOLDERS: - if normalized.startswith(skip_path.upper()): - return True - return False - - -def read_input_files_file(path,root_path): - files_to_process = set() - if not os.path.exists(path): - print('Invalid input file:{}'.format(path)) - else: - with open(path,'r') as f: - file_content = f.readlines() - for filename in file_content: - if filename.startswith('#'): - continue - base_name = filename.replace(root_path,'').strip() - base_name = os.path.realpath(root_path + '/' + base_name) - files_to_process.add(base_name.upper()) - return files_to_process - - -BOM_ENCODINGS = [ (codecs.BOM_UTF32), - (codecs.BOM_UTF16), - (codecs.BOM_UTF8)] - - -def extract_header(original_file_content): - def _clean_bom(line): - for bom in BOM_ENCODINGS: - if bom in line: - return re.sub('[^\040-\176]','',line) - return line - - header_content = [] - for original_line in original_file_content: - bom_cleaned_line = _clean_bom(original_line).strip() - if bom_cleaned_line.startswith('#'): - break - if bom_cleaned_line.startswith('using'): - break - if bom_cleaned_line.startswith('import'): - break - if bom_cleaned_line.startswith('namespace'): - break - header_content.append(bom_cleaned_line) - - return header_content - - -def analyze_header_content(source_file, show_tally, orig_file_path,skip_log, original_description_lines): - - # Read the contents of the file and extract the header - with open(source_file,'r') as r: - original_file_content = r.readlines() - header_content = extract_header(original_file_content) - - if '#' in source_file: - filename_and_ext_only = os.path.splitext(os.path.split(source_file)[1].split('#')[0]) - else: - filename_and_ext_only = os.path.splitext(os.path.split(source_file)[1])[0] - filename_only = filename_and_ext_only[0] - ext_only = filename_and_ext_only[1] - filename_only_upper = filename_only.upper() - - # Clean the header of comment tokens and non work tokens - clean_header_content = [] - has_description = False - skipped_first = False - description_label_added = False - found_first_complete_description = False - for line in header_content: - if not skipped_first: - skipped_first = True - else: - # see if we can pull original description line - if not found_first_complete_description: - m_original_desc_one_line = re.match('(//|\\*)?(\\s*)(Description|Desc|'+filename_only+ext_only+')\\s*\\:\\s*(.*)',line) - if m_original_desc_one_line is not None: - desc_label_key = m_original_desc_one_line.group(3) - if m_original_desc_one_line.group(4) is not None: - has_description_header = True - extracted_description = m_original_desc_one_line.group(4) - if extracted_description.strip().__len__()>0: - original_description_lines.append('// Description : {}'.format(m_original_desc_one_line.group(4))) - description_label_added = True - has_description = True - # If the description label key is the filename, then this is one line only - if desc_label_key=='Description': - found_first_complete_description = True - else: - multiline_desc_check = re.sub(r'[\W]',' ',line).split(' ') - multiline_desc_check_words = [w.upper() for w in multiline_desc_check if w!=''] - if len(multiline_desc_check_words)>0: - if not description_label_added: - original_description_lines.append('// Description : {}'.format(re.sub(r'[\s/\\]',' ',line).strip())) - description_label_added = True - has_description = True - else: - original_description_lines.append('// {}'.format(re.sub(r'[\s/\\]',' ',line).strip())) - has_description = True - else: - found_first_complete_description = False - - updated_line = re.sub(r'[\W]',' ',line) - if show_tally: - print(updated_line) - - clean_header_content.append(updated_line) - - # Count the words we care about - word_count = 0 - - # Analyze each line - for line in clean_header_content: - # Split each line into capitalized words - words = [w.upper() for w in line.split(' ') if w != ''] - for word in words: - - # Skip the filename itself - if word==filename_only_upper: - continue - - # Skip any ignore words - if word in TALLY_IGNORE_WORDS: - continue - - # Skip any numbers - if re.match('\d{1,4}',word): - continue - - word_count+=1 - - if show_tally: - print('\n\nTotal Words:{}'.format(word_count)) - - # Keep track of files that were skipped but had at least 4 unmatched words for futher analysis - if word_count > 4 and not has_description: - skip_log.write('***********************************************************************\n') - skip_log.write('** Skipping file {}:\n'.format(orig_file_path)) - skip_log.write('***********************************************************************\n') - for skip_line in header_content: - skip_log.write(skip_line+'\n') - skip_log.write('\n\n\n\n\n\n') - - return has_description or word_count > WORD_THRESHOLD - - -def process_file(cl_number,p4_path_root,root_code_path,orig_filepath, original_file_content, show_details, skip_log, manual_skip_files, index): - - # Pull the previous revision from mainline into a temp file - prev_file_content_file = pull_source_revision(root_code_path,orig_filepath,P4_MAINLINE,PRECOPYRIGHT_REV) - - original_description_lines = [] - if not analyze_header_content(prev_file_content_file, show_details, orig_filepath, skip_log, original_description_lines): - return - - # Pull the latest revision - source_revision_file = pull_source_revision(root_code_path,orig_filepath,p4_path_root,-1) - if not os.path.exists(source_revision_file): - print('...File not in perforce {}:{}',p4_path_root,orig_filepath) - return - - # Keep track of the hash of the original file - original_file_hash = calculate_file_hash(source_revision_file) - - # If we detected any description lines in the original, attempt to insert it into the temp copy - if len(original_description_lines)>0: - source_revision_file = auto_insert_description(source_revision_file,original_description_lines) - - # Bring up the diff viewer - compare_files(prev_file_content_file, source_revision_file) - - # If a changelist is supplied, checkout and update the source file into the CL - if cl_number > 0: - # Calculate the hash of the sourece file again to detect any changes - check_file_hash = calculate_file_hash(source_revision_file) - - # If the hashes differ, then we need to check out the original file, update it with the changes - if check_file_hash!=original_file_hash: - - # Checkout the file if necessary - if not check_file_status(orig_filepath): - if not checkout_file(root_code_path,orig_filepath, p4_path_root,cl_number): - print('...Unable to check out file {}'.format(orig_filepath)) - os.remove(source_revision_file) - os.remove(prev_file_content_file) - return - # Update the original with the temp - replace_source_with_update_temp(orig_filepath,source_revision_file) - - print('Updated {}'.format(orig_filepath)) - else: - with open(MANUAL_SKIP_FILE,'a') as update_file: - update_file.write(orig_filepath.lower()+'\n') - manual_skip_files.add(orig_filepath.lower()) - print('Manually Skipped {}'.format(orig_filepath)) - - # Check out the file if needed - os.remove(source_revision_file) - os.remove(prev_file_content_file) - - -def process(cl_number, p4_path, root_path, code_path, filtered_extensions, is_code_path_input_file,show_details,skip_log, manual_skip_files, skip_to): - - # Collect the files to process - files_to_process = set() - if is_code_path_input_file: - files_to_process = read_input_files_file(code_path,root_path) - else: - if os.path.isdir(code_path): - for (dirpath, dirnames, filenames) in os.walk(code_path): - if _is_skip_folder(root_path, dirpath): - continue - for file in filenames: - file_name,file_ext = os.path.splitext(file) - file_ext = file_ext.upper()[1:] - if file_ext in filtered_extensions and not _is_skip_file(file): - files_to_process.add(dirpath + "/" + file) - else: - files_to_process.add(code_path) - - file_count = len(files_to_process) - file_progress = 0 - - for file_to_process in files_to_process: - - # Open each file and handle in memory - with open(file_to_process,'r') as f: - file_content = f.readlines() - - file_progress += 1 - - # Process each file - if file_progress0: - print('({}/{}) Skipping {}. (Forced)'.format(file_progress,file_count,file_to_process)) - continue - - # Skip files that were already skipped previously - if file_to_process.lower() in manual_skip_files: - print('({}/{}) Skipping {}. Already Manually Skipped'.format(file_progress,file_count,file_to_process)) - continue - # Skip files that are already checked out - if check_file_status(file_to_process): - print('({}/{}) Skipping {}. Already checked out'.format(file_progress,file_count,file_to_process)) - continue - if process_file(cl_number, p4_path,root_path,file_to_process, file_content, show_details, skip_log, manual_skip_files, file_progress): - print('({}/{}) Processed {}'.format(file_progress,file_count,file_to_process)) - else: - print('({}/{}) Skipped {}'.format(file_progress,file_count,file_to_process)) - - -if __name__ == "__main__": - - parser = argparse.ArgumentParser() - - parser.add_argument('-i','--input_files', action='store_true', default=False, help='Option to use code_path as an input file of files to process') - - parser.add_argument('-p','--py', action='store_true', default=False, help='Python files only (.py)') - parser.add_argument('-c','--cpp', action='store_true', default=False, help='C/C++ files only') - parser.add_argument('--cs', action='store_true', default=False, help='C# files only') - parser.add_argument('--ext', action='store_true', default=False, help='.EXT files only') - parser.add_argument('--lua', action='store_true', default=False, help='.LUA files only') - parser.add_argument('--bat', action='store_true', default=False, help='.BAT files only') - parser.add_argument('--cf', action='store_true', default=False, help='CFI/CFX files only') - parser.add_argument('--details', action='store_true', default=False, help='Show details of the header analysis') - - parser.add_argument('-s','--skip',nargs='?',type=int,default=-1,help='The entry number to skip forward to') - parser.add_argument('--cl',nargs='?',type=int,default=0,help='Change list number to apply updates to. If not set (or zero), then modified files will not be checked out') - - parser.add_argument('p4_path', type=str, help='The base p4 path') - parser.add_argument('root_path', help='The base root path') - parser.add_argument('code_path', help='The root code path process on', default='.') - - args = parser.parse_args() - - print('Using Perforce environment:') - print(' P4PORT={}'.format(os.environ["P4PORT"])) - print(' P4CLIENT={}'.format(os.environ["P4CLIENT"])) - - if not os.path.exists(args.root_path): - print('[ERROR]: Root path \'{}\' is invalid'.format(args.root_path)) - exit() - else: - input_root_path = args.root_path - - if not os.path.isdir(input_root_path): - print('[ERROR]: Root path \'{}\' cannot be a file'.format(args.root_path)) - exit() - - print('Root path {}'.format(args.root_path)) - print('p4 path {}'.format(args.p4_path)) - - if args.input_files: - code_path = args.code_path - if not os.path.exists(code_path) or not os.path.isfile(code_path): - print('[ERROR]: Code input file \'{}\' is invalid'.format(args.code_path)) - exit() - else: - code_path = os.path.normpath(input_root_path+'/'+args.code_path) - if not os.path.exists(code_path): - print('[ERROR]: Code path \'{}\' is invalid'.format(args.code_path)) - exit() - - if os.path.isdir(code_path): - print('Working on code folder {}'.format(code_path)) - else: - print('Working on a single code file {}'.format(code_path)) - - filtered_extensions = [] - if args.py: - print('Filtering on Python files') - filtered_extensions.append('PY') - if args.cpp: - print('Filtering on C/C++ files') - filtered_extensions.append('H') - filtered_extensions.append('HPP') - filtered_extensions.append('HXX') - filtered_extensions.append('INL') - filtered_extensions.append('C') - filtered_extensions.append('CPP') - if args.cs: - print('Filtering on C# files') - filtered_extensions.append('CS') - if args.ext: - print('Filtering on EXT files') - filtered_extensions.append('EXT') - if args.lua: - print('Filtering on LUA files') - filtered_extensions.append('LUA') - if args.bat: - print('Filtering on BAT files') - filtered_extensions.append('BAT') - if args.cf: - print('Filtering on CFI/CFX files') - filtered_extensions.append('CFI') - filtered_extensions.append('CFX') - if len(filtered_extensions)==0: - filtered_extensions = DEFAULT_FILTERED_EXTENSIONS - - manual_skipped_files = set() - if os.path.exists(MANUAL_SKIP_FILE): - with open('manual_skipped.txt','r') as msf: - manual_skipped_files_list = msf.readlines() - for manual_skipped_file in manual_skipped_files_list: - manual_skipped_files.add(manual_skipped_file.lower().strip()) - - with open('skipped_logs','w') as skip_log: - process(args.cl, args.p4_path, input_root_path, code_path, filtered_extensions,args.input_files, args.details, - skip_log, manual_skipped_files,args.skip) - diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_update.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_update.py deleted file mode 100755 index 920a341c80..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/copyright_update.py +++ /dev/null @@ -1,813 +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. -# - -import sys -import time -import re -import os -import stat -import subprocess -import logging -import argparse -import shutil - -AMAZON_HEADER='''/* -* 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. -* -*/ -''' - -PY_AMAZON_HEADER='''# -# 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. -# -''' - -BAT_AMAZON_HEADER='''@echo off -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -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 -''' - - -AMAZON_EXT_HEADER_TOP='''//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -''' - -AMAZON_EXT_HEADER_BOTTOM='''// -//////////////////////////////////////////////////////////////////////////// -''' - -AMAZON_LUA_HEADER_TOP='''---------------------------------------------------------------------------------------------------- --- --- 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. --- -''' - -AMAZON_LUA_HEADER_BOTTOM='''-- ----------------------------------------------------------------------------------------------------- -''' - - - -AMAZON_DEPRECATED_HEADER='Copyright 2015 Amazon.com' - -FORMER_CRYTEK_HEADER='// Original file Copyright Crytek GMBH or its affiliates, used under license.' - -PY_FORMER_CRYTEK_HEADER='# Original file Copyright Crytek GMBH or its affiliates, used under license.' - -LUA_FORMER_CRYTEK_HEADER='-- Original file Copyright Crytek GMBH or its affiliates, used under license.' - -BAT_FORMER_CRYTEK_HEADER='REM Original file Copyright Crytek GMBH or its affiliates, used under license.' - -# BEYOND_COMPARE_PATH="\"C:\\Program Files (x86)\\Beyond Compare 4\\BCompare.exe\"" -BEYOND_COMPARE_PATH="\"C:\\Program Files (x86)\\Beyond Compare 3\\BCompare.exe\"" - - - -DEFAULT_FILTERED_EXTENSIONS = ['CS','H','HPP','HXX','INL','C','CPP', 'EXT','PY', 'LUA', 'BAT', 'CFX', 'CFI'] - -# Check if this line had the original (non-amazon) copyright notice -def _is_former_crytek_header(line): - if 'CRYTEK' in line.upper() and line != FORMER_CRYTEK_HEADER and line != PY_FORMER_CRYTEK_HEADER: - return True - else: - return False - - -def _is_amazon_header(line): - if 'AMAZON.COM' in line.upper() and not AMAZON_DEPRECATED_HEADER.upper() in line.upper(): - return True - else: - return False - -def _is_amazon_deprecated_header(line): - if AMAZON_DEPRECATED_HEADER.upper() in line.upper(): - return True - else: - return False - -ORIGINAL_AMAZON_SOURCE_FOLDER_ROOTS = ['./Code/Framework', - './Code/GameCore', - './Code/GameCoreTemplate', - './Gems', - './Code/Tools/AzCodeGenerator'] -SKIP_FOLDERS = ['/Code/SDKs', - '/Code/Sandbox/SDKs', - '/Code/Tools/SDKs', - '/Code/Tools/waf-1.7.13', - '/Code/Tools/MaxCryExport/Skin/12', - '/Code/Tools/MaxCryExport/Skin/13', - '/Code/Tools/MaxCryExport/Skin/14', - '/Code/Tools/MaxCryExport/Skin/15', - '/Code/Tools/MaxCryExport/Skin/16', - '/Code/Tools/MaxCryExport/Skin/17', - '/Code/Tools/MaxCryExport/Skin/18', - '/Code/Tools/HLSLCrossCompiler', - '/Code/Tools/HLSLCrossCompilerMETAL', - '/BinTemp'] - - -SKIP_FILES = ['resource.h', - '__init__.py'] - -logging.basicConfig(filename='copyright_update.log',level=logging.INFO) - -log_file_updated = open('copyright_updated.files','w') -log_file_updated.write('# Copyright Updated File List\n#\n') - -log_file_skipped = open('copyright_skipped.files','w') -log_file_skipped.write('# Copyright Skipped File List\n#\n') - -log_file_open_source = open('opensource.files','w') -log_file_open_source.write('# Detected open source files\n#\n') - -def log_update(path, detail): - logging.info('Updating file {} : {}'.format(path,detail)) - log_file_updated.write('{}\n'.format(path)) - -def log_skipped(path, detail): - logging.info('Skipping file {} : {}'.format(path,detail)) - log_file_skipped.write('{}\n'.format(path)) - -def log_opensource(path, license): - logging.info('Skipping file {} : Licensed ({}) File detected'.format(path,license)) - log_file_open_source.write('{}\n'.format(path)) - -def close_logs(): - log_file_updated.close() - log_file_skipped.close() - log_file_open_source.close() - -def _is_skip_folder(root_code_path,dirname): - - normalized = '/'+dirname.replace(root_code_path,'').replace('\\','/').upper() - for skip_path in SKIP_FOLDERS: - if normalized.startswith(skip_path.upper()): - return True - return False - -def _is_skip_file(filepath): - if filepath.endswith('.Designer.cs'): - return True - normalized = os.path.dirname(filepath).replace('\\','/').upper() - for skip_file in SKIP_FILES: - if normalized.endswith('/'+skip_file.upper()): - return True - return False - -def _is_file_original_amazon(filepath): - - normalized = filepath.replace('\\','/').upper() - for amazon_path in ORIGINAL_AMAZON_SOURCE_FOLDER_ROOTS: - if normalized.startswith(amazon_path.upper()): - return True - return False - -def _is_copyright_notice_tbd(line): - if 'COPYRIGHT_NOTICE_TBD' in line.upper(): - return True - else: - return False - -def _has_original_crytek_note(line): - if FORMER_CRYTEK_HEADER in line: - return True - elif PY_FORMER_CRYTEK_HEADER in line: - return True - else: - return False - -def _is_cs_auto_generated(line): - if 'auto-generated' in line: - return True - else: - return False - -def _is_open_source(line,filename): - if 'Microsoft Public License' in line: - log_opensource(filename,'Microsoft Public License') - return True - if '$QT_BEGIN_LICENSE:LGPL$' in line: - log_opensource(filename,'QT Lesser General Public License') - return True - if 'LICENSE.LGPL' in line: - log_opensource(filename,'GPL License') - return True - if 'Apache License' in line: - log_opensource(filename,'Apache License') - return True - if 'BSD LICENSE' in line.upper(): - log_opensource(filename,'BSD License') - return True - if 'ADOBE SYSTEMS' in line.upper(): - log_opensource(filename,'Adobe License') - return True - if 'Public License' in line: - log_opensource(filename,'Public License') - return True - - return False - -def _is_amazon_old_header_line(line): - if 'a third party where indicated' in line: - return True - else: - return False - -def check_file_status(filepath): - st = os.stat(filepath) - return bool(st.st_mode & (stat.S_IWGRP|stat.S_IWUSR|stat.S_IWOTH)) - -def checkout_file(root_code_path,filepath, p4_path_root,cl_number): - p4_file_path = filepath.replace(root_path,'') - p4_path = p4_path_root + p4_file_path - p4_path = p4_path.replace('\\','/') - - try: - result = subprocess.call('p4 edit -c {} \"{}\"'.format(cl_number,p4_path)) - if result < 0: - print('[ABORT] Process terminated by signal') - return False - except OSError as e: - print('[ERROR] p4 call error:{}'.format(e)) - return False - - return check_file_status(filepath) - - -def load_original_crytek_set(path, filtered_extensions): - original_set = set() - with open(path,'r') as f: - file_content = f.readlines() - for filename in file_content: - if filename.startswith('#'): - continue - base_name = filename.replace('//crypristine/vendor_branch_3.8.1','').strip() - orig_file, orig_ext = os.path.splitext(base_name) - if orig_ext.upper()[1:] in filtered_extensions: - original_set.add(base_name.upper()) - return original_set - - -def read_input_files_file(path,root_path): - files_to_process = set() - if not os.path.exists(path): - print('Invalid input file:{}'.format(path)) - else: - with open(path,'r') as f: - file_content = f.readlines() - for filename in file_content: - if filename.startswith('#'): - continue - base_name = filename.replace(root_path,'').strip() - base_name = os.path.realpath(root_path + '/' + base_name) - files_to_process.add(base_name.upper()) - return files_to_process - - - - -def process_file(orig_filepath, original_file_content, updated_file_content, is_original_crytek): - - def _script_non_printable(instr): - return re.sub('[^\040-\176]','',instr) - - orig_file, orig_ext = os.path.splitext(orig_filepath) - orig_ext = orig_ext[1:].lower() - - is_csharp = orig_ext == 'cs' - is_cc = orig_ext in ['h','hpp','cxx','cpp','c','inl','cc'] - is_py = orig_ext in ['py'] - is_java = orig_ext in ['java'] - is_ext = orig_ext == 'ext' - is_lua = orig_ext == 'lua' - is_bat = orig_ext == 'bat' - is_cf = orig_ext in ['cfx','cfi'] - - # Is the header removable (Either Crytek or COPYRIGHT_NOTICE_TBD)7 - header_removable = False - - # Has a comment header, is it original crytek? - is_original_crytek_header = False - - # Has a comment header, is it amazon? - is_amazon_header = False - - has_original_crytek_note = False - - # Has a comment header, is it deprecated amazon? - is_amazon_deprecated_header = False - - # Is this a placeholder for the copyright notice - is_copyright_notice_tbd = False - - # No header block? - missing_header_block = False - - # Comment header block starts with // (continue until first #) - starts_with_cc = False # Starts with // - - # Comment header block starts with /* (continue until */) - starts_with_cs = False # Starts with /* - - # Mark the start of where the source file should continue from after the new copyright(s) - copyright_remove_index = -1 - - # Is this an auto-generated csharp file - is_cs_auto_generated = False - - # Does this contain the old/deprecated amazon copyright - is_amazon_old_header_line = False - - # Does this file have the original crytek note - has_original_crytek_note = False - - is_open_source = False - - line_index = 0 - - # Examine the contents of the file - file_content_len = len(original_file_content) - - # Special case. There are some c-sharp files that start of with non-ascii characters for some reason. Strip it out - # from only the first line - if is_csharp: - line = _script_non_printable(original_file_content[0]) - original_file_content[0] = line+'\n' - - # Flag to indicate the file starts with comments - has_starting_comments = False - - # Flag to indicate we are inside a /* comment - starting_code_index = 0 - - # (EXT) flags - ext_comment_divider_started = False - has_ext_comment_divider = False - has_ext_description = False - ext_start_description_line = ext_end_description_line = 0 - - # (PY) flags - py_started_str_quotes = False - - # (LUA) flags - lua_has_comment = False - has_lua_description = False - lua_start_description_line = lua_end_description_line = 0 - - - # First pass is to determine if there exists any comment blocks before any real code - while line_index0: - desc_line = ext_start_description_line - while desc_line <= ext_end_description_line: - updated_file_content.append(original_file_content[desc_line]) - desc_line += 1 - updated_file_content.append(AMAZON_EXT_HEADER_BOTTOM) - - elif is_lua: - updated_file_content.append(AMAZON_LUA_HEADER_TOP) - if is_original_crytek or is_original_crytek_header: - updated_file_content.append(LUA_FORMER_CRYTEK_HEADER+'\n') - updated_file_content.append('--\n--\n') - if lua_start_description_line>0: - desc_line = lua_start_description_line - while desc_line <= lua_end_description_line: - updated_file_content.append(original_file_content[desc_line]) - desc_line += 1 - updated_file_content.append(AMAZON_LUA_HEADER_BOTTOM) - - - elif is_py: - updated_file_content.append(PY_AMAZON_HEADER) - if is_original_crytek: - updated_file_content.append(PY_FORMER_CRYTEK_HEADER+'\n') - updated_file_content.append('#\n\n') - - elif is_bat: - updated_file_content.append(BAT_AMAZON_HEADER+'REM\n') - if is_original_crytek: - updated_file_content.append(BAT_FORMER_CRYTEK_HEADER+'\n') - updated_file_content.append('REM\n') - updated_file_content.append('\n') - if original_file_content[starting_code_index].lower().startswith('@echo off'): - starting_code_index += 1 - - line_index = starting_code_index - while line_index, which we strip off to generate the suffix - # We do this with a single p4 command for speed. - - print "Fetching vendor files dictionary" - - p = subprocess.Popen("p4 files //lyengine/vendor/...",shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) - pat = re.compile("^//lyengine/vendor/[^/]*/(.*)#.*") - for line in p.stdout: - line = line.strip() - m = pat.match(line) - if m: - vendorFiles[m.group(1)] = 1 - - # Stage 2, we look at all files under the provided root and check if the suffix minus the root is a file - # that occurs in a crytek original branch. - - print "Identified {0} unique file paths in original CryEngine branches(s).".format(len(vendorFiles)) - - print "Scanning files under: " + root - - # Now we scan the non-deleted files under our root (note the "p4 files -e" flag to skip deleted files!) - # For each of these files, we check if it was originally in a vendor drop or not - # partitioning into two lists, amazonFiles and crytekFiles. - # This is the first stage of determining which files get which copyright message. - # Because we may also have open source files, we must do further investigations to see - # which case we are in with each file. - - p = subprocess.Popen("p4 files -e " + root + "/...",shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) - pat = re.compile("^" + perforceRoot + "/(.*)#.*") - epat = re.compile("^.*/(SDKs|sdk|waf-.*)/") - - for line in p.stdout: - line = line.strip() - - # Skip files that are in external SDK directories, in the waf source or are not known code file types - if epat.match(line): - continue - - m = pat.match(line) - if m: - suffix = m.group(1) - # Skip files that are not code files unless they have a crytek copyright - if not codeFilePat.match(suffix) and not hasCrytekCopyrights(suffix): - continue - - if suffix in vendorFiles: - crytekFiles[suffix] = "Pure" - else: - amazonFiles[suffix] = "Pure" - - for file in amazonFiles.keys(): - - if skipFilesWithAmazonNotice and hasAmazonNotice(file): - amazonFiles[file] = "Skip" - elif has3rdPartyCopyrights(file): - amazonFiles[file] = "3rdParty" - - for file in crytekFiles.keys(): - if skipFilesWithAmazonNotice and hasAmazonNotice(file): - crytekFiles[file] = "Skip" - elif has3rdPartyCopyrights(file): - crytekFiles[file] = "3rdParty" - - return - -# This function scans a file to see if there are copyright notices or license notices from Crytek -def hasCrytekCopyrights(file): - try: - count = 0 - f=open(file) - p = re.compile(r".*\bcopyright\b|(c) ?[12][0-9][0-9][0-9]",re.IGNORECASE) - pCrytek = re.compile(r".*\bcrytek\b",re.IGNORECASE) - for line in f: - if p.match(line) and pCrytek.match(line): - return True - count += 1 - # Optimization. Crytek copyrights occur early in the file. Don't look too far into binary files. - if count > 100: - return False - return False - except: - return False - -# This function scans a file to see if there are official copyright headers from Amazon -def hasAmazonNotice(file): - try: - count = 0 - f=open(file) - - # Break up the notice lines to check in order - lines = OfficialNotice.strip('\n').splitlines() - # Index of the currently matched line for the whole notice - matchIndex = 0 - - for line in f: - line = line.strip('\n') - if line.endswith(lines[matchIndex]): - matchIndex += 1 - if matchIndex == len(lines): - return True - - count += 1 - # Optimization. Amazon copyrights occur early in the file. Don't look too far into binary files. - if count > 100: - return False - return False - except: - return False - -# This function scans a file to see if there are copyright notices or license notices -# from some party other than Amazon or Crytek -def has3rdPartyCopyrights(file): - try: - f=open(file) - p = re.compile(r".*\bcopyright\b|(c) ?[12][0-9][0-9][0-9]",re.IGNORECASE) - pAmazon = re.compile(r".*\bamazon\b",re.IGNORECASE) - pCrytek = re.compile(r".*\bcrytek\b",re.IGNORECASE) - pWAITING = re.compile(r".*COPYRIGHT_NOTICE_TBD",re.IGNORECASE) - for line in f: - if p.match(line) and not pAmazon.match(line) and not pCrytek.match(line) and not pWAITING.match(line): - return True - return False - except: - return False - -# We define some patterns to find and remove Amazon copyright header blocks here - -# This pattern must occur in every commment block we want to erase - -removeBlock=re.compile(r".*COPYRIGHT_NOTICE_TBD|.*Copyright.*Amazon.com",re.IGNORECASE) - -# Matches any # or // style comment -CStartBlock = re.compile(r"[ \t]*/\*") -CStopBlock = re.compile(r".*\*/[ \t]*\n") -XMLStartBlock = re.compile(r"[ \t]*[ \t]*\n") -CPPComment = re.compile(r"[ \t]*//") -LuaComment = re.compile(r"[ \t]*//") -BatchComment = re.compile(r"[ \t]*#(?!(def|if|endif|undef|pragma|include))") - -CrytekCopyright = re.compile(r"^.*(crytek.*copyright|crytek.*\(c\)|copyright.*crytek|\(c\).*crytek)",re.IGNORECASE) - -EngineIDLine = re.compile(r"^(.*)\b(Crytek Engine|Crytek CryEngine|(?","-- ") -LuaOfficialNotice = createNotice(OfficialNotice,"---","---","-- ") -BatchOfficialNotice = createNotice(OfficialNotice,"###","###","# ") - -def cleanLineofCrytek(line): - # Clean away original Crytek copyright notices - if CrytekCopyright.match(line): - line = re.sub(r"^([ \t]*)(//|#|)([ \t]*).*$", r"\1\2\3",line) - # Clean up references to CryEngine or Crytek Engine -> Lumberyard in block headers - if EngineIDLine.match(line): - line = EngineIDLine.sub(r"\1Lumberyard\3",line) - return line - - -def applyCopyrightNotice(file,extraNotice): - - # Check out for edit - p = subprocess.Popen("p4 edit \"" + file + "\"",shell=True) - p.wait() - - f=open(file) - fo=open("tmpfile","w") - - content = "" - count = 0 - - # Grab the first 50 lines to work with - # The rest we copy over without looking at them - - block="" - state="code" - remove=False - placeBlock=0 - - for line in f: - - # Try to put the comment underneath any include guards and pragma once statement - if placeBlock <=3 and re.match("^[ \t]*\n",line): placeBlock = placeBlock - elif placeBlock == 0 and re.match("^#ifndef ",line): placeBlock = 1 - elif placeBlock == 1 and re.match("^#define ",line): placeBlock = 2 - elif placeBlock == 2 and re.match("^#pragma once",line): placeBlock = 3 - elif placeBlock <= 4: placeBlock = 4 - - if placeBlock == 4: - placeBlock = 5 - # Place the official notice and the extra notice in place depending on file extension - extension = os.path.splitext(file)[1].lower() - if extension in ['.c','.h']: - fo.write(COfficialNotice) - if extraNotice: - fo.write("\n/* {0} */\n".format(extraNotice)) - elif extension in ['.cpp','.cc','.cs','.mm','.hpp','.hxx','.inl','.rc','.ext','.cfx','.cfi']: - fo.write(CPPOfficialNotice) - if extraNotice: - fo.write("\n// {0}\n".format(extraNotice)) - elif extension == ".lua": - fo.write(LuaOfficialNotice) - if extraNotice: - fo.write("\n-- {0}\n".format(extraNotice)) - elif extension == ".targets": # XML style comments - fo.write(XMLOfficialNotice) - if extraNotice: - fo.write("\n\n".format(extraNotice)) - else: - fo.write(BatchOfficialNotice) - if extraNotice: - fo.write("\n# {0}\n".format(extraNotice)) - - # After placig the main header - # Eat blank lines - if placeBlock == 5: - if line == "\n": continue - else: placeBlock = 6 - - count += 1 - state = startOrContinueBlock(line,state) - - if state != "code" and state != "finish": - line = cleanLineofCrytek(line) - if line != "\n": - block+=line - if removeBlock.match(line): remove=True - else: - if state == "finish": - line = cleanLineofCrytek(line) - if line != "\n": - block+=line - if block != "": - if not remove: fo.write(block) - remove=False - block="" - if state != "finish": - fo.write(line) - state = "code" - - if count > 50 and state == "code": - break - - # If we get out of the loop and we are in a block, the file ended - if state != "code" and block != "": - if not remove: fo.write(block) - remove=False - block="" - - # and now copy the rest of the file as is - for line in f: - fo.write(line) - - f.close() - fo.close() - - # Make a backup - #shutil.copyfile(file,file+".bak") - # Make the change - shutil.copyfile("tmpfile",file) - - -# Set up two lists to contain files originating with either Crytek or Amazon -# Each of these dictionaries will either have "Pure" or "3rdParty" for each file. -# Pure denotes files that have no 3rd party copyright notices associated with them. -# 3rdParty indicates a copyright message for some other party is present. - -amazonFiles = {} -crytekFiles = {} - - -# Partition the files by copyright notice conditions -partition_files(scanRoot) - -print "Done partition: classified {0} files.".format(len(amazonFiles)+len(crytekFiles)) - - -# Apply the appropriate copyright notices to each file - -changeCount = 0 -skipCount = 0 - -# log the files that we modify -amzn_pure = open('copyright_removal_amzn_pure.log', 'w') -amzn_3rdparty = open('copright_removal_amzn_3rdparty.log', 'w') -amzn_skip = open('copyright_removal_amzn_skip.log', 'w') -crytek_pure = open('copyright_removal_crytek_pure.log', 'w') -crytek_copyright_found = open('copyright_removal_crytek_copyright_found.log', 'w') -crytek_3rdparty = open('copyright_removal_crytek_3rdparty.log', 'w') -crytek_skip = open('copyright_removal_crytek_skip.log', 'w') - - -for file in amazonFiles.keys(): - if amazonFiles[file] == "Pure": - print "Apply Amazon Copyright: " + file - applyCopyrightNotice(file,"") - amzn_pure.write(file + '\n') - changeCount += 1 - elif amazonFiles[file] != "Skip": - print "Apply Amazon 3rd party notice: " + file - applyCopyrightNotice(file,"Modifications copyright Amazon.com, Inc. or its affiliates.") - amzn_3rdparty.write(file + '\n') - changeCount += 1 - else: - amzn_skip.write(file + '\n') - skipCount += 1 - -for file in crytekFiles.keys(): - if crytekFiles[file] == "Pure": - print "Apply Amazon sublicense of Crytek Notice: " + file - # In this case, even if Crytek did not assert copyright, we will do it for them? - applyCopyrightNotice(file,"Original file Copyright Crytek GMBH or its affiliates, used under license.") - crytek_pure.write(file + '\n') - changeCount += 1 - elif crytekFiles[file] != "Skip": - # in this case, double check if there is a crytek notice in the file - # and if the copyright notice that is there is near the top - if hasCrytekCopyrights(file): - print "Apply Amazon 3rd party notice and Crytek notice: " + file - applyCopyrightNotice(file,"Original file Copyright Crytek GMBH or its affiliates, used under license.") - crytek_copyright_found.write(file + '\n') - changeCount += 1 - else: - # This is a weird case. Crytek may or may not have changed the file, and have not asserted copyright. - # We assume that they did not, because it is all from some other party. - # These cases are few and probably bear investigation - print "Apply Amazon 3rd party notice and Crytek notice of origin?: " + file - applyCopyrightNotice(file,"Modifications copyright Amazon.com, Inc. or its affiliates.") - crytek_3rdparty.write(file + '\n') - changeCount += 1 - else: - crytek_skip.write(file + '\n') - skipCount += 1 - -amzn_pure.close() -amzn_3rdparty.close() -amzn_skip.close() -crytek_pure.close() -crytek_copyright_found.close() -crytek_3rdparty.close() -crytek_skip.close() - - - -print "Done editing. {0} files checked out and changed.".format(changeCount) -if skipCount > 0: - print "Skipped {0} files with existing Amazon notices.".format(skipCount) diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/crytek_3.8.1_source.txt b/Tools/build/JenkinsScripts/distribution/copyright_removal/crytek_3.8.1_source.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Tools/build/JenkinsScripts/distribution/copyright_removal/replace_crytek_copyright.py b/Tools/build/JenkinsScripts/distribution/copyright_removal/replace_crytek_copyright.py deleted file mode 100755 index 1f0204a29a..0000000000 --- a/Tools/build/JenkinsScripts/distribution/copyright_removal/replace_crytek_copyright.py +++ /dev/null @@ -1,126 +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. -""" - -import re -import os -import shutil -import stat - -max_num_lines_to_read = 30 -copyright_removed_count = 0 -special_case_count = 0 -star_comments = re.compile(r'/\*.*\*/', re.DOTALL) -flagged_extensions = ['.c', '.cpp', '.h', '.hpp', '.inl'] -skippable_extensions = ['.log', '.p4ignore', '.obj', '.dll', '.png', '.pdb', '.dylib', '.lib',\ - '.exe', '.flt', '.asi', '.exp', '.ilk', '.pch', '.res', '.bmp', '.cur',\ - '.ico', '.resx', '.jpg', '.psd', '.gif', '.a', '.fxcb', '.icns', '.cab',\ - '.chm', '.hxc', '.xsd', '.tif', '.xml'] -crytek_replacement_header = '// Original file Copyright Crytek GMBH or its affiliates, used under license.\n' -#categorizer = Categorizer() - -def remove_crytek_copyrights(): - for dirname, dirnames, filenames in os.walk('.'): - if skippable_directory(dirname): - continue - for filename in filenames: - full_filename = os.path.join(dirname, filename) - if skippable_file(filename): - continue - elif cpp_style_file(filename): - remove_crytek_copyright_from_file(full_filename) - - -def remove_crytek_copyright_from_file(full_filename): - comment_start_index, comment_end_index, comment_type = fetch_comment_indices_and_comment_type(full_filename) - if crytek_copyright_not_found(comment_start_index, comment_end_index, full_filename): - return - temp_file = full_filename + '_temp' - shutil.copyfile(full_filename, temp_file) - os.chmod(full_filename, stat.S_IWRITE) - with open(temp_file, 'r') as t, open(full_filename, 'w') as f: - # first, put in our replacement header - f.write(crytek_replacement_header) - for line_index, line in enumerate(t): - if inside_copyright_block(line_index, comment_start_index, comment_end_index): - continue - else: - f.write(line) - os.chmod(temp_file, stat.S_IWRITE) - os.remove(temp_file) - -def fetch_comment_indices_and_comment_type(full_filename): - start_index = -1 - end_index = -1 - comment_type = None - with open(full_filename, 'r') as f: - for index, line in enumerate(f): - if index <= max_num_lines_to_read: - start_index, end_index, comment_type = update_indices_and_type(start_index, end_index, comment_type, index, line) - else: - break - return start_index, end_index, comment_type - -def update_indices_and_type(start_index, end_index, comment_type, index, line): - # set start, end, or comment type if they haven't been set yet - if start_index == -1: - if '/*' in line: - start_index = index - if end_index == -1: - if '*/' in line: - end_index = index - - if comment_type == None: - if '/*' in line: - comment_type = 'star' - return start_index, end_index, comment_type - -def crytek_copyright_detected(lines): - return 'Crytek' in lines and 'Copyright' in lines - -def skippable_directory(directory): - skippable = 'SDKs' in directory - if skippable: - log('skipping directory' + directory) - return skippable - -def skippable_file(filename): - skippable = os.path.splitext(filename)[1] in skippable_extensions - if skippable: - log('skipping file ' + filename) - return skippable - -def cpp_style_file(filename): - return os.path.splitext(filename)[1] in flagged_extensions - -def crytek_copyright_not_found(comment_start_index, comment_end_index, filename): - not_found = comment_start_index == -1 or comment_end_index == -1 - if not_found: - log('Crytek copyright not found in file: {}.'.format(filename)) - else: - log('replacing copyright of ' + filename) - return not_found - -def inside_copyright_block(line_index, comment_start_index, comment_end_index): - return line_index >= comment_start_index and line_index <= comment_end_index - - -def main(): - remove_crytek_copyrights() - - -def log(msg, log_name=None): - print msg - if log_name != None: - log_name.write(msg) - -if __name__ == '__main__': - main() diff --git a/Tools/build/JenkinsScripts/distribution/get_changelist_number.py b/Tools/build/JenkinsScripts/distribution/get_changelist_number.py deleted file mode 100755 index 4d27f51aea..0000000000 --- a/Tools/build/JenkinsScripts/distribution/get_changelist_number.py +++ /dev/null @@ -1,20 +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. -""" - -import subprocess -import sys - -out = subprocess.check_output('p4 changes -m1 //lyengine/promotions/release_candidate_stable/...') - -changelist = out.split()[1] - -print changelist, diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitDailyValidation.py b/Tools/build/JenkinsScripts/distribution/git_release/GitDailyValidation.py deleted file mode 100755 index 0a5ca066e6..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitDailyValidation.py +++ /dev/null @@ -1,143 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# -import argparse -import tempfile -import shutil -import sys -import os - -THIS_SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, "..")) # Required for importing Git scripts -from GitRelease import mirror_repo_from_local -from GitIntegrityChecker import check_integrity, clone_from_url, IntegrityError, handleRemoveReadonly -from GitOpsCodeCommit import custom_clone -from GitOpsGitHub import create_authenticated_https_clone_url, are_credentials_valid - -def parse_args(): - parser = argparse.ArgumentParser(description="Performs validation of Git repos, and restores if necessary.") - parser.add_argument('--publicRepoURL', - help='The URL for the repository that we are validating the integrity of (expects a GitHub URL).', - required=True) - parser.add_argument('--backupRepoURL', - help='The URL for the repository that we are baselining our check of the public repository against. (expects a CodeCommit URL).', - required=True) - parser.add_argument('--hashFile', - help='Path to the file containing acceptable commit hashes.', - required=True) - parser.add_argument('--githubUser', - required=True, - help='Username for the Github account.') - parser.add_argument('--githubPassword', - required=True, - help='Password for the Github account.') - parser.add_argument('--ccUser', - required=True, - help='Username for the CodeCommit account.') - parser.add_argument('--ccPassword', - required=True, - help='Password for the CodeCommit account.') - parser.add_argument('--dryRun', - help='Execute without performing any restore.', - action="store_true") - args = parser.parse_args() - return args - - -def validate_args(args): - # ensure that backup repo isn't a github repo - github_domain = 'github.com' - if github_domain in args.backupRepoURL.lower(): - raise Exception('Cannot backup repo to another GitHub repo. Please use a git repo not on GitHub.') - # ensure that destination repo is a github repo - if github_domain not in args.publicRepoURL.lower(): - raise Exception('Cannot release to any repo other than one hosted on GitHub. Please use a git repo on GitHub.') - - if not os.path.exists(args.hashFile): - raise Exception(f'Hash file not found: {args.hashFile}') - - if not are_credentials_valid(args.githubUser, args.githubPassword): - raise Exception('Provided GitHub credentials are invalid.') - - -def restore_repo_from_backup(user, password, src_repo_url, dst_repo_url): - # Make a temporary workspace for cloning the CodeCommit repo. - temp_dir_path = tempfile.mkdtemp() - try: - clone_from_url(user, password, src_repo_url, temp_dir_path) - mirror_repo_from_local(temp_dir_path, dst_repo_url) - except: - raise - finally: - # Remove the temporary cloning workspace. - shutil.rmtree(temp_dir_path, ignore_errors=False, onerror=handleRemoveReadonly) - -def main(): - args = parse_args() - validate_args(args) - - github_repo_url = args.publicRepoURL - github_backup_repo_url = args.backupRepoURL - github_integrity_valid = True - github_hash_list = [] # init as empty list. - codecommit_integrity_valid = True - codecommit_hash_list = [] # init as empty list - - # - # Obtain integrity status - # - try: - print("Checking GitHub repo integrity...") - check_integrity(None, args.hashFile, False, - clone_from_url, args.githubUser, args.githubPassword, github_repo_url) - except IntegrityError as error: - print(error) - github_integrity_valid = False - github_hash_list = error.repo_hash_list - - try: - print("Checking CodeCommit repo integrity...") - check_integrity(None, args.hashFile, False, - clone_from_url, args.ccUser, args.ccPassword, github_backup_repo_url) - except IntegrityError as error: - print(error) - codecommit_integrity_valid = False - codecommit_hash_list = error.repo_hash_list - - # - # Validate integrity and restore if necessary. - # - print("Inspecting repo integrity results...") - if not codecommit_integrity_valid and not github_integrity_valid and codecommit_hash_list == github_hash_list: - raise Exception("Internal and external mirrors are identical, but the hashlist is different. " - "Internal hashlist has been compromised! Intervene manually.") - - if not codecommit_integrity_valid: - raise Exception("Internal Git mirror has been compromised. Intervene manually.") - - if not github_integrity_valid: - print("GitHub repository has been compromised! Executing restore operation.") - if args.dryRun: - print("Dry run: Skip restore operation") - else: - authenticated_github_repo_url = create_authenticated_https_clone_url(args.githubUser, args.githubPassword, github_repo_url) - restore_repo_from_backup(args.ccUser, args.ccPassword, github_backup_repo_url, authenticated_github_repo_url) - - # If we are here, all possible exceptions have been evaluated. - # It is safe to assume all is well. - print("Integrity validation succeeded.") - - -if __name__ == "__main__": - try: - main() - except Exception as e: - print(e) - sys.exit(1) diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitHashList.json b/Tools/build/JenkinsScripts/distribution/git_release/GitHashList.json deleted file mode 100644 index 6e0c78b42a..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitHashList.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Hashlist": [ - "d21172c26536133a4213873469a171f4f0c4280c", - "01c1c1acf52ebe65259df8c3706e7d3c156924fb", - "3c7dbc9b7e33050e99ceede18de61f6db5e15bef", - "44f7b2480f7a9839d3389b08f5945ef56092ebc4", - "cfd94c64e631911e9b3e98db606081c2ea5ff14d", - "e881f3023cc1840650eb7b133e605881d1d4330d", - "247aa1c6eb21e10db0cc566895444c7b5f855052", - "10c18d4c2296622d104be5b1146ffc8630d0fe8f", - "0b34452ef270f6b27896858dc7899c9796efb124", - "4648727c4c84f4bc224656f8adeef050581af344", - "9608bcf905bb60e9f326bd3fe8297381c22d83a6", - "931f5b9a04f7cf156bf7dec3165a1e74cb831209", - "87761bcdca2cf76fd4c6a976daf3e7a2dc08120c", - "164512f8d415d6bdf37e195af319ffe5f96a8f0b", - "6fef201546019126306a6b47d5b9e1f2d82d56ae", - "2d8969362cd5fa5523c231e5e3abb6d855e31d59", - "d10be93eb4c147af77ac90bc36137f7cd4e0e510", - "24840d0102c4ebda6334bf7355ecd34c0fd5eda7", - "6b8dd98ad0e59b1817a79f6aaf5b89afb41b1086" - ] -} \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityChecker.py b/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityChecker.py deleted file mode 100755 index c20396f176..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityChecker.py +++ /dev/null @@ -1,203 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# -import argparse -import errno -import json -import os -import shutil -import stat -import subprocess -import tempfile -import sys - -THIS_SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, "..")) # Required for importing Git scripts -from GitOpsGitHub import create_authenticated_https_clone_url -from GitOpsCommon import get_revision_list - -HASHLIST_KEY = 'Hashlist' - - -class IntegrityError(RuntimeError): - """Exception type for failed integrity check.""" - def __init__(self, message, file_hash_list, repo_hash_list): - self.message = message - self.hash_list = file_hash_list - self.repo_hash_list = repo_hash_list - - -def handleRemoveReadonly(func, path, exc): - """ - Python has issues removing files and directories on Windows - (even if we've just created them) if they were set to 'readonly'. - This usually occurs when deleting a '.git' directory, because some internal - git repository files become 'readonly' when initializing a new repo. - The following function should override general permission issues when - deleting. - """ - excvalue = exc[1] - if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 - func(path) - else: - raise - - -def validate_args(args): - all_github_args_valid = (args.githubUser is not None and - args.githubPassword is not None) - assert (all_github_args_valid or args.gitLocation is not None), 'Please provide GitHub information, ' \ - 'or a path to a git repository on disk.' - if all_github_args_valid and args.gitLocation is not None: - print("Warning: A GitHub username and a path to a git repository have been provided. These commands are not " \ - "compatible, and this script will default to using provided GitHub credentials.") - - # If a working directory was given, verify it exists and is empty. - if args.workingDirectory is not None: - assert (os.path.exists(args.workingDirectory)), 'If using the working directory argument, please provide a ' \ - 'directory that exists on disk.' - assert (os.listdir(args.workingDirectory) == []), 'Please provide an empty working directory.' - - -def parse_args(): - parser = argparse.ArgumentParser(description="Compares the commit hashes of a git repository against" - "a known good hash list.") - parser.add_argument('-gitRepoURL', - help='The URL for the repository that we are checking the integrity of.', - required=True) - parser.add_argument('--hashFile', - help='Path to the file containing acceptable commit hashes.', - required=True) - - # Either a Github username and password need to be passed in, or a location of a git install on disk. - parser.add_argument('--githubUser', - default=None, - help='Username for the Github account.') - parser.add_argument('--githubPassword', - default=None, - help='Password for the Github account.') - parser.add_argument('--preserveGithubClone', - help='If using Github, preserves the cloned data on disk for inspection by the user.', - required=False, - action="store_true") - - parser.add_argument('--gitLocation', - default=None, - help='Path to a git repository on disk. Cloning will not occur if this is set.') - - parser.add_argument('--workingDirectory', - default=None, - help='Path to a temporary working directory. If not supplied, tempfile.mkdtemp will be used.') - args = parser.parse_args() - validate_args(args) - return args - - -def load_json_hashes(json_file_path): - file_data = open(json_file_path, 'r') - json_file_data = json.load(file_data) - file_data.close() - file_hashes = json_file_data[HASHLIST_KEY] - return file_hashes - - -def clone_from_url(github_user, github_password, github_repo, root_dir=None): - if root_dir is None: - root_dir = os.getcwd() - if os.path.exists(root_dir) and os.path.isdir(root_dir): - print("Cloning from GitHub into directory:\n" + root_dir) - authenticated_clone_url = create_authenticated_https_clone_url(github_user,github_password, github_repo) - subprocess.call(["git", "clone", "--no-checkout", authenticated_clone_url, root_dir]) - else: - raise Exception(root_dir, "Provided path is not a valid directory on disk.") - - -def validate_hash_counts_match(git_hashes, json_hashes): - return len(git_hashes) == len(json_hashes) - - -def validate_hashes_match(git_hashes, json_hashes): - for git_hash, json_hash in list(zip(git_hashes, json_hashes)): - if git_hash != json_hash: - return False, git_hash, json_hash - return True, None, None - - -def check_integrity(working_directory, hash_file, preserve_github_clone, git_clone_function, *extra_args): - """ - Checks the integrity of a specified repo. Will raise an exception if integrity fails. - - :param working_directory: Where the repo will be cloned. - :param hash_file: The hashfile to compare against for verifying integrity. - :param preserve_github_clone: True, if we want to keep the repo on disk after integrity check. - :param git_clone_function: A clone operation function. GitHub & CodeCommit clone differently due to authentication. - :param extra_args: Arguments for the clone operation function. - :return: - """ - - # Create a sub-folder for easy cleanup. - if working_directory is not None: - local_git_location = os.path.join(working_directory, "temp_git_repo") - os.makedirs(local_git_location) - else: - local_git_location = tempfile.mkdtemp() - - # Change directory to the intended location before cloning. Regardless of success or fail, - # we must change back to inital directory and delete the temp repo, if necessary. It is important - # that we return to the initial directory because this function may be called from other Python modules. - # We will use try/finally to ensure we always return to the initial directory. - try: - initial_dir = os.getcwd() - os.chdir(local_git_location) - git_clone_function(*extra_args) - - json_hashes = load_json_hashes(hash_file) - - # This git logging function results in all hashes for the repository printed out, one per line. - git_hashes = get_revision_list(local_git_location) - - finally: - # No more Git operations to be made, restore CWD - os.chdir(initial_dir) - - # Once we have the list of hashes, we can clean up all of the temp files that were created. - if not preserve_github_clone: - print("Deleting cloned Git repository.") - shutil.rmtree(local_git_location, ignore_errors=False, onerror=handleRemoveReadonly) - - if not validate_hash_counts_match(git_hashes, json_hashes): - exception_message = "ERROR: Length of hash lists do not match. There are " + \ - str(len(git_hashes)) + " git commits, and " + str(len(json_hashes)) + \ - " hashes in the passed in JSON file." - raise IntegrityError(exception_message, json_hashes, git_hashes) - - hash_result, git_hash, json_hash = validate_hashes_match(git_hashes, json_hashes) - - if not hash_result: - exception_message = "ERROR: Hashes do not match. Git hash '" + git_hash + "'. JSON hash '" + json_hash + "'" - raise IntegrityError(exception_message, json_hashes, git_hashes) - - print("All hashes match.") - - -def main(): - args = parse_args() - check_integrity( - args.workingDirectory, - args.hashFile, - args.preserveGithubClone, - clone_from_url, - args.githubUser, - args.githubPassword, - args.gitRepoURL - ) -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityCheckerTester.py b/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityCheckerTester.py deleted file mode 100755 index c9ae0612e6..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitIntegrityCheckerTester.py +++ /dev/null @@ -1,47 +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. -""" - -import unittest -import GitIntegrityChecker - - -class GitIntegrityCheckerTester(unittest.TestCase): - - def test_hashCountMatch_withEqualCounts_returnsTrue(self): - list_1 = ["A", "B", "C"] - list_2 = ["A", "B", "C"] - self.assertTrue(GitIntegrityChecker.validate_hash_counts_match(list_1, list_2)) - - def test_hashCountMatch_withBiggerList1_returnsFalse(self): - list_1 = ["A", "B", "C", "D"] - list_2 = ["A", "B", "C"] - self.assertFalse(GitIntegrityChecker.validate_hash_counts_match(list_1, list_2)) - - def test_hashCountMatch_withBiggerList2_returnsFalse(self): - list_1 = ["A", "B", "C"] - list_2 = ["A", "B", "C", "D"] - self.assertFalse(GitIntegrityChecker.validate_hash_counts_match(list_1, list_2)) - - def test_hashMatch_withIdenticalLists_returnsTrue(self): - list_1 = ["A", "B", "C"] - list_2 = ["A", "B", "C"] - match_results, list_1_out, list_2_out = GitIntegrityChecker.validate_hashes_match(list_1, list_2) - self.assertTrue(match_results) - - def test_hashMatch_withDifferentLists_returnsFalse(self): - list_1 = ["A", "B", "D"] - list_2 = ["A", "B", "C"] - match_results, list_1_out, list_2_out = GitIntegrityChecker.validate_hashes_match(list_1, list_2) - self.assertFalse(match_results) - -if __name__ == '__main__': - unittest.main() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitMoveDetection.py b/Tools/build/JenkinsScripts/distribution/git_release/GitMoveDetection.py deleted file mode 100755 index d21825b47c..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitMoveDetection.py +++ /dev/null @@ -1,331 +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. -# -from P4 import P4 -import subprocess -import os -import re - - -class MoveDetection: - """ - This class scans two Perforce branches at a specific revision to determine which files have been moved from one - branch to another. The core logic relies on finding a historical common ancestor of a file split between the two - specified branches. - """ - def __init__(self): - self.p4 = P4() - self.p4.connect() - self.parent = dict() - self.history_data = dict() - """ - --- Below is a sample structure for intended use of the 'history_data' dictionary. - --- This dictionary is constructed/populated what we call build_parent_hash(). - history_data: - { - "//lyengine/releases/ver01_10": - { - roots: - { - [p4_filepath, revision] - } - rev_roots: - { - [p4_filepath, revision] - } - files: - { - [p4_filepath, revision] - } - } - "//lyengine/releases/ver01_11": - { - ... - } - } - """ - - @staticmethod - def branch_pathname_to_inclusive_pathspec(branch_key): - if branch_key.endswith('/'): - return branch_key + '...' - else: - return branch_key + '/...' - - @staticmethod - def generate_filelist_hashes(branch_key, branch_cl_revspec): - """ - Generates iterable listing of files on a branch for use when calculating file ancestor data. - :param branch_key: - The branch to scan for files. - :param branch_cl_revspec: - Used to generate the file list at the point in time of specified P4 revspec. - Typically, this value is with a P4 CL number (i.e. @44569). - :return complete_file_list_hash, file_list_hash: - Two iterable collections of file hashes - One including deleted files, another excluding deleted files. - """ - file_list_filename = branch_key.replace('/', '.') + '_files.log' - if not os.path.exists(file_list_filename): - file_list_fp = open(file_list_filename, "w+") - - command = f'p4 files {MoveDetection.branch_pathname_to_inclusive_pathspec(branch_key)}@{branch_cl_revspec}' - print('Performing: ' + command) - subprocess.check_call(command.split(), stdout=file_list_fp) - # begin reading from the start - file_list_fp.seek(0) - else: - file_list_fp = open(file_list_filename, 'r') - - complete_file_list_hash = {} # All files, including deleted ones. - file_list_hash = {} # All files, excluding deleted ones. - - for line in file_list_fp: - filename = re.sub('(#[0-9][0-9]*) - .*', "", line).strip() - revision = re.sub('.*(#[0-9][0-9]*) - .*', "\\1", line).strip() - action = re.sub('.*#[0-9]* - ', '', line).strip() - if not action.startswith('delete change'): - file_list_hash[(filename, revision)] = True - complete_file_list_hash[(filename, revision)] = True - - file_list_fp.close() - return complete_file_list_hash, file_list_hash - - @staticmethod - def generate_history_data(branch_cl_revspec, branch_key, complete_file_list_hash): - """ - Calculates historical data to identify ancestor/roots (original name of a file when added) and - descendants/reverse-roots (all the possible permutations of an original file, whether via copy, branch, or move) - - :param branch_cl_revspec: - Used to generate the file list at the point in time of specified P4 revspec. - Typically, this value is with a P4 CL number (i.e. @44569). - :param branch_key: - The branch to scan for files. - :param complete_file_list_hash: - An iterable collection of the latests files on the branch to compare with. - :return temp_rev_roots, temp_roots: - Dictionaries depicting file ancestors and possible descendants for each file. - """ - file_log_filename = branch_key.replace('/', '.') + '_filelog.log' - if not os.path.exists(file_log_filename): - file_log = open(file_log_filename, "w+") - command = 'p4 filelog -h -s -p {0}@{1}'.format(MoveDetection.branch_pathname_to_inclusive_pathspec(branch_key), - branch_cl_revspec) - print('Performing: ' + command) - subprocess.check_call(command.split(), stdout=file_log) - # begin reading from the start, immediately after populating the file. - file_log.seek(0) - else: - file_log = open(file_log_filename, 'r') - ''' - Loop control vars - ''' - DEFAULT_VALUE = (str(), -1) - potential_ancestor = DEFAULT_VALUE # ( filename, revision ) - current_parsed_filename = DEFAULT_VALUE - current_branch_filename = DEFAULT_VALUE - temp_roots = dict() # for calculation purposes - temp_rev_roots = dict() # for calculation purposes - cur_line = 0 - # Begin parsing file log - for line in file_log: - if line.startswith('//'): # Filename - potential_ancestor = current_parsed_filename - current_parsed_filename = (line.strip(), -1) - - elif line.startswith('... #'): # Revision - if current_parsed_filename[1] == -1: # If no revision has been found yet... - current_parsed_filename = (current_parsed_filename[0], line.split()[1]) # Gets the revision number. - - # If we are parsing a filename existing in our current/latest revision... - # We use the complete file list hash because we want to account for deleted files when - # building the ancestry data. Unfortunately, 'p4 filelog' does not support excluding deleted files. - # We have to filter this out manually... - if current_parsed_filename in complete_file_list_hash: - # Treat this filename as a child filename, and begin scanning it's ancestors. - # This is the starting point of a file's rename/move history. - - # If the 'current_branch_filename' IS NOT the default value... - # (This basically means we avoid a default-initialization value as a key in the dict.) - if current_branch_filename != DEFAULT_VALUE: - # Close out history on prior file... - - # Track filename root - temp_roots[current_branch_filename] = potential_ancestor - # Track filename reverse root. - if potential_ancestor not in temp_rev_roots: - temp_rev_roots[potential_ancestor] = list() - temp_rev_roots[potential_ancestor].append(current_branch_filename) - - # Start tracking history of the next file - current_branch_filename = current_parsed_filename - - cur_line += 1 - file_log.close() - # Close history for the last file in the log file's history/entry. - temp_roots[current_branch_filename] = potential_ancestor - if potential_ancestor not in temp_rev_roots: - temp_rev_roots[potential_ancestor] = list() - temp_rev_roots[potential_ancestor].append(current_branch_filename) - return temp_rev_roots, temp_roots - - def build_parent_hash(self, branch_key, branch_cl_revspec): - """ - :param branch_key: - The branch to scan for files. - :param branch_cl_revspec: - Used to generate the file list at the point in time of specified P4 revspec. - Typically, this value is with a P4 CL number (i.e. @44569). - """ - - # Get files list - complete_file_list_hash, file_list_hash = self.generate_filelist_hashes(branch_key, branch_cl_revspec) - # Get file history - file_reverse_roots, file_roots = self.generate_history_data(branch_cl_revspec, branch_key, - complete_file_list_hash) - - # Construct results. Save data to class members. - self.history_data[branch_key] = dict() - self.history_data[branch_key]['roots'] = file_roots - self.history_data[branch_key]['rev_roots'] = file_reverse_roots - # Below, we save only the currently existing files as a means to iterate over all files, without having to query - # Perforce continuously. - self.history_data[branch_key]['files'] = file_list_hash - - def find_moved_files_between_branches(self, p4_branch_name_src, p4_branch_name_dst): - """ - Find files in revisionB that have moved from revisionA - """ - file_move = list() - - for Bfile in self.history_data[p4_branch_name_dst]['files']: - root_b = self.history_data[p4_branch_name_dst]['roots'][Bfile] - dest_filename = Bfile[0].split(p4_branch_name_dst)[1] - - # If 'Bfile' shares a common ancestor with any file in 'branchA'... - if root_b in self.history_data[p4_branch_name_src]['rev_roots']: - reverse_roots_a = self.history_data[p4_branch_name_src]['rev_roots'][root_b] # Related candidates - - # Scan the candidates to see if any of them depict the file WAS NOT moved/branched/copied. - found_exact_file_in_both_branches = False - for Afile in reverse_roots_a: - src_filename = Afile[0].split(p4_branch_name_src)[1] - if src_filename == dest_filename: - found_exact_file_in_both_branches = True - break - - # If there is no sign of the file in the other branch, we have moved the file. - if found_exact_file_in_both_branches is False: - # Register a file move - file_move.append((src_filename, dest_filename)) - print(file_move[-1]) - - return self.filter_file_moves_to_dev(file_move) - - @staticmethod - def filter_file_moves_to_dev(file_moves): - filtered_moves = list() - for move in file_moves: - if move[0].startswith('dev/'): - filtered_moves.append(move) - return filtered_moves - - @staticmethod - def chrono_sort_moves(move_list): - """ - Sorts file moves in chronological operations to avoid out-of-order rename stomping. - :param move_list: - List of tuples {src_filename, dst_filename} - :return: - A sorted list that can be iterated from beginning to end for rename opterations, without stomping conflicts. - """ - # Iterate through all the moves to construct a linked list. - head_to_tail_mapping = dict() # All the filenames for the start of a chain. (For discovering insertion points) - chains = dict() # A collecton of a chain of moves (A->B->C->D file renames) - tail_to_head_mapping = dict() # All the filenames at the end of a chain. (For discovering insertion points) - - for move in move_list: # tuple: (src, dst) - src = move[0] - dst = move[1] - - # Create a chain for this move. - chains[src] = [src, dst] - head_to_tail_mapping[src] = dst - tail_to_head_mapping[dst] = src - - # Possible outcomes: - # Extending the end of an existing chain... - if src in tail_to_head_mapping: - - # Update our tails & heads - new_tail = head_to_tail_mapping[src] # Tail of the chain starting with 'src' - new_head = tail_to_head_mapping[src] # Tail of the chain ending with 'src' - - # Join above two chains together. - tail_to_head_mapping[new_tail] = new_head - head_to_tail_mapping[new_head] = new_tail - - # Update chain. - chains[new_head] = chains[new_head] + chains[src][1:] # Remove first duplicate entry - - # Clean-up - del head_to_tail_mapping[src] - del tail_to_head_mapping[src] - del chains[src] - - # Extending the beginning of an existing chain... - if dst in head_to_tail_mapping: - # Update our tails & heads - new_tail = head_to_tail_mapping[dst] # Tail of the chain starting with 'dst' - new_head = tail_to_head_mapping[dst] # Tail of the chain ending with 'dst' - - # Extend. - chains[new_head] = chains[new_head] + chains[dst][1:] # Remove first duplicate entry - - # Join above two chains together. - tail_to_head_mapping[new_tail] = new_head - head_to_tail_mapping[new_head] = new_tail - - # Clean-up. - del head_to_tail_mapping[dst] - del tail_to_head_mapping[dst] - del chains[dst] - - # Construct list from chains - return_list = list() - for cur_chain in chains: - previous_filename = None - - reverse_chain = chains[cur_chain] - reverse_chain.reverse() - - for current_filename in reverse_chain: - if previous_filename: - # We are appending in reverse order. - # When renaming, we go from the end of the list, to the beginning. - # This way we avoid stomping renames. - return_list.append((current_filename, previous_filename)) - previous_filename = current_filename - - return return_list - - def generate_list_files_moved_between_branches(self, branch_cl_tuple_src, branch_cl_tuple_dst): - """ - :param branch_cl_tuple_src: - {Tuple} (branch, revision/build number) - :param branch_cl_tuple_dst: - {Tuple} (branch, revision/build number) - :return: - A list of tuples (filename before, filename after) ordered by intended chronological move operations - """ - self.build_parent_hash(branch_cl_tuple_src[0], branch_cl_tuple_src[1]) - self.build_parent_hash(branch_cl_tuple_dst[0], branch_cl_tuple_dst[1]) - file_moves = self.find_moved_files_between_branches(branch_cl_tuple_src[0], branch_cl_tuple_dst[0]) - return self.chrono_sort_moves(file_moves) diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCodeCommit.py b/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCodeCommit.py deleted file mode 100755 index be8e16d490..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCodeCommit.py +++ /dev/null @@ -1,75 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# - -""" -This file is the central location for functions and operations for CodeCommit that are shared accross different scripts. -""" -import subprocess -import os -import git - -# Initializes a Git repository configured with necessary settings to access CodeCommit via AWS CLI credentials. -def init_git_repo(aws_repo_url, awscli_profile, local_repo_directory): - """ - Initializes a Git repository configured with necessary settings to access CodeCommit via AWS CLI credentials. - - :param aws_repo_url: Clone URL for the CodeCommit repo - :param awscli_profile: AWS CLI profile with access/permissions to the repo. - :param local_repo_directory: Clone directory - :return: - """ - - parse_key = "amazonaws.com" - host_domain_end_index = aws_repo_url.index(parse_key) + len(parse_key) - host_domain = aws_repo_url[:host_domain_end_index] - - subprocess.call(["git", "init", local_repo_directory]) - - config_append = f""" -[credential "{host_domain}"] -\thelper = !aws --profile {awscli_profile} codecommit credential-helper $@ -\tUseHttpPath = true - -[remote "origin"] -\turl = {aws_repo_url} -\tfetch = +refs/heads/*:refs/remotes/origin/* - -[branch "master"] -\tremote = origin -\tmerge = refs/heads/master -""" - - config_filepath = os.path.join(local_repo_directory, '.git', 'config') - - with open(config_filepath, "a") as myfile: - myfile.write(config_append) - - -def custom_clone(aws_repo_url, awscli_profile, local_repo_directory, setup_tracking_branches): - print("Initializing local repo with custom AWS CodeCommit config...") - initial_directory = os.getcwd() - os.chdir(local_repo_directory) - init_git_repo(aws_repo_url, awscli_profile, local_repo_directory) - os.chdir(initial_directory) - - repo = git.Repo(local_repo_directory) - - print(f"Fetching from remote: {aws_repo_url}") - repo.remote().fetch() # Fetch branches - repo.remote().fetch("--tags") # Fetch tags - - if setup_tracking_branches: - for remote_branch in repo.remote().refs: - branch_name = remote_branch.remote_head - repo.create_head(branch_name, remote_branch) \ - .set_tracking_branch(remote_branch) - - return repo diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCommon.py b/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCommon.py deleted file mode 100755 index de38537fa7..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsCommon.py +++ /dev/null @@ -1,24 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# -""" -This file is the central location for functions and operations common to GitHub and CodeCommit -""" - -import subprocess - - -def get_revision_list(repo_diretory): - print(f"Parsing hashes from git repository: {repo_diretory}") - p = subprocess.Popen(["git", "rev-list", "--all"], stdout=subprocess.PIPE, cwd=repo_diretory) - (git_hash_output, git_hash_error) = p.communicate() - if git_hash_error is not None: - raise Exception(git_hash_error) - return git_hash_output.splitlines() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsGitHub.py b/Tools/build/JenkinsScripts/distribution/git_release/GitOpsGitHub.py deleted file mode 100755 index 92e7e5e874..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitOpsGitHub.py +++ /dev/null @@ -1,49 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# - -""" -This file is the central location for functions and operations for GitHub that are shared accross different scripts. -""" -from urllib.parse import quote_plus -from github import Github, BadCredentialsException - - -def create_authenticated_https_clone_url(github_user, github_password, https_endpoint_url): - # Windows does not ship with SSH, and we need a universally usable approach. - # This is why we opt for HTTPS authentication. Without user input, we will - # need to inject username/password into the repo url at - # 'auth_insertion_offset'. - # Example resulting URL- https://username:password@endpoint.com/repo.git - auth_insertion_offset = 8 - - # If you have a symbol like @ in your username or password, it will mess up the url command to clone. - # urllib.quote_plus replaces special characters with url safe characters, turning @ into %40. - url_safe_password = quote_plus(github_password) - url_safe_user = quote_plus(github_user) - - authenticated_url = "{0}{1}:{2}@{3}".format(https_endpoint_url[:auth_insertion_offset], - url_safe_user, - url_safe_password, - https_endpoint_url[auth_insertion_offset:]) - return authenticated_url - - -def are_credentials_valid(username, password): - auth_test_obj = Github(username, password) - - try: - for repo in auth_test_obj.get_user().get_repos(): - # Will raise 'Bad Credentials' exception if can't find name. - repo.name - except BadCredentialsException: - return False - - return True diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitPromotion.py b/Tools/build/JenkinsScripts/distribution/git_release/GitPromotion.py deleted file mode 100755 index 20849e3831..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitPromotion.py +++ /dev/null @@ -1,417 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# -from P4 import P4 -import argparse -import boto3 -import os -import sys -import shutil -from importlib import reload -from urllib.parse import urlparse -from git import Repo, RemoteProgress -from git.repo.base import InvalidGitRepositoryError, NoSuchPathError - -THIS_SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, "..")) # Required for AWS_PyTools -from GitStaging import handle_remove_readonly, clean_replace_repo_contents -from GitOpsCodeCommit import custom_clone, init_git_repo -from GitMoveDetection import MoveDetection - - -class MyProgressPrinter(RemoteProgress): - def update(self, op_code, cur_count, max_count=None, message=''): - print(op_code, cur_count, max_count, cur_count / (max_count or 100.0), message or "NO MESSAGE") - - -def create_args(): - parser = argparse.ArgumentParser(description='Promotes a specified release from the \'SignedBuilds\' repository.') - parser.add_argument('--sourceRepoURL', - help='The URL for the repository that we are taking the contents of the promotion from.', - required=True) - - parser.add_argument('--destinationRepoURL', - help='The URL for the repository that we are promoting content to.', - required=True) - - parser.add_argument('--commitRef', - help='A valid Git reference from the staging repo to use as a base for building the new commit.' - ' Usually a Perforce changelist number (the staging repo\'s tag names).', - required=True) - - parser.add_argument('--localRepoDirectory', - help='Path to the local repository where the Git work takes place. ' - 'If the directory does not exist, it will be created. ' - 'If the directory contains no repository, a new local clone will be created.', - required=True) - - parser.add_argument('--genRoot', - help='Directory for temp files.', - default="", - required=True) - - parser.add_argument('--dryRun', - help='Runs without pushing or modifying remotes.', - action="store_true", - required=False) - - parser.add_argument('--clean', - help='Runs with a clean slate. Deletes any pre-existing files that may cause conflicts.', - action="store_true", - required=False) - - # we should assume that the account containing staging repo is the same as the account containing promotion repo - parser.add_argument('--awsProfile', - help='AWS credentials profile generated from AWS CLI. Defaults to \'default\'.', - required=False, - default='default') - return parser.parse_args() - - -def validate_args(args): - #ensure that source and dest repos aren't github repos - github_domain = "github.com" - if github_domain in args.sourceRepoURL.lower() or github_domain in args.destinationRepoURL.lower(): - abort_operation("Cannot promote to or from GitHub directly. Please use a git repo not on GitHub.") - - #ensure that repo urls don't have a trailing slash - if args.sourceRepoURL.endswith('/'): - args.sourceRepoURL = args.sourceRepoURL[:-1] - if args.destinationRepoURL.endswith('/'): - args.destinationRepoURL = args.destinationRepoURL[:-1] - - # ensure aws profile exists on the machine - if args.awsProfile: - if boto3.Session(profile_name=args.awsProfile) is None: - abort_operation("The AWS CLI profile name specified does not exist on this machine. Please specify an existing AWS CLI profile.") - - -def get_repo_name(url): - url_path = urlparse(url).path - return os.path.split(url_path)[-1] - - -def generate_workspace_repo(local_repo_directory, aws_profile_name, source_repo_name, source_repo_url, dest_repo_url): - repo_url = dest_repo_url - init_git_repo(repo_url, aws_profile_name, local_repo_directory) - repo = Repo(local_repo_directory) - repo.git.fetch('origin') - repo.git.fetch('origin', '--tags') - - # Add remote for 'signed release builds' repo - repo.create_remote(source_repo_name, source_repo_url) - repo.git.fetch(source_repo_name) - repo.git.fetch(source_repo_name, '--tags') - return repo - - -def branch_name_from_version_string(version_string): - version_split = version_string.split(".") - return f"{version_split[0]}.{version_split[1]}" - - -def rename_tag(old_name, new_name, remote_name, repo, dryRun): - # Create copy of old tag - repo.git.tag(new_name, old_name) - if not dryRun: - repo.git.push(remote_name, new_name) - # Delete old tag - repo.git.tag("-d", old_name) - if not dryRun: - repo.git.push(remote_name, ":" + old_name) - - -def init_mix_repo(local_repo_directory, aws_profile_name, source_repo_name, source_repo_url, dest_repo_url): - # Acquire git repo with dependent remotes - try: - mix_repo = Repo(local_repo_directory) - - # Delete all the local tags before we fetch to ensure tags are synchronized. - for tag in mix_repo.tags: - mix_repo.delete_tag(tag) - mix_repo.remote('origin').fetch(progress=MyProgressPrinter()) - mix_repo.remote(source_repo_name).fetch(progress=MyProgressPrinter()) - except InvalidGitRepositoryError: - print("No local repo in specified directory. Deleting local contents & creating repo from remote.") - shutil.rmtree(local_repo_directory, onerror=handle_remove_readonly) - mix_repo = generate_workspace_repo(local_repo_directory, aws_profile_name, source_repo_name, source_repo_url, dest_repo_url) - except NoSuchPathError: - print("Local directory does not exist. Creating new directory and local repo within it...") - mix_repo = generate_workspace_repo(local_repo_directory, aws_profile_name, source_repo_name, source_repo_url, dest_repo_url) - return mix_repo - - -def ensure_tag_exists(repo, commit_ref, source_repo_url, dest_repo_url): - if commit_ref not in repo.tags: - available_tags = ('\n'.join(str(p) for p in repo.tags)) - raise Exception("ERROR: '{0}' tag does not exist in '{1}' or '{2}' repositories. \ - Has it already been promoted?\n\nTags available:\n{3}".format( - commit_ref, - source_repo_url, - dest_repo_url, - available_tags)) - - -def get_ly_version_from_mirror_repo(mirror_repo): - # Find tag for the specified commit of GitHubMirror repo. - version_tag = get_tag_for_commit(mirror_repo, mirror_repo.head.commit) - return str(version_tag)[1:] # drop the 'v' from tag string. - - -def get_tag_for_commit(repo, commit): - return next((tag for tag in repo.tags if tag.commit == commit), None) - - -def find_cl_for_ly_version_from_staging_repo(ly_version_string, mix_repo, repo_remote_name): - """ - Get last promoted commit of version branch in SignedBuilds repo - :param ly_version_string: string of a lumberyard version (X.X.X.X) - :param mix_repo: repository object containing a remote to the SignedBuilds repo. - :param repo_remote_name: Alias for the git remote repository representing the staging repo. - :return: The string value of the changelist number. - """ - refs = mix_repo.remotes[repo_remote_name].refs - staging_repo_version_branch = refs[ly_version_string] - staging_repo_version_branch_head = staging_repo_version_branch.commit - - # Traverse all commits in the branch to find a match for '*-Promoted'. - commit = staging_repo_version_branch_head - while commit: - # If we have a promoted tag... - commit_tag = get_tag_for_commit(mix_repo, commit) - if commit_tag is not None and 'Promoted' in commit_tag.name: - # Return the int value of the CL number - return ''.join(filter(str.isdigit, commit_tag.name)) - - if len(staging_repo_version_branch_head.parents) > 1: - raise Exception(f'Commit {commit} has more than one parent: {staging_repo_version_branch_head.parents}') - - commit = staging_repo_version_branch_head.parents[0] - - raise Exception('Could not find tagged release. Dev Error') - - -def generate_move_commit(mirror_repo, branch_name_src, build_number_src, branch_name_dst, build_number_dst): - """ - Performs a Git commit containing only file moves between two Lumberyard releases. - - :param mirror_repo: - GitPython repository reference - :param branch_name_src: - Name of the SOURCE Perforce branch - :param build_number_src: - Build/Changelist number within the SOURCE branch - :param branch_name_dst: - Name of the DESTINATION Perforce branch - :param build_number_dst: - Build/Changelist number within the DESTINATION branch - :return: - """ - - # We want to skip generating a move-commit if there is no prior history to create a range from. This condition can - # be present in any branch, not just the repo as a whole. - # At the time of execution, we expect at least 1 commit already present. The existing commit represents the previous - # commit, whereas the incoming commit represents the next commit. In this function, we create the commit that is - # lodged in the middle; the move-commit. - rev_list_count = int(mirror_repo.git.rev_list('HEAD', '--count')) - if rev_list_count < 1: - raise Exception('Cannot promote an empty branch.') - - move_detection = MoveDetection() - file_moves = move_detection.generate_list_files_moved_between_branches((branch_name_src, build_number_src), - (branch_name_dst, build_number_dst)) - if len(file_moves) == 0: - print('No files moved between releases. Skipping move-commit generation.') - else: - skipped_files = list() - for move in file_moves: - filename_before = os.path.join(mirror_repo.working_dir, move[0]) - filename_after = os.path.join(mirror_repo.working_dir, move[1]) - - # If the old file is not found, it's likely due to a file move happening outside the repo's tracked directory. - # Such a case occurs when files in the additive zip have moved/renamed. We don't care about these files. - if not os.path.exists(filename_before): - skipped_files.append(move) - continue - - filename_after_dir = os.path.dirname(filename_after) - if not os.path.exists(filename_after_dir): - os.makedirs(filename_after_dir) - - # Git is attempting to move to an existing file. Skip this move. - if os.path.exists(filename_after): - continue - - mirror_repo.git.mv(filename_before, filename_after) - - print('Skipped processing the following moves not tracked by the git repository:') - for entry in skipped_files: - print(entry) - - mirror_repo.index.commit("Move Commit") - - -def format_p4_branch_from_ly_version(ly_version): - split_version = ly_version.split('.') - parsed_version = f'{split_version[0].zfill(2)}_{split_version[1].zfill(2)}' - return f'//lyengine/releases/ver{parsed_version}/' - - -def find_ly_version_for_p4_cl(repo, p4_cl): - tag_ref = repo.tag('refs/tags/' + p4_cl) - branch_list = repo.git.branch('-r', '--contains', tag_ref.commit) - branch_list = branch_list.split() - - # We assume the latest branch in the list is always the correct version. - latest_branch = branch_list[0] - - # Return right-hand split of [remote]/[branch name]. - return latest_branch.split('/')[1] - - -def main(): - args = create_args() - validate_args(args) - - if args.clean: - print("Running clean. Deleting pre-existing local repo.") - if os.path.exists(args.localRepoDirectory): - shutil.rmtree(args.localRepoDirectory, onerror=handle_remove_readonly) - - previous_lumberyard_version = None - next_lumberyard_version = None - source_repo_name = get_repo_name(args.sourceRepoURL) - mix_repo = init_mix_repo(args.localRepoDirectory, args.awsProfile, source_repo_name, args.sourceRepoURL, args.destinationRepoURL) - remote_origin_refs = mix_repo.remote().refs - - ensure_tag_exists(mix_repo, args.commitRef, args.sourceRepoURL, args.destinationRepoURL) - - # Checkout the to-be-promoted commit - mix_repo.git.checkout(args.commitRef) - - # Import Lumberyard version data. - sys.path.append(os.path.join(mix_repo.working_dir, 'dev')) - import waf_branch_spec - next_lumberyard_version = waf_branch_spec.LUMBERYARD_VERSION - mirror_repo_branch_name = branch_name_from_version_string(next_lumberyard_version) - should_create_version_branch = False - empty_master_branch = False - - # We always delete the local repository, regardless of the '--clean' flag because reusing a git repo requires - # extensive sanitation to guarantee safe usage. It's easier to just clone a new one specifically for our purposes. - if os.path.exists(args.genRoot): - print(f"Path: {args.genRoot}\nFound pre-existing temp directory. Clearing contents before proceeding...") - shutil.rmtree(args.genRoot, onerror=handle_remove_readonly) - - # We want to move all files of the to-be-promoted commit in a separate directory. This leaves the working directory - # bare. - print ("Copying repo contents to temp directory.") - os.makedirs(args.genRoot) - exclude_git_dir = os.path.join(args.localRepoDirectory, ".git") - clean_replace_repo_contents(args.localRepoDirectory, args.genRoot, [exclude_git_dir]) - - # Checkout the corresponding (mirror repo) branch which our new commit will be based off of. - # We must determine if we branch off from a canonical version branch or from 'master'. - if hasattr(mix_repo.heads, mirror_repo_branch_name): - print(f"Checking out local branch '{mirror_repo_branch_name}'") - mix_repo.heads[mirror_repo_branch_name].checkout() - elif hasattr(remote_origin_refs, mirror_repo_branch_name): - print(f"Checking out remote branch '{mirror_repo_branch_name}'") - mix_repo.create_head(mirror_repo_branch_name, remote_origin_refs[mirror_repo_branch_name]) \ - .set_tracking_branch(remote_origin_refs[mirror_repo_branch_name]) \ - .checkout() - else: - print(f"'{mirror_repo_branch_name}' branch not found. Creating version branch after committing in 'master'.") - should_create_version_branch = True - - if hasattr(mix_repo.heads, 'master'): - print("Performing checkout on 'master'.") - mix_repo.heads.master.checkout() - else: - print("'master' does not exist locally.") - if hasattr(remote_origin_refs, 'master'): - print("'origin/master' found. Performing checkout from 'origin' remote.") - mix_repo.create_head('master', remote_origin_refs.master) \ - .set_tracking_branch(remote_origin_refs.master) \ - .checkout() - else: - print("'master' neither exist locally or remotely. Using default-empty 'master' branch.") - mix_repo.git.checkout("--orphan", "master") - mix_repo.git.reset(".") - mix_repo.git.clean("-df") - empty_master_branch = True - - # Before performing any new commits, we must set the stage for the incoming commit. That means we must generate a - # move-commit to track where the new Lumberyard version's files are destined to exist. - print ("Generating Move-Commit...") - mix_repo.git.reset('--hard') - - # Importing this file before v1.24 (python 2.7) will raise errors. This can be safely ignored. - try: - reload(waf_branch_spec) - except TypeError: - pass - - previous_lumberyard_version = waf_branch_spec.LUMBERYARD_VERSION - # Try to decode in case waf_branch_spec is still using the old format. - try: - previous_lumberyard_version = previous_lumberyard_version.decode('utf-8', 'ignore') - except (UnicodeDecodeError, AttributeError): - pass - - previous_CL = find_cl_for_ly_version_from_staging_repo(previous_lumberyard_version, mix_repo, source_repo_name) - previous_branch = format_p4_branch_from_ly_version(previous_lumberyard_version) - next_CL = ''.join(filter(str.isdigit, args.commitRef)) - next_branch = format_p4_branch_from_ly_version(find_ly_version_for_p4_cl(mix_repo, args.commitRef)) - - generate_move_commit(mix_repo, previous_branch, previous_CL, next_branch, next_CL) - - # Replace repo contents with the temp files we created early on. - exclude_git_dir = os.path.join(args.localRepoDirectory, ".git") - clean_replace_repo_contents(args.genRoot, args.localRepoDirectory, [exclude_git_dir]) - mix_repo.git.add("--all", "--force") - promoted_commit_object = mix_repo.commit(args.commitRef) - mix_repo.index.commit(promoted_commit_object.message, - author=promoted_commit_object.author, - committer=promoted_commit_object.committer) - - # Tag for customer release - print("Tagging new commit.") - version_tag_string = "v{0}".format(next_lumberyard_version) - mix_repo.create_tag(version_tag_string, force=True) - - # Rename staging repo tag, appending '-Promoted' - rename_tag(args.commitRef, args.commitRef + "-Promoted", - source_repo_name, mix_repo, args.dryRun) - - # Push commit & tags - if args.dryRun: - print("Performing dry run. No changes will be pushed to remotes.") - else: - print("Pushing tag & commit") - if empty_master_branch: - mix_repo.git.push("-u", "origin", "master") - else: - mix_repo.git.push("--all") - mix_repo.remote().push(version_tag_string) - - # Create version branch, if necessary - if should_create_version_branch: - print(f"Creating branch '{mirror_repo_branch_name}' off new master head.") - mix_repo.create_head(mirror_repo_branch_name) - if args.dryRun: - print("Performing dry run. No changes will be pushed to remotes.") - else: - mix_repo.git.push("-u", "origin", "{0}:{0}".format(mirror_repo_branch_name)) - - -if __name__ == "__main__": - main() - sys.exit() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitRelease.py b/Tools/build/JenkinsScripts/distribution/git_release/GitRelease.py deleted file mode 100755 index 999d67e8a2..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitRelease.py +++ /dev/null @@ -1,217 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# -import argparse -import boto3 -import sys -import shutil -import json -import os.path -import re -from subprocess import Popen, PIPE, check_output -from git import Repo - -THIS_SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, '..')) # Required for importing Git scripts -from GitStaging import handle_remove_readonly, abort_operation -from GitOpsCodeCommit import custom_clone -from GitIntegrityChecker import HASHLIST_KEY -from GitOpsGitHub import create_authenticated_https_clone_url, are_credentials_valid -from GitOpsCommon import get_revision_list - -def create_args(): - parser = argparse.ArgumentParser(description='Mirrors all content from the internal to external GitHubMirror.') - parser.add_argument('--sourceRepoURL', - help='The URL for the repository that we are mirroring to GitHub (expects a CodeCommit URL).', - required=True) - parser.add_argument('--destinationRepoURL', - help='The URL for the repository that we are mirroring on to (expects a GitHub URL).', - required=True) - parser.add_argument('--backupRepoURL', - help='The URL for the repository that we are backing up the mirrored content to (expects a CodeCommit URL).', - required=True) - parser.add_argument('--hashFile', - help='Hash file to update when release succeeds.', - required=True) - parser.add_argument('--genRoot', - help='Directory for temp files.', - required=True) - parser.add_argument('--githubUser', - help='Username for the Github account.', - required=True) - parser.add_argument('--githubPassword', - help='Password for the Github account.', - required=True) - parser.add_argument('--awsProfile', - help='AWS credentials profile generated from AWS CLI. Defaults to \'default\'.', - required=False, - default='default') - parser.add_argument('--keep', - help='Keeps all intermediary files after operation completes.', - action='store_true', - required=False) - parser.add_argument('--SkipP4Submit', - help='Skips the submission to P4 history.', - action='store_true', - required=False) - return parser.parse_args() - - -def validate_args(args): - # ensure that source and backup repos aren't github repos - github_domain = 'github.com' - if github_domain in args.sourceRepoURL.lower() or github_domain in args.backupRepoURL.lower(): - abort_operation('Cannot mirror from GitHub directly. Please use a git repo not on GitHub.') - - if github_domain in args.backupRepoURL.lower(): - abort_operation('Cannot backup repo to another GitHub repo. Please use a git repo not on GitHub.') - - # ensure that destination repo is a github repo - if github_domain not in args.destinationRepoURL.lower(): - abort_operation('Cannot release to any repo other than one hosted on GitHub. Please use a git repo on GitHub.') - - # ensure aws profile exists on the machine - if args.awsProfile: - if boto3.Session(profile_name=args.awsProfile) is None: - abort_operation('The AWS CLI profile name specified does not exist on this machine. Please specify an existing AWS CLI profile.') - - if not os.path.exists(args.hashFile): - abort_operation(f'Hash file not found: {args.hashFile}. If using perforce, please make sure that the file is mapped to your workspace, is checked out, and is at the lastest revision.') - - if not are_credentials_valid(args.githubUser, args.githubPassword): - abort_operation('Provided GitHub credentials are invalid. If you are using an account with Two-Factor Authentication enabled, your password should be replaced with the proper acces token.') - - -def mirror_repo_from_local(working_dir, dest_repo_url): - repo = Repo(working_dir) - - # Perform a mirroring operation by pushing all refs into the remote repo. - # This operation will delete stale refs and overwrite outdated ones on the remote repo. - print(f'Pushing to remote: {dest_repo_url}') - repo.git.push('--mirror', dest_repo_url) - - repo.close() - - -def mirror_repo_from_remote(working_dir, aws_profile, keep, source_repo_url, dest_repo_url): - # We begin by 'cloning' the git repo from the internal GitHub mirror at CodeCommit. Normally a git clone would - # elegantly set everything ready to mirror, but CodeCommit access is done via AWS CLI, meaning that the git repo - # needs a particular configuration in order to communicate with CodeCommit. Said configuration can be setup on the - # user's machine, but we inject the configuration directly into the repo initialization in order for the scripts to - # be portable across machines. - # A drawback with this method is that there are more manual steps to do (such as creating local branches for each - # branch remote) in order to correctly mirror the repo to the external GitHub site. - if os.path.exists(working_dir): - shutil.rmtree(working_dir, onerror=handle_remove_readonly) - os.makedirs(working_dir) - - # Clone the remote repo to mirror. - custom_clone(source_repo_url, aws_profile, working_dir, True) - - # Perform the actual mirrorring operation. - # Shortcut: - # Use alternate mirror function for code re-use. - mirror_repo_from_local(working_dir, dest_repo_url) - - if not keep: - print('Cleaning up temp files.') - shutil.rmtree(working_dir, onerror=handle_remove_readonly) - - -def get_last_commit_info(repo_directory): - initial_dir = os.getcwd() - os.chdir(repo_directory) - commit_info = check_output(['git', 'log', '-1', '--all', '--date-order', '--oneline', '--pretty=format:\'%H %s\'']) - os.chdir(initial_dir) - - # Sanitize string from stdout for Python usage - commit_info = re.sub('[\'\\\]', '', commit_info) - - commit_info_split = commit_info.split(' ', 1) - commit_hash = commit_info_split[0] - commit_title = commit_info_split[1] - print(f'Last commit info found from directory {repo_directory}:\nCommit hash: {commit_hash}\nCommit Title: {commit_title}') - return commit_hash, commit_title - - -def create_git_release_p4_changelist(changelist_description): - changelist_config = check_output(['p4', 'change', '-o']) - changelist_config = changelist_config.replace('', changelist_description, 1) - - p = Popen(['p4', 'change', '-i'], stdout=PIPE, stdin=PIPE, stderr=PIPE) - result_stdout = p.communicate(input=changelist_config)[0] - - # Successful result prints changelist number (example: 'Change 452982 created.\r\n') - changelist_number = result_stdout.split()[1] - return changelist_number - - -def p4_update_hashlist(commit_hashes_filepath, hash_list, changelist_number): - print(f'Checking out hashlist file for edit: {commit_hashes_filepath}') - print(check_output(['p4', 'edit', '-c', changelist_number, commit_hashes_filepath])) - - print('Loading hashlist from file.') - with open(commit_hashes_filepath) as json_data: - json_obj_hashes = json.load(json_data) - json_obj_hashes[HASHLIST_KEY] = hash_list - - # Replace the hashlist file with the new updated version - print('Writting new hash list to file') - os.remove(commit_hashes_filepath) - with open(commit_hashes_filepath, 'w') as f: - json.dump(json_obj_hashes, f, indent=4) - - -def submit_p4_changelist(changelist_number): - print(f'Submitting P4 CL{changelist_number}...') - print(check_output(['p4', 'submit', '-c', changelist_number])) - - -def main(): - args = create_args() - validate_args(args) - - https_authenticated_url = \ - create_authenticated_https_clone_url(args.githubUser, args.githubPassword, - args.destinationRepoURL) - - working_dir = os.path.join(args.genRoot, 'git_repo_release') - - # Mirror the repo to GitHub. - mirror_repo_from_remote(working_dir, args.awsProfile, True, - args.sourceRepoURL, - https_authenticated_url) - - # Reuse the cloned repo to mirror once more to our internal backup - mirror_repo_from_local(working_dir, args.backupRepoURL) - - # Do a rev-list to update the hashlist - hash_list = get_revision_list(working_dir) - - # Get the last git commit to parse the version number. We need this number to fill the description of the Perforce - # changelist used to update the hashlist. Ignore the 'commit_hash'. - commit_hash, commit_title = get_last_commit_info(working_dir) - - p4_cl_number = create_git_release_p4_changelist('GitHub ' + commit_title) - - p4_update_hashlist(args.hashFile, hash_list, p4_cl_number) - - if not args.SkipP4Submit: - submit_p4_changelist(p4_cl_number) - else: - print('Skipping P4 Submit.') - - if not args.keep: - # Delete the repo - shutil.rmtree(working_dir, onerror=handle_remove_readonly) - -if __name__ == '__main__': - main() - sys.exit() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/GitStaging.py b/Tools/build/JenkinsScripts/distribution/git_release/GitStaging.py deleted file mode 100755 index d04550b82a..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/GitStaging.py +++ /dev/null @@ -1,825 +0,0 @@ -############################################################################################ -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or -# a third party where indicated. -# -# 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. -############################################################################################# - -# Requires following installs via pip: -# - Boto3 -# Requires following software pre-installed: -# - Git -# - Python 3.7.6 x64 -# - Apache Ant -from distutils import spawn -from distutils.version import StrictVersion -from git import Repo, RemoteProgress -from urllib.parse import urljoin, urlparse -import argparse -import boto3 -import botocore.exceptions -import datetime -import errno -import GitOpsCodeCommit -import glob -import json -import locale -import os -import shutil -import stat -import subprocess -import sys -import textwrap -import time - -THIS_SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, "..")) # Required for AWS_PyTools -sys.path.append(os.path.join(THIS_SCRIPT_DIRECTORY, "..", "Installer")) # Required for BuildInstallerUtils -from AWS_PyTools import LyCloudfrontOps -from AWS_PyTools import LyChecksum -from Installer import SignTool - - -URL_KEY = "URL" -CHECKSUM_KEY = "Checksum" -SIZE_KEY = "Uncompressed Size" -BOOTSTRAP_CONFIG_FILENAME = "bootstrap_config.json" - -HASH_FILE_NAME = "filehashes.json" -class ExitCodes(object): - # Starting with higher numbers to avoid default system error collisions. - INVALID_ARGUMENT = 11 - UNSIGNED_PACKAGE = 12 - - -def print_status_message(message): - print("-----------------------------") - print(f"{message}") - print("-----------------------------\n") - - -def bytes_to_megabytes(size_in_bytes): - bytes_in_megabytes = 1048576 - return size_in_bytes / bytes_in_megabytes - - -def bytes_to_gigabytes(size_in_bytes): - megabytes_in_gigabytes = 1024 - return bytes_to_megabytes(size_in_bytes) / megabytes_in_gigabytes - - -def appendTrailingSlashToUrl(url): - if not url.endswith(tuple(['/', '\\'])): - url += '/' - return url - - -def get_empty_subdirectories(path): - empty_directories = [] - for dirpath, dirnames, filenames in os.walk(path): - for cur_dir in dirnames: - full_path = os.path.join(dirpath, cur_dir) - if not os.listdir(full_path): - empty_directories.append(full_path) - return empty_directories - - -def get_directory_size_in_bytes(start_path): - total_size = 0 - for dirpath, dirnames, filenames in os.walk(start_path): - for f in filenames: - fp = os.path.join(dirpath, f) - total_size += os.path.getsize(fp) - return total_size - - -# Python has issues removing files and directories on Windows -# (even if we've just created them) if they were set to 'readonly'. -# This usually occurs when deleting a '.git' directory, because some internal -# git repository files become 'readonly' when initializing a new repo. -# The following function should override general permission issues when -# deleting. -def handle_remove_readonly(func, path, exc): - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 - func(path) - - -# Ensures a specified directory is existent and empty. If clean is 'True', -# the directory will delete all contents within. The clean argument is -# intended to be used for retrying script operation from scratch. Use with -# care. -def ensure_directory_is_usable(directory, clean): - if os.path.exists(directory): - print(f"'{directory}' already exists.") - if clean is True: - print(f"Clean mode enabled. Deleting contents of '{directory}'") - dir_entries = os.listdir(directory) - for entry in dir_entries: - entry_full_path = os.path.join(directory, entry) - if os.path.isfile(entry_full_path): - os.chmod(entry_full_path, stat.S_IWRITE) - os.remove(entry_full_path) - elif os.path.isdir(entry_full_path): - shutil.rmtree(entry_full_path, - ignore_errors=False, - onerror=handle_remove_readonly) - if len(os.listdir(directory)) > 0: - print("Required directory for operation is not empty.") - print(f"Failed to delete contents of: {directory}") - sys.exit() - else: - print("Reusing contents of existing directory.") - else: - print(f"'{directory}' does not exist. Creating.") - os.makedirs(directory) - - -def parse_script_arguments(): - parser = argparse.ArgumentParser(description='Creates a git commit from a signed Lumberyard release.') - - parser.add_argument('--gitURL', - help="The url for the repo you would like to push to.", - default=None) - parser.add_argument('--gitBranch', - help="The branch which the commit will be made to.", - required=False, - default="master") - parser.add_argument('--packagePath', - help='Filepath to the signed Lumberyard package.', - required=True) - parser.add_argument('--cloudfrontURL', - help='Cloudfront base URL.', - required=False, - default=None) - parser.add_argument('--zipDescriptor', - help='Name of the zip file as appears on a commit message when describing the URL.', - required=True) - parser.add_argument('--binZipSuffix', - help='Suffix appended to the newly created binary zip name.', - required=True) - # is it safe to assume that the profile being used for S3 and CodeCommit are the same? - parser.add_argument('--awsProfile', - help='AWS credentials profile generated from AWS CLI. The codecommit repo and cloudfront distribution should both be able to be access by this profile. Defaults to "default".', - required=False, - default='default') - parser.add_argument('--uploadProfile', - help='AWS CLI profile to use to upload to cloudfront', - required=False, - default='default') - parser.add_argument('--genRoot', - help='Path to where the entire script operation will take place.', - required=True) - parser.add_argument('--binDownloader', - help='Path to the binary downloader which is stored in Perforce.', - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", "git_bootstrap.exe")) - parser.add_argument('--gitReadme', - help="The readme to be displayed on the Git repo page.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", "README.md")) - parser.add_argument('--gitGuidelines', - help="The contribution guidelines for customers submitting changes.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", "CONTRIBUTING.md")) - parser.add_argument('--gitIgnore', - help="The default '.gitignore' for the repo.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", ".gitignore")) - parser.add_argument('--gitBugTemplate', - help="The bug issue template.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", ".github", "ISSUE_TEMPLATE", "bug_report.md")) - parser.add_argument('--gitFeatureTemplate', - help="The feature issue template.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", ".github", "ISSUE_TEMPLATE", "feature_request.md")) - parser.add_argument('--gitQuestionTemplate', - help="The question issue template.", - required=False, - default=os.path.join(THIS_SCRIPT_DIRECTORY, "inject", ".github", "ISSUE_TEMPLATE", "question.md")) - parser.add_argument('--clean', - help='Clear out existing temp directories before executing this operation.', - required=False, - action="store_true") - parser.add_argument('--keep', - help='Skips the clean-up process at the end of the ' - 'operation, keeping temp files in the working directory.', - required=False, - action="store_true") - parser.add_argument('--performUpload', - help='Performs the upload of the Lumberyard build binaries zip. ' - 'If specified, artifacts are deleted upon successful upload.', - required=False, - action="store_true") - parser.add_argument('--performPush', - help='Performs the a Git push of the new repo changes created by this process.', - required=False, - action="store_true") - parser.add_argument('--allowUnsignedPackages', - help='Allows unsigned Lumberyard packages to be processed.', - required=False, - action="store_true") - parser.add_argument('--engineDefaultSettingsPath', - help="Path to 'default_settings.json' relative to the engine root.", - required=False, - default='dev/_WAF_/default_settings.json') - parser.add_argument('--zipOnly', - help='Only generate the zip. Do not actually do anything with a git repo.', - required=False, - action="store_true") - return parser.parse_args() - - -# Takes a repository directory and replaces it's contents with the contents of -# another directory, all while preserving the state of the repository. -# The incoming contents are MOVED, not copied. -def clean_replace_repo_contents(incoming_content_directory, repo_directory, excludes): - repo_dir_entries = os.listdir(repo_directory) - for entry in repo_dir_entries: - src_entry_full_path = os.path.join(repo_directory, entry) - if src_entry_full_path in excludes: - continue - if os.path.isfile(src_entry_full_path): - os.remove(src_entry_full_path) - elif os.path.isdir(src_entry_full_path): - print(f"Removing directory '{src_entry_full_path}'") - shutil.rmtree(src_entry_full_path, - ignore_errors=False, - onerror=handle_remove_readonly) - - # Add the incoming content to the repo directory - src_dir_entries = os.listdir(incoming_content_directory) - for entry in src_dir_entries: - src_entry_full_path = os.path.join(incoming_content_directory, entry) - dst_entry_full_path = os.path.join(repo_directory, entry) - if src_entry_full_path in excludes: - continue - shutil.move(src_entry_full_path, dst_entry_full_path) - - -# Checks whether a particular temp file should be generated/created. -# The 'filepath' argument does not necessarily correlate to the file-to-be-created. -# Example: Checking if FileA should be generated to decide how to process FileB. -def should_generate_resource(filepath, run_clean): - if run_clean: - should_create = True - print(f"'--clean' flag detected. Checking if '{filepath}' already exists.") - if os.path.exists(filepath): - print(f"'{filepath}' already exists. Removing.") - os.remove(filepath) - else: - print(f"'{filepath}' is not present.") - elif not os.path.exists(filepath): - should_create = True - print(f"'{filepath}' does not currently exist.") - else: - should_create = False - print(f"'{filepath}' already exists.") - return should_create - - -def abort_operation(reason, exit_code): - print(reason) - print("Aborting operation.") - sys.exit(exit_code) - - -### ZIP GENERATION FUNCTIONS - -# create a json file that contains key value pairs of relative path of a file going into the zip, to that file's hash -def generate_hashes_file(bin_directory): - directory_to_hash = os.path.join(bin_directory, "") - out_file_path = os.path.join(directory_to_hash, HASH_FILE_NAME) - if os.path.exists(out_file_path): - print(f"Hash list already exists. Reusing existing file:\n{out_file_path}") - else: - file_hashes = {} - for root, _, files in os.walk(directory_to_hash): - for filename in files: - file_to_hash = os.path.join(root, filename) - rel_file_path = os.path.relpath(file_to_hash, os.path.dirname(directory_to_hash)) - # make sure the key (file path) is relative, so that it doesn't matter - # where the customer has their repository. - # Opens file in universal mode to reduce unix vs pc line endings issues. - file_hashes[rel_file_path] = LyChecksum.getChecksumForSingleFile(file_to_hash).hexdigest() - with open(out_file_path, 'w') as out_file: - json.dump(file_hashes, out_file, sort_keys=True, indent=4, separators=(',', ': ')) - print(f"Hash list file output to {out_file_path}") - - -### GIT COMMIT FUNCTIONS - -def get_downloader_version(downloader_filepath): - p = subprocess.Popen([downloader_filepath, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, error = p.communicate() - if p.returncode != 0: - raise Exception(f"Downloader version command failed ({p.returncode:d}) {output} {error}") - version = output.strip() - return version - - -def get_ly_version(src_directory): - sys.path.append(os.path.join(src_directory, 'dev')) - import waf_branch_spec - return waf_branch_spec.LUMBERYARD_VERSION - - -def get_ly_build(src_directory): - sys.path.append(os.path.join(src_directory, 'dev')) - import waf_branch_spec - return waf_branch_spec.LUMBERYARD_BUILD - - -# creates a file with the given name at the root of the repo containing all of the -# additive binary info -def create_bootstrap_config(filename, path, url, checksum, size): - zip_info = { URL_KEY: url, CHECKSUM_KEY: checksum, SIZE_KEY: size } - out_file_path = os.path.join(path, filename) - with open(out_file_path, 'w') as out_file: - json.dump(zip_info, out_file, sort_keys=True, indent=4, separators=(',', ': ')) - - -# returns True if needed to create a new branch during this operation -def checkout_git_branch(repo, ly_version): - if hasattr(repo.heads, ly_version): - print(f'Performing checkout of local branch {ly_version}') - repo.git.checkout(ly_version) - elif hasattr(repo.remote("origin").refs, ly_version): - print(f'Performing checkout of remote branch {ly_version}') - remote_ref = repo.remote("origin").refs[ly_version] - repo.create_head(ly_version, remote_ref) \ - .set_tracking_branch(remote_ref) \ - .checkout() - else: - print(f"Branch '{ly_version}' was not found. Searching for closest relative.") - ly_version_split = ly_version.split('.') - - remote_heads = [] - for head in repo.remote('origin').refs: - origin_prefix = 'origin/' - ref_name = head.name[len(origin_prefix):] - product_major_version_pattern = f"{ly_version_split[0]}.{ly_version_split[1]}" - if ref_name.startswith(product_major_version_pattern): - remote_heads.append(ref_name) - - # Did we get any matches? - if len(remote_heads) > 0: - identified_parent_branch_name = remote_heads[len(remote_heads)-1] - repo.git.checkout(identified_parent_branch_name) - - # Magic Git voodoo code to show commits belonging to checked out branch, containing the word 'Promoted'. - promoted_commits_string = subprocess.check_output("git log" - " --decorate=full" - " --simplify-by-decoration" - " --pretty=oneline" - " HEAD" - " | sed -r -e \"s#^[^\(]*\(([^\)]*)\).*$#\\1#\" -e 's#,#\\n#g'" - " | grep 'tag:'" - " | sed -r -e 's#[[:space:]]*tag:[[:space:]]*##'" - " | grep 'Promoted'", shell=True) - promoted_commits_array = promoted_commits_string.splitlines() - - # Due to output order of subprocess command, the first element is the last promoted commit in this branch. - identified_promoted_commit_tag_name = promoted_commits_array[0] - print(subprocess.check_output(["git", "checkout", "-b", ly_version, identified_promoted_commit_tag_name])) - # We found no matches, we are adding a new version to master. - # No need to checkout master because every checkout for this logic branch has failed; we are already on master. - else: - return True - return False - - -def validate_downloader(args, clone_directory, binary_downloader_filename): - p4_downloader_filepath = args.binDownloader - git_downloader_filepath = os.path.join(clone_directory, binary_downloader_filename) - - if os.path.exists(git_downloader_filepath): - print("A binary downloader already exists in the Git repo.") - p4_downloader_version = StrictVersion(get_downloader_version(p4_downloader_filepath).decode()) - git_downloader_version = StrictVersion(get_downloader_version(git_downloader_filepath).decode()) - - if p4_downloader_version > git_downloader_version: - print(f"The binary downloader in Git is outdated: v{git_downloader_version}") - print(f"Updating to a newer version: v{p4_downloader_version}") - shutil.copy(p4_downloader_filepath, git_downloader_filepath) - # The downloader binary might be read-only, specially if taken directy from a Perforce-managed - # directory while not checked-out. This may cause permission issues, prompts, or errors on future - # scripts/automation without authority to modify read-only files. Setting the file to read/write. - os.chmod(git_downloader_filepath, stat.S_IWRITE) - elif p4_downloader_version == git_downloader_version: - print("No changes detected in the binary downloader.") - else: - raise Exception(f"The binary downloader in the Git repo is newer (v{git_downloader_version}) than the internal one(v{p4_downloader_version}).\n" - "Has the Git repo become compromised?") - else: - print("No binary downloader exists in the Git repository. Adding.") - shutil.copy(p4_downloader_filepath, git_downloader_filepath) - - -def checkout_git_repo (args): - print_status_message("Generating empty git repo...") - GitOpsCodeCommit.init_git_repo(args.gitURL, args.awsProfile, os.path.curdir) - repo = Repo(os.path.curdir) - - print_status_message("Fetching git repo from remote...") - repo.remote("origin").fetch() - - if not hasattr(repo.heads, args.gitBranch) and not hasattr(repo.remote().refs, args.gitBranch): - # We only reach here if gitBranch (presumably 'master', but can be anything) is missing from local & remote. - # This happens when staging to an empty repo. In such case, we create a local branch which will push at the end. - # Orphan checkout is only useful if gitBranch is other than 'master', otherwise, this call has no effect. - repo.git.checkout('--orphan', args.gitBranch) - else: - repo.git.checkout(args.gitBranch) - - return repo - - -def checkout_version_branch(src_directory, repo): - # We want to attach the Lumberyard version number to the commit message. - # Obtain version & build-number from the package contents via module import. - # To successfully import package contents, we must append to our Python 'sys' path. - ly_version = get_ly_version(src_directory) - print(f'Parsed Lumberyard version from source: {ly_version}') - - # Checkout whatever branch we should check this commit in to, or make one if there is not already an appropriate branch - creating_new_version_branch = checkout_git_branch(repo, ly_version) - - return ly_version, creating_new_version_branch - - -def stage_files_for_commit(args, clone_directory, src_directory, repo): - # Performing an accurate commit requires detecting modification, deletion, and addition to the repo files. - # In order to automatically detect this, we will leverage Git's ability to pick up on changes. To do this, we will - # delete all local files from the repo to then add the new source files. Git should know which files differ. - print_status_message("Collecting files for staging...") - binary_downloader_filename = os.path.basename(args.binDownloader) - excludes = [ - os.path.join(clone_directory, ".git"), - os.path.join(clone_directory, binary_downloader_filename) - ] - clean_replace_repo_contents(src_directory, clone_directory, excludes) - - # During the Git staging process, we may or may not include the binary downloader as part of the commit. - print_status_message("Validating binary downloader...") - validate_downloader(args, clone_directory, binary_downloader_filename) - - # Add all into Git staging to determine what the historical changes are. - # Force the add to bypass .gitignore rules. This ensures any unintended ignored files - # are mistakenly added to the repository instead of being lost/deleted during this staging proceedure. - print_status_message("Staging Git files...") - repo.git.add("--all", "--force") - - -def commit_to_local_repo(args, repo, ly_version, src_directory, bin_directory_size_in_bytes, creating_new_version_branch): - bin_directory_size_in_gigabytes = bytes_to_gigabytes(bin_directory_size_in_bytes) - - print_status_message("Generating Git commit...") - # Generate a commit message. This can be expanded with development - # highlights. The highlights could be fed in via python arguments in form - # of a URL to scrape, text file, or raw arguments. - git_commit_message_args = [ly_version, - args.zipDescriptor, - locale.format_string("%.2f", bin_directory_size_in_gigabytes, grouping=True), - bin_directory_size_in_bytes,] - git_commit_message = textwrap.dedent( - """Lumberyard Release {0} - - {1} Uncompressed Size: {2}GB ({3} bytes) - """.format(*git_commit_message_args)) - - print(f"Generating commit with the following message:\n{git_commit_message}") - repo.index.commit(git_commit_message) - - # For CI builds, we want to tag the commit with the Perforce change list (CL) number. - repo.create_tag('CL' + str(get_ly_build(src_directory))) - - if creating_new_version_branch: - repo.git.checkout('-b', ly_version) - # TODO: - # Need to figure out how to set upstream without pushing so that we may isolate all - # pushes to a single block of code in this file (for easier debugging and maintenance). - if args.performPush: - repo.git.push('-u', 'origin', ly_version) - - -def push_repo_to_remote(args, repo): - if args.performPush: - print_status_message("Pushing Git commit to remote...") - repo.git.push('--all') - repo.git.push('--tags') - - else: - print_status_message("'--performPush' flag not present. Skipping Git push procedure...") - - -def clean_up_repo_and_tempfiles(args, repo, abs_gen_root): - if not args.keep: - print_status_message("Cleaning up temp files...") - repo.close() - - # Give OS time to release any handles on files/paths (we see you, Windows) - time.sleep(0.1) - - # Although we created multiple directories, the files in genRoot are all - # temp files. We can safely delete the parent directory instead of each - # individually created directory/file. - shutil.rmtree(abs_gen_root, ignore_errors=False, onerror=handle_remove_readonly) - else: - print_status_message("'--keep' flag detected. Skipping cleanup procedure...") - - -# Tests for any invalid input. Any error results into application termination. -def validate_args(args): - # Test for cloudfront url secure protocol - if args.performUpload == True or args.zipOnly == False: - if args.cloudfrontURL == None: - abort_operation("Need to specify --cloudfrontURL if generating a commit or uploading the zip.") - if args.performUpload == True or args.cloudfrontURL is not None: - if not args.cloudfrontURL.startswith("https://"): - abort_operation("Incorrect cloudfront protocol. Ensure cloudfront URL starts with 'https://'", - ExitCodes.INVALID_ARGUMENT) - args.cloudfrontURL = appendTrailingSlashToUrl(args.cloudfrontURL) - - # Check to see if a default aws profile is available - try: - boto3.Session(profile_name=args.awsProfile) - except botocore.exceptions.ProfileNotFound: - abort_operation("AWS credentials files are missing. " - "Ensure AWS CLI is installed and configured with your IAM credentials.", - ExitCodes.INVALID_ARGUMENT) - - # Ensure Lumberyard package exists - ly_package_filepath = os.path.abspath(args.packagePath) - if os.path.exists(ly_package_filepath) is False: - abort_operation(f"'{ly_package_filepath}' does not exist.", - ExitCodes.INVALID_ARGUMENT) - if os.path.isfile(ly_package_filepath) is False: - abort_operation(f"'{ly_package_filepath}' is not a valid file. Did you specify a directoy or symlink?", - ExitCodes.INVALID_ARGUMENT) - - if args.performPush == True and args.zipOnly == True: - abort_operation("Cannot specify both 'zipOnly' and 'performPush'. Please specify just one.") - - if args.zipOnly == False: - # Verify Git is installed - if spawn.find_executable("git") is None: - abort_operation("Cannot find Git in your environment path. Ensure Git is installed on your machine.") - - if args.gitURL is None: - abort_operation('You must specify "--gitURL" with a valid URL to a git repo in order to perform any git operations with this script.') - - # Ensure repo URL does not point to a public GitHub repo - if "github.com" in args.gitURL.lower(): - abort_operation("Cannot stage to GitHub directly. Please use a git repo not on GitHub.") - - # Ensure bin downloader is a valid file - if os.path.exists(args.binDownloader) is False: - abort_operation(f"'--binDownloader' filepath does not exist:\n{args.binDownloader}") - - # Ensure readme is a valid file - if os.path.exists(args.gitReadme) is False: - abort_operation(f"'--gitReadme' filepath does not exist:\n{args.gitReadme}") - - # Ensure contributions is a valid file - if os.path.exists(args.gitGuidelines) is False: - abort_operation(f"'--gitGuidelines' filepath does not exist:\n{args.gitGuidelines}") - - # Ensure gitignore is a valid file - if os.path.exists(args.gitIgnore) is False: - abort_operation(f"'--gitIgnore' filepath does not exist:\n{args.gitIgnore}") - - # Ensure gitBugTemplate is a valid file - if os.path.exists(args.gitBugTemplate) is False: - abort_operation(f"'--gitBugTemplate' filepath does not exist:\n{args.gitBugTemplate}") - - # Ensure gitFeatureTemplate is a valid file - if os.path.exists(args.gitFeatureTemplate) is False: - abort_operation(f"'--gitFeatureTemplate' filepath does not exist:\n{args.gitFeatureTemplate}") - - # Ensure gitQuestionTemplate is a valid file - if os.path.exists(args.gitQuestionTemplate) is False: - abort_operation(f"'--gitQuestionTemplate' filepath does not exist:\n{args.gitQuestionTemplate}") - - -# Returns True if a Lumberyard package is signed. -def is_lumberyard_package_signed(unpacked_directory_root): - # List of binaries obtained from 'InstallerAutomation.py' - binaries_to_scan = [ - os.path.join(unpacked_directory_root, "dev", "Bin64vc141", "Editor.exe"), - os.path.join(unpacked_directory_root, "dev", "Bin64vc142", "Editor.exe") - ] - - for bin_filename in binaries_to_scan: - if SignTool.signtoolVerifySign(bin_filename, True) is False: - return False - return True - - -def main(): - args = parse_script_arguments() - validate_args(args) - - initial_cwd = os.getcwd() - locale.setlocale(locale.LC_NUMERIC, 'english') - - # Cache the absolute path of genRoot (aka, the workspace) - abs_gen_root = os.path.abspath(args.genRoot) - - # Where the package shall be entirely extracted to. - # Contents are 1:1 with zip. - bin_directory = os.path.join(abs_gen_root, "PackageExtract") - - # Where the source files will be once split (moved) from the extracted - # package directory. - src_directory = os.path.join(abs_gen_root, "Src") - - # Directory for the local git clone of the repository. - clone_directory = os.path.join(abs_gen_root, "Repo") - - # We want to split the package into source files and binary files. - # To begin this process, we must extract the contents from the zip. - print_status_message("Creating genRoot directories...") - ensure_directory_is_usable(clone_directory, args.clean) - ensure_directory_is_usable(src_directory, args.clean) - ensure_directory_is_usable(bin_directory, args.clean) - - package_zip_filepath = os.path.abspath(args.packagePath) - - if args.clean or not os.path.exists(bin_directory): - print_status_message(f"Extracting files from {package_zip_filepath}") - subprocess.call(["ant", - "ExtractPackage", - "-DZipfile=" + package_zip_filepath, - "-DExtractDir=" + bin_directory], - shell=True) - else: - print_status_message("Path already exists. Reusing contents") - - print_status_message("Verifying structure of package contents") - empty_directories = get_empty_subdirectories(bin_directory) - if len(empty_directories) > 0: - stringList = '\n'.join(empty_directories) - print(f"Package contains empty directories. Deleting:\n{stringList}") - for x in empty_directories: - shutil.rmtree(x) - else: - print("Structure is valid. No empty directories found.") - - if args.allowUnsignedPackages: - print_status_message("'--allowUnsignedPackages' flag detected. Skipping signature check.") - else: - print_status_message("Scanning for signed Lumberyard package") - if not is_lumberyard_package_signed(bin_directory): - abort_operation("The provided package is not signed. Retry with a signed package, or ensure " - "'--allowUnsignedPackages' flag is specified.", ExitCodes.UNSIGNED_PACKAGE) - elif not SignTool.signtoolVerifySign(args.binDownloader, True): - abort_operation("The provided package is signed, but the binary downloader is not. Sign the downloader, or " - "ensure '--allowUnsignedPackages' flag is specified.", ExitCodes.UNSIGNED_PACKAGE) - else: - print("Package is signed.") - - # We now meet the requirements for the next step: Splitting. - # For this, we invoke an ant script. - if args.clean: - print_status_message("Splitting source and binary files...") - subprocess.call(["ant", - "SplitZip", - "-DExtractBuild=" + bin_directory, - "-DGitSrc=" + src_directory], - shell=True) - - # The Github readme, guidelines and templates are stored separately so let's make sure they're included in the distribution. - github_readme_filename = os.path.basename(args.gitReadme) - shutil.copy(args.gitReadme, os.path.join(src_directory, github_readme_filename)) - - github_contributions_filename = os.path.basename(args.gitGuidelines) - shutil.copy(args.gitGuidelines, os.path.join(src_directory, github_contributions_filename)) - - github_gitignore_filename = os.path.basename(args.gitIgnore) - shutil.copy(args.gitIgnore, os.path.join(src_directory, github_gitignore_filename)) - - template_path = os.path.join(src_directory,".github/ISSUE_TEMPLATE") - if not os.path.exists(template_path): - os.makedirs(template_path) - - github_bug_filename = os.path.join(template_path, os.path.basename(args.gitBugTemplate)) - shutil.copy(args.gitBugTemplate, os.path.join(github_bug_filename)) - - github_feature_filename = os.path.join(template_path, os.path.basename(args.gitFeatureTemplate)) - shutil.copy(args.gitFeatureTemplate, os.path.join(github_feature_filename)) - - github_question_filename = os.path.join(template_path, os.path.basename(args.gitQuestionTemplate)) - shutil.copy(args.gitQuestionTemplate, os.path.join(github_question_filename)) - - # Generate the file containing the list of hashes of all of the content that will go into the zip - print_status_message("Generating file containing list of file hashes...") - generate_hashes_file(bin_directory) - - - # We have split our Source from Binaries. We can now identify the size of - # the binaries zip when uncompressed. We will need this for the commit message. - print_status_message("Measuring unpacked binaries size...") - bin_directory_size_in_bytes = get_directory_size_in_bytes(bin_directory) - bin_directory_size_in_megabytes = bytes_to_megabytes(bin_directory_size_in_bytes) - bin_directory_size_in_gigabytes = bytes_to_gigabytes(bin_directory_size_in_bytes) - - print(textwrap.dedent(f""" - Total size in Bytes: {locale.format_string("%d", bin_directory_size_in_bytes, grouping=True)} - Megabytes: {locale.format_string("%.4f", bin_directory_size_in_megabytes, grouping=True)} - Gigabytes: {locale.format_string("%.2f", bin_directory_size_in_gigabytes, grouping=True)} - """)) - - # Generate the expected filepath for the binaries zip. - if args.clean: - timestamp = time.time() - bin_zip_filename = os.path.basename(package_zip_filepath) - bin_zip_filepath = "{0}_{1}-{2}.zip".format( - os.path.join(abs_gen_root, os.path.splitext(bin_zip_filename)[0]), - datetime.datetime.fromtimestamp(timestamp).strftime('%m%d%y_%H%M%S'), - args.binZipSuffix) - else: - # Find the last generated binary zip. - glob_pattern = f"{abs_gen_root}\\*-{args.binZipSuffix}.zip" - glob_list_result = glob.glob(glob_pattern) - glob_list_length = len(glob_list_result) - if glob_list_length > 0: - bin_zip_filepath = glob_list_result[glob_list_length-1] - else: - raise Exception("No pre-existing binary zip to reuse. Run with '--clean' flag to generate new binary zip.") - - - # Let's zip up the Binaries for submitting to S3. - # We may be resuming from a previous run. We may not want to start over - # from scratch as this takes a while, thus, we check before processing... - if should_generate_resource(bin_zip_filepath, args.clean): - print_status_message(f"Zipping binary files into '{bin_zip_filepath}'") - subprocess.call(["ant", - "ZipBinaries", - "-DZipDest=" + bin_zip_filepath, - "-DZipSrc=" + bin_directory], - shell=True) - else: - print_status_message("Skipping binary files zipping operation.") - - # We generate a checksum for the zip file. The downloader will use this to - # ensure the contents have not been tampered with. - print_status_message("Generating bin zip checksum.") - bin_zip_file_checksum = LyChecksum.getChecksumForSingleFile(bin_zip_filepath) - - target_cloudfront_url = "N/A" - if args.performUpload: - print_status_message("Uploading to S3...") - target_bucket_path = LyCloudfrontOps.uploadFileToCloudfrontURL(bin_zip_filepath, - args.cloudfrontURL, - args.uploadProfile, - False) - # Bucket path and cloudfront url both contain the bucket folder name in their paths. - # We'll trim the the clourfront url to only be the cloudfront distribution link. - # We then append the path to generate a qualified url for download. - parsed_url = urlparse(args.cloudfrontURL) - target_bucket_url = '{url.scheme}://{url.netloc}/'.format(url=parsed_url) - target_cloudfront_url = urljoin(target_bucket_url, target_bucket_path) - print(f"Uploaded file to: {target_cloudfront_url}") - if not args.keep: - os.remove(bin_zip_filepath) - else: - print_status_message("'--performUpload' flag not present. Skipping S3 upload procedure...") - - # generate the JSON file that contains information on the git binary. Can - # only do that if we have the url to put into the file. - if args.cloudfrontURL: - create_bootstrap_config(BOOTSTRAP_CONFIG_FILENAME, - src_directory, - urljoin(args.cloudfrontURL,os.path.basename(bin_zip_filepath)), - bin_zip_file_checksum.hexdigest(), - bin_directory_size_in_bytes) - - if args.zipOnly == False: - # We may now begin the git phase. - # To perform all subsequent git operations, we should do them from the repo directory. - os.chdir(clone_directory) - - repo = checkout_git_repo(args) - ly_version, create_new_branch = checkout_version_branch(src_directory, repo) - stage_files_for_commit(args, clone_directory, src_directory, repo) - commit_to_local_repo(args, repo, ly_version, src_directory, bin_directory_size_in_bytes, create_new_branch) - push_repo_to_remote(args, repo) - - # Let's return to the original working directory. - os.chdir(initial_cwd) - clean_up_repo_and_tempfiles(args, repo, abs_gen_root) - - else: - print_status_message("'--zipOnly' flag present. Skipping Git commit generation...") - - print_status_message("Lumberyard to Git operation completed successfully.") - - -if __name__ == "__main__": - main() - sys.exit() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/build.xml b/Tools/build/JenkinsScripts/distribution/git_release/build.xml deleted file mode 100644 index 16d1e694f5..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/build.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap.py b/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap.py deleted file mode 100755 index 1025e8c5ea..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap.py +++ /dev/null @@ -1,1136 +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. -# - -import argparse -import datetime -import hashlib -import json -import math -import os -import Queue -import re -import shutil -import ssl -import subprocess -import sys -import threading -import time -import urllib2 -import urlparse -import zipfile -from collections import deque -from distutils import dir_util, file_util, spawn -from distutils.errors import DistutilsFileError - -importDir = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.join(importDir, "..")) # Required for AWS_PyTools -from AWS_PyTools import LyChecksum -from GitStaging import get_directory_size_in_bytes, URL_KEY, CHECKSUM_KEY, SIZE_KEY, BOOTSTRAP_CONFIG_FILENAME - -FETCH_CHUNK_SIZE = 1000000 -CHUNK_FILE_SIZE = 100000000 # 100 million bytes per chunk file -WORKING_DIR_NAME = "_temp" -DOWNLOAD_DIR_NAME = "d" -UNPACK_DIR_NAME = "u" - -DOWNLOADER_THREAD_COUNT = 20 - -# The downloader is intended to be an executable. Typically, executables should have their version bake into the binary. -# Windows has two variations of versions for a binary file: FileVersion, ProductVersion. Furthermore, we need to import -# Windows-specific apis to read Windows executable binary versions. Other operating systems have their own versioning scheme. -# To simplify maintenance, we will simply track the version in the source code itself. -DOWNLOADER_RELEASE_VERSION = "1.2" - -FILESIZE_UNIT_ONE_INCREMENT = 1024 -FILESIZE_UNIT_TWO_INCREMENT = FILESIZE_UNIT_ONE_INCREMENT * FILESIZE_UNIT_ONE_INCREMENT -FILESIZE_UNIT_THREE_INCREMENT = FILESIZE_UNIT_TWO_INCREMENT * FILESIZE_UNIT_ONE_INCREMENT - -HASH_FILE_NAME = "filehashes.json" -DEFAULT_HASH_FILE_URL = "https://d3dn1rjl3s1m7l.cloudfront.net/default-hash-file/" + HASH_FILE_NAME - -TRY_AGAIN_STRING = "Please try again or contact Lumberyard support if you continue to experience issues." - -#returns the size of the file moved -def safe_file_copy(src_basepath, dst_basepath, cur_file): - src_file_path = os.path.join(src_basepath, cur_file) - dst_file_path = os.path.join(dst_basepath, cur_file) - - dir_util.mkpath(os.path.dirname(dst_file_path)) - dst_name, copied = file_util.copy_file(src_file_path, dst_file_path, verbose=0) - - if copied is False: - raise Exception("Failed to copy {} to {}.".format(src_file_path, dst_file_path)) - - return os.path.getsize(dst_name) - - -def _get_input_replace_file(filename): - - def _print_invalid_input_given(response): - print 'Your response of "{0}" is not a valid response. Please enter one of the options mentioned.\n' - - valid_replace_responses = ['y', 'yes', 'yes all'] - valid_keep_responses = ['n', 'no', 'no all'] - - response_given = None - while not response_given: - print 'A new version of {0} has been downloaded, but a change to the local file has been detected.'.format(filename) - print 'Would you like to replace the file on disk with the new version? ({0})'.format("/".join(valid_replace_responses + valid_keep_responses)) - print 'Answering "n" will keep the local file with your modificaitions.' - print 'Ansering "yes all"/"no all" will assume this answer for all subsequent prompts.' - response = raw_input("Replace the file on disk with the new version? ({0}) ".format("/".join(valid_replace_responses + valid_keep_responses))) - print "" - normalized_input = None - try: - normalized_input = response.lower() - if normalized_input not in valid_replace_responses and \ - normalized_input not in valid_keep_responses: - _print_invalid_input_given(response) - else: - valid_respose = True - response_given = normalized_input - except Exception: - _print_invalid_input_given(response) - - # we know this is valid input. if it is not a replace response, then it must be a keep - return response_given in valid_replace_responses, 'a' in response_given - - -def find_files_to_prompt(args, changed_files, dst_basepath, old_file_hashes): - num_files_to_prompt = 0 - for key in changed_files: - # get path to file that is currently on disk - existing_file_path = os.path.join(dst_basepath, key) - if os.path.exists(existing_file_path): - # get the hash of the file on disk - file_hash = LyChecksum.getChecksumForSingleFile(existing_file_path, 'rU').hexdigest() - # if disk is same as old, replace - if file_hash == old_file_hashes[key]: - continue - # otherwise, ask if keep, replace - else: - # assume an answer - if not (args.yes or args.no): - num_files_to_prompt += 1 - - return num_files_to_prompt - - -def partition_moves_and_skips(args, changed_files, dst_basepath, old_file_hashes): - changed_files_to_move = set() - changed_files_to_skip = set() - - for key in changed_files: - should_move_file = False - # get path to file that is currently on disk - existing_file_path = os.path.join(dst_basepath, key) - if os.path.exists(existing_file_path): - # get the hash of the file on disk - file_hash = LyChecksum.getChecksumForSingleFile(existing_file_path, 'rU').hexdigest() - # if disk is same as old, replace - if file_hash == old_file_hashes[key]: - should_move_file = True - # otherwise, ask if keep, replace - else: - # assume the answer is to replace - if args.yes: - should_move_file = True - # assume the answer is to keep - elif args.no: - should_move_file = False - else: - should_move_file, use_as_assumption = _get_input_replace_file(existing_file_path) - if use_as_assumption and should_move_file: - args.yes = True - print "Marking all subsequent files as files to replace." - elif use_as_assumption and not should_move_file: - args.no = True - print "Marking all subsequent files as files to keep." - - # it was deleted on disk, so it should be safe to move over - else: - should_move_file = True - - if should_move_file: - changed_files_to_move.add(key) - else: - changed_files_to_skip.add(key) - - return changed_files_to_move, changed_files_to_skip - - -def load_hashlist_from_json(path): - file_path = os.path.join(path, HASH_FILE_NAME) - hash_list = {} - if not os.path.exists(file_path): - raise Exception("No hashfile exists at {0}.".format(file_path)) - with open(file_path, 'rU') as hashfile: - hash_list = json.load(hashfile) - return hash_list - - -def copy_directory_contents(args, src_basepath, dst_basepath, uncompressed_size): - # read in new hashlist - new_file_hashes = load_hashlist_from_json(src_basepath) - - # read in old hashlist. We check to make sure it is still on disk before we get here. - old_file_hashes = load_hashlist_from_json(dst_basepath) - - num_files_in_new = len(new_file_hashes.keys()) - print "There are {0} files in the new zip file.\n".format(num_files_in_new) - - old_file_hashes_keys = set(old_file_hashes.keys()) - new_file_hashes_keys = set(new_file_hashes.keys()) - - changed_files = old_file_hashes_keys & new_file_hashes_keys # '&' operator finds intersection between sets - deleted_files = set() - added_files = set() - missing_files = set() - identical_hashes = set() - changed_files_to_move = set() - changed_files_to_skip = set() - - identical_files_size_total = 0 - - # lets get rid of files that have the same hash, as we dont care about then - # skip if the same - for key in changed_files: - # if the file doesn't exist on disk, treat it as an add, regardless of whether the filelists have diff hashes - if not os.path.exists(os.path.join(dst_basepath, key)): - missing_files.add(key) - # if the file is on disk, and the hashes in the filelists are the same, there is no action to take, sorecord the progress - elif old_file_hashes[key] == new_file_hashes[key]: - identical_files_size_total += os.path.getsize(os.path.join(src_basepath, key)) - del old_file_hashes[key] - del new_file_hashes[key] - identical_hashes.add(key) - - # now that we cleared all of the identical hashes, if a file doesn't - # exist in the intersection, it is an add or delete, depending on - # the source hash list - deleted_files = old_file_hashes_keys.difference(changed_files) - added_files = missing_files.union(new_file_hashes_keys.difference(changed_files)) - - # cant remove from the set being iterated over, so get the difference between - # identical hashes and changed hashes and save it back to the changed set - changed_files = changed_files.difference(identical_hashes.union(missing_files)) - - total_keys = len(old_file_hashes_keys | new_file_hashes_keys) - keys_across_all_sets = len(changed_files | deleted_files | added_files | missing_files | identical_hashes) - if total_keys != keys_across_all_sets: - raise Exception("Not all keys caught in the resulting sets.") - - print "Finding files with conflicts." - # figure out how many files there are to prompt about - num_files_to_prompt = find_files_to_prompt(args, changed_files, dst_basepath, old_file_hashes) - print "There are {0} files with conflicts that need to be asked about.\n".format(num_files_to_prompt) - - # split the files into moves and skips, and ask customers about files with any conflicts - changed_files_to_move, changed_files_to_skip = partition_moves_and_skips(args, changed_files, dst_basepath, old_file_hashes) - - - # find the total size for all the skipped files - skipped_files_size_total = 0 - for key in changed_files_to_skip: - skipped_files_size_total += os.path.getsize(os.path.join(src_basepath, key)) - - move_progress_meter = ProgressMeter() - move_progress_meter.action_label = "Moving" - move_progress_meter.target = float(uncompressed_size) - move_progress_meter.report_eta = False - move_progress_meter.report_speed = False - move_progress_meter.start() - - # initialize the meter with the size of the files not being moved either due to being skipped, or being identical - move_progress_meter.record_progress(identical_files_size_total + skipped_files_size_total) - - # if in new but not old, keep - it was added - # also move files that were changed that should be moved - num_files_moved = 0 - for key in added_files.union(changed_files_to_move): - dest_file_size = safe_file_copy(src_basepath, dst_basepath, key) - move_progress_meter.record_progress(dest_file_size) - num_files_moved += 1 - - # if in old but not new, it was deleted. compare against disk - num_files_deleted = 0 - for key in deleted_files: - # get path to file that is currently on disk - existing_file_path = os.path.join(dst_basepath, key) - if os.path.exists(existing_file_path): - # get the hash of the file on disk - file_hash = LyChecksum.getChecksumForSingleFile(existing_file_path, 'rU').hexdigest() - # if disk is same as old, deleted, otherwise, we keep the file that is there. - # not tracked against the progress, as removes are not counted - # against the total (the uncompressed size of the zip) - if file_hash == old_file_hashes[key]: - os.remove(existing_file_path) - num_files_deleted += 1 - - # move new hashfile over - dest_file_size = safe_file_copy(src_basepath, dst_basepath, HASH_FILE_NAME) - move_progress_meter.record_progress(dest_file_size) - - move_progress_meter.stop() - - print "{0}/{1} new files were moved".format(num_files_moved, num_files_in_new) - print "{0}/{1} files were removed".format(num_files_deleted, len(deleted_files)) - -def get_default_hashlist(args, dst_basepath, working_dir_path): - # acquire default hashlist - default_hashlist_url = DEFAULT_HASH_FILE_URL - if args.overrideDefaultHashfileURL is not None: - default_hashlist_url = args.overrideDefaultHashfileURL - - with Downloader(DOWNLOADER_THREAD_COUNT) as downloader: - dest = os.path.join(working_dir_path, HASH_FILE_NAME) - print "Downloading files from url {0} to {1}"\ - .format(default_hashlist_url, dest) - try: - files = downloader.download_file(default_hashlist_url, dest, 0, True, True) - finally: - downloader.close() - if not files: - raise Exception("Failed to finish downloading {0} after a few retries." - .format(HASH_FILE_NAME)) - # now that we have the hashlist, move it to the root of the local repo - safe_file_copy(working_dir_path, dst_basepath, HASH_FILE_NAME) - os.remove(dest) - - -def is_url(potential_url): - return potential_url.startswith('https') - - -def create_ssl_context(): - ciphers_to_remove = ["RC4", "DES", "PSK", "MD5", "IDEA", "SRP", "DH", "DSS", "SEED", "3DES"] - cipher_string = ssl._DEFAULT_CIPHERS + ":" - for idx in range(len(ciphers_to_remove)): - # create the cipher string to permanently remove all of these ciphers, - # based on the format documented at - # https://www.openssl.org/docs/man1.0.2/apps/ciphers.html - cipher_string += "!{}".format(ciphers_to_remove[idx]) - if idx < len(ciphers_to_remove) - 1: - cipher_string += ":" # ":" is the delimiter - - ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) - ssl_context.set_ciphers(cipher_string) - - ssl_context.verify_mode = ssl.CERT_REQUIRED - # I can't find a way to load CRL - # ssl_context.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN - - return ssl_context - - -# -# Disk space -# -def get_free_disk_space(dir_name): - # Get the remaining space on the drive that the given directory is on - import platform - import ctypes - if platform.system() == 'Windows': - free_bytes = ctypes.c_ulonglong(0) - ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(dir_name), None, None, ctypes.pointer(free_bytes)) - return free_bytes.value - else: - st = os.statvfs(dir_name) - return st.f_bavail * st.f_frsize - - -# -# Checksum -# -def get_checksum_for_multi_file(multi_file): - block_size = 65536 - fileset_hash = hashlib.sha512() - buf = multi_file.read(block_size) - while len(buf) > 0: - fileset_hash.update(buf) - buf = multi_file.read(block_size) - return fileset_hash - - -def get_zip_info_from_json(zip_descriptor): - try: - url = zip_descriptor[URL_KEY] - - checksum = zip_descriptor[CHECKSUM_KEY] - if not LyChecksum.is_valid_hash_sha512(checksum): - raise Exception("The checksum found in the config file is not a valid SHA512 checksum.") - - size = zip_descriptor[SIZE_KEY] - if not size > 0: - raise Exception("The uncompressed size mentioned in the config file is " - "a value less than, or equal to zero.") - except KeyError as missingKey: - print "There is a key, value pair missing from the bootstrap configuration file." - print "Error: {0}".format(missingKey) - raise missingKey - except Exception: - raise - return url, checksum, size - - -def get_info_from_bootstrap_config(config_filepath): - zip_descriptor = {} - if not os.path.exists(config_filepath): - raise Exception("Could not find bootstrap config file at the root of the repository ({0}). " - "Please sync this file from the repository again." - .format(bootstrap_config_file)) - with open(config_filepath, 'rU') as config_file: - zip_descriptor = json.load(config_file) - try: - url, checksum, size = get_zip_info_from_json(zip_descriptor) - except Exception: - raise - - return url, checksum, size - - -# -# Args -# -def create_args(): - parser = argparse.ArgumentParser(description="Downloads required files relevant to the repositiry HEAD " - "to complete Lumberyard setup via Git.") - parser.add_argument('--rootDir', - default=os.path.dirname(os.path.abspath(__file__)), - help="The location of the root of the repository.") - parser.add_argument('--pathToGit', - default=spawn.find_executable("git"), - help="The location of the git executable. Git is assumed to be in your path if " - "this argument is not provided.") - parser.add_argument('-k', '--keep', - default=False, - action='store_true', - help='Keep downloaded files around after download finishes. (default False)') - parser.add_argument('-c', '--clean', - default=False, - action='store_true', - help='Remove any temp files before proceeding. (default False)') - parser.add_argument('-v', '--verbose', - default=False, - action='store_true', - help='Enables logging messages. (default False)') - parser.add_argument('--version', - default=False, - action='store_true', - help='Print application version') - parser.add_argument('-s', '--skipWarning', - default=False, - action='store_true', - help='Skip all warnings produced. (default False)') - # If specified, download the hashfile from the given location - parser.add_argument('--overrideDefaultHashfileURL', - default=None, - help=argparse.SUPPRESS) - group = parser.add_mutually_exclusive_group() - group.add_argument('-y', "--yes", - default=False, - action='store_true', - help='Will automatically answer "yes" to all files being asked to be overwritten. Only specify one of either --yes or --no. (default False)') - group.add_argument('-n', "--no", - default=False, - action='store_true', - help='Will automatically answer "no" to all files being asked to be overwritten. Only specify one of either --yes or --no. (default False)') - - args, unknown = parser.parse_known_args() - return args - - -def validate_args(args): - if args.version: - print DOWNLOADER_RELEASE_VERSION - sys.exit(0) - - assert (os.path.exists(args.rootDir)), "The root directory specified (%r) does not exist." % args.rootDir - - # check to make sure git exists either from the path or user specified location - if args.pathToGit is None: - raise Exception("Cannot find Git in your environment path. This scripts requires Git to be installed.") - else: - if os.path.isfile(args.pathToGit) is False: - raise Exception("The path to Git provided does not exists.") - - -class ProgressMeter: - def __init__(self): - self.event = None - self.worker = None - - self.lock = threading.Lock() - self.startTime = 0 - self.rateSamples = deque() - - self.action_label = "" - self.target = 0 - self.progress = 0 - - self.report_eta = True - self.report_speed = True - self.report_target = True - - self.report_bar = True - self.report_bar_width = 10 - - self.prev_line_length = 0 - - self.spinner_frames = ["|", "/", "-", "\\"] - self.curr_spinner_frame = 0 - - @staticmethod - def meter_worker(meter, event): - while not event.is_set(): - try: - meter.report_progress() - time.sleep(0.25) - except Exception: - pass - - def add_target(self, i): - self.lock.acquire() - try: - self.target += i - finally: - self.lock.release() - - def record_progress(self, i): - self.lock.acquire() - try: - self.progress += i - finally: - self.lock.release() - - def reset(self): - self.startTime = 0 - self.rateSamples = deque() - - self.action_label = "" - self.target = 0 - self.progress = 0 - - self.report_eta = True - self.report_speed = True - self.report_target = True - - self.report_bar = True - self.report_bar_width = 10 - - self.prev_line_length = 0 - self.curr_spinner_frame = 0 - - def start(self): - self.event = threading.Event() - self.worker = threading.Thread(target=self.meter_worker, args=(self, self.event)) - self.worker.setDaemon(True) - self.worker.start() - self.startTime = time.clock() - - # Set up so we can work with with statement, and auto destruct - def __enter__(self): - self.start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - # Make sure the thread stops - self.stop() - - def __del__(self): - if self.event: - self.event.set() - - def stop(self): - self.report_progress() # Final progress report, to show completion - self.event.set() - print "" # Set a new line from all other print operations - - def build_report_str(self, percent_complete, rate, eta): - # Build output report string - output_str = "{}".format(self.action_label) - - if self.report_target is True: - output_str += " {:4.2f} GB".format(float(self.target) / FILESIZE_UNIT_THREE_INCREMENT) - - if self.report_speed is True: - output_str += " @ {:5.2f} MB/s".format(rate / FILESIZE_UNIT_TWO_INCREMENT) - - if self.report_bar is True: - percent_per_width = 100.0 / self.report_bar_width - current_bar_width = percent_complete * 100.0 / percent_per_width - current_bar_width = int(math.floor(current_bar_width)) - remaining_width = self.report_bar_width - current_bar_width - - curr_spinner_icon = "" - if remaining_width is not 0: - curr_spinner_icon = self.spinner_frames[self.curr_spinner_frame] - - output_str += " [" + ("=" * current_bar_width) + curr_spinner_icon + (" " * (remaining_width - 1)) + "]" - - output_str += " {:.0%} complete.".format(percent_complete) - - if self.report_eta is True: - output_str += " ETA {}.".format(str(datetime.timedelta(seconds=eta))) - - return output_str - - def report_progress(self): - self.lock.acquire() - try: - if self.target == 0: - percent_complete = 1.0 - else: - percent_complete = self.progress * 1.0 / self.target - - self.rateSamples.append([self.progress, time.clock()]) - # We only keep 40 samples, about 10 seconds worth - if len(self.rateSamples) > 40: - self.rateSamples.popleft() - if len(self.rateSamples) < 2: - rate = 0.0 - else: - # Calculate rate from oldest sample and newest sample. - span = float(self.rateSamples[-1][0] - self.rateSamples[0][0]) - duration = self.rateSamples[-1][1] - self.rateSamples[0][1] - rate = span / duration - - if percent_complete == 1.0: - eta = 0 - elif rate == 0.0: - eta = 100000 - else: - eta = int((self.target - self.progress) / rate) - - self.curr_spinner_frame = (self.curr_spinner_frame + 1) % len(self.spinner_frames) - output_str = self.build_report_str(percent_complete, rate, eta) - - # Calculate the delta of prev and curr line length to clear - curr_line_length = len(output_str) - line_len_delta = max(self.prev_line_length - curr_line_length, 0) - - # Extra spaces added to the end of the string to clear the unused buffer of previous write - sys.stdout.write("\r" + output_str + " " * line_len_delta) # \r placed at the beginning to play nice with PyCharm. - sys.stdout.flush() - self.prev_line_length = curr_line_length - - except Exception as e: - print "Exception: ", e - sys.stdout.flush() - finally: - self.lock.release() - - -class Downloader: - meter = ProgressMeter() - download_queue = Queue.Queue() - max_worker_threads = 1 - max_retries = 3 - timeout = 5 # in seconds. - event = None - - def __init__(self, max_threads=1, max_retries=3): - self.max_worker_threads = max_threads - self.retries = max_retries - self.event = threading.Event() - - # preallocate the worker threads. - for i in range(self.max_worker_threads): - worker = threading.Thread(target=self.download_chunk_file, args=(self.download_queue, self.event)) - worker.daemon = True - worker.start() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - # Make sure the threads stop - self.event.set() - - def __del__(self): - self.event.set() - - def close(self): - self.event.set() - - def download_chunk(self): - pass - - def download_chunk_segments(self, start, end, file_path, url, exit_event): - # Set up so that we can resume a download that was interrupted - try: - existing_size = os.path.getsize(file_path) - except os.error as e: - "Exception: {}".format(e) - existing_size = 0 - - # offset by the size of the already downloaded file so we can resume - start = start + existing_size - - # if the existing size of the file matches the expected size, then we already have the file, so skip it. - if existing_size is not min((end - start)+1, CHUNK_FILE_SIZE): - segments = int(math.ceil(float((end-start)+1)/float(FETCH_CHUNK_SIZE))) - - with open(file_path, 'ab') as chunk_file: - for segment in range(segments): - # check for the exit event - if exit_event.is_set(): - break - - segment_start = start + (segment * FETCH_CHUNK_SIZE) - segment_end = min(end, (segment_start + FETCH_CHUNK_SIZE) - 1) - byte_range = '{}-{}'.format(segment_start, segment_end) - chunk_content_read_size = 10000 - try: - request_result = urllib2.urlopen( - urllib2.Request(url, headers={'Range': 'bytes=%s' % byte_range}), timeout=self.timeout) - # Result codes 206 and 200 are both considered successes - if not (request_result.getcode() == 206 or request_result.getcode() == 200): - raise Exception("URL Request did not succeed. Error code: {}" - .format(request_result.getcode())) - while True: - data = request_result.read(chunk_content_read_size) - if exit_event.is_set() or not data: - break - self.meter.record_progress(len(data)) - chunk_file.write(data) - chunk_file.flush() - except Exception: - raise - - # Helper thread worker for Downloader class - def download_chunk_file(self, queue, exit_event): - while not exit_event.is_set(): - try: - job = queue.get(timeout=1) - try: - start = job['start'] - end = job['end'] - file_path = job['file'] - url = job['url'] - for i in range(self.max_retries): - if exit_event.is_set(): - break - try: - self.download_chunk_segments(start, end, file_path, url, exit_event) - except Exception: - # if the try throws, we retry, so ignore - pass - else: - break - else: - raise Exception("GET Request for {} failed after retries. Site down or network disconnected?" - .format(file_path)) - finally: - queue.task_done() - except Exception: - # No jobs in the queue. Don't error, but don't block on it. Otherwise, - # the daemon thread cant quit when the event was set - pass - - def simple_download(self, url, dest): - self.meter.reset() - self.meter.action_label = "Downloading" - self.meter.start() - request_result = urllib2.urlopen(urllib2.Request(url), timeout=self.timeout) - if request_result.getcode() != 200: - raise ValueError('HEAD Request failed.', request_result.getcode()) - with open(dest, 'wb') as download_file: - data = request_result.read() - if data: - self.meter.record_progress(len(data)) - download_file.write(data) - download_file.flush() - self.meter.stop() - self.meter.reset() - - def download_file(self, url, dest, expected_uncompressed_size, force_simple=False, suppress_suffix=False): - start_time = time.clock() - - # ssl tests - ssl_context = create_ssl_context() - for i in range(self.max_retries): - try: - request_result = urllib2.urlopen(urllib2.Request(url), timeout=10, context=ssl_context) - # should not hard code this... pass this to an error handling function to figure out what to do - if request_result.getcode() != 200: - raise ValueError('HEAD Request failed.', request_result.getcode()) - - except ssl.SSLError as ssl_error: - raise Exception("SSL ERROR: Type: {0}, Library: {1}, Reason: {2}." - .format(type(ssl_error), ssl_error.library, ssl_error.reason)) - - except ssl.CertificateError: - raise - - except urllib2.HTTPError: - raise - - except urllib2.URLError as e: - if isinstance(e.reason, ssl.SSLError): - # raise the SSLError exception we encountered and stop downloading - raise e.reason - pass # we'll ignore the other URLErrors for now, it'll be caught in the else statement below - - except Exception as e: - import traceback - print "Generic exception caught: " + traceback.format_exc() - print str(e) - pass # we'll ignore the error now. Might want to put this into a "most recent error" var for later - - else: - break # we got the result, so no need to loop further""" - - else: - # we went through the loop without getting a result. figure out what the errors were and report it upwards - raise Exception('HEAD Request failed after retries. Site down or network disconnected?') - - file_size = int(request_result.headers.getheader('content-length')) - # check disk to see if there is enough space for the compressed file and the uncompressed file - remaining_disk_space = get_free_disk_space(os.path.dirname(dest)) - operation_required_size = file_size + expected_uncompressed_size - if operation_required_size > remaining_disk_space: - raise Exception("There is not enough space on disk ({}) to perform the operation. " - "Please make sure that {}GB of free space is available then try again." - .format(dest, operation_required_size - / FILESIZE_UNIT_THREE_INCREMENT)) - - # We may be re-running the script from a previous attempt where we have already partially downloaded some files. - # Calculate the actual amount to be downloaded. - dest_directory = os.path.dirname(os.path.abspath(dest)) - dest_byte_size = get_directory_size_in_bytes(os.path.abspath(dest_directory)) - self.meter.add_target(file_size) - self.meter.record_progress(dest_byte_size) - - ranges_available = request_result.headers.getheader('accept-ranges') - if ranges_available != 'bytes' or force_simple is True: - # download without using ranges - download_dest = dest - if not suppress_suffix: - download_dest += ".000" - self.simple_download(url, download_dest) - return download_dest - else: - # We have byte ranges, so we can download in chunks in - # parallel. We download into multiple files, which we - # will recombine with the file inputs function to pass - # into the unzip function later. - # This allows a clean resume with parallel gets from - # different parts of the overall range. - - chunk_files = int(math.ceil(float(file_size) / float(CHUNK_FILE_SIZE))) - # break into a collection of files - file_list = ["{}.{:04d}".format(dest, x) for x in range(chunk_files)] - files = [{'start': x * CHUNK_FILE_SIZE, - 'end': min(((x+1) * CHUNK_FILE_SIZE) - 1, file_size - 1), - 'file': "{}.{:04d}".format(dest, x), - 'url': url} for x in range(chunk_files)] - - for entry in files: - self.download_queue.put(entry) - - self.meter.action_label = "Downloading" - self.meter.start() - - while self.download_queue.unfinished_tasks: - time.sleep(0.1) - - # double check all tasks are completed - self.download_queue.join() - - self.meter.stop() - - if self.meter.progress < self.meter.target: - print_str = "Download failed. Check network and retry. Elapsed time {}"\ - .format(str(datetime.timedelta(seconds=time.clock() - start_time))) - return_list = [] - else: - print_str = "Finished. Elapsed time {}"\ - .format(str(datetime.timedelta(seconds=time.clock()-start_time))) - return_list = file_list - - print print_str - sys.stdout.flush() - return return_list - - -# Class to treat a collection of chunk files as a single larger file. -# We use this to unzip the chunk files as a single file. -# This is a minimal implementation, as required by the zipFile handle. -# This essentially supports only seeking and reading. -# Minimal error processing is present here. Probably needs some more -# to deal with ill formed input files. Right now we just assume -# errors thrown by the underlying system will be the right ones. -class MultiFile: - fileList = [] - fileSizes = [] - fileOffsets = [] - fileSize = 0 - current_file = 0 - - def __init__(self, files, mode): - self.fileList = files - self.mode = mode - for f in files: - self.fileSizes.append(os.path.getsize(f)) - self.fileOffsets.append(self.fileSize) - self.fileSize += self.fileSizes[-1] - try: - self.cfp = open(self.fileList[0], self.mode) - except Exception: - raise - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - pass - - def seek(self, offset, w=0): - cursor = self.tell() - if w == os.SEEK_SET: - cursor = offset - elif w == os.SEEK_CUR: - cursor += offset - elif w == 2: - cursor = self.fileSize + offset - - # Determine which file we are in now, and do the local seek - current_pos = cursor - local_curr_file = 0 - for i in range(len(self.fileSizes) - 1): - if current_pos < self.fileSizes[i]: - local_curr_file = i - break - current_pos -= self.fileSizes[i] - else: - local_curr_file = len(self.fileSizes) - 1 - - if self.current_file != local_curr_file: - self.current_file = local_curr_file - self.cfp.close() - self.cfp = open(self.fileList[self.current_file], self.mode) - self.cfp.seek(current_pos, 0) - - def close(self): - self.cfp.close() - - def tell(self): - cpos = self.cfp.tell() - cursor = self.fileOffsets[self.current_file] + cpos - return cursor - - def read(self, size=None): - if size is None: - size = self.fileSize - self.tell() - block = self.cfp.read(size) - remaining = size-len(block) - # Keep reading if there is size to read remaining, and we are - # not yet already reading the last file (and may have gotten EOF) - while remaining > 0 and self.current_file < len(self.fileList)-1: - # Switch to next file - self.cfp.close() - self.current_file += 1 - self.cfp = open(self.fileList[self.current_file], self.mode) - nblock = self.cfp.read(remaining) - block += nblock - remaining -= len(nblock) - return block - - -def main(): - try: - args = create_args() - validate_args(args) - abs_root_dir = os.path.abspath(args.rootDir) - remove_downloaded_files = False - script_succeed = False - - if args.skipWarning is False: - print "Now completing your Lumberyard setup." - print "This downloads essential content not included in the Git repository." - print "If you've made any changes, please back them up before running this." - print "Press Enter to continue (Ctrl+C to cancel at anytime)..." - sys.stdout.flush() - - # blocks until user presses the Enter key - raw_input() - - # As of 1.8, the longest file path relative to root of the zip is 151, - # giving 104 chars before the windows path limit. Set the max working dir - # length to 60 to have some wiggle room. - max_working_dir_len = 60 - # working dir should be rootDir/working_dir_name. if that is too long, try - # using %TEMP%/working_dir_name - working_dir_path = os.path.join(abs_root_dir, WORKING_DIR_NAME) - if len(working_dir_path) > max_working_dir_len: - # switch to using default temp dir - working_dir_path = os.path.join(os.path.expandvars("%TEMP%"), WORKING_DIR_NAME) - unpack_dir_path = os.path.join(working_dir_path, UNPACK_DIR_NAME) - - # Remove any pre-downloaded files, if necessary. - if args.clean and os.path.exists(working_dir_path): - shutil.rmtree(working_dir_path) - - if not os.path.exists(working_dir_path): - os.makedirs(working_dir_path) - - # check for old hashlist - old_hash_file_path = os.path.join(abs_root_dir, HASH_FILE_NAME) - if not os.path.exists(old_hash_file_path): - get_default_hashlist(args, abs_root_dir, working_dir_path) - - try: - try: - bootstrap_config_file = os.path.join(abs_root_dir, BOOTSTRAP_CONFIG_FILENAME) - download_url, expected_checksum, uncompressed_size = get_info_from_bootstrap_config(bootstrap_config_file) - download_file_name = os.path.basename(urlparse.urlparse(download_url)[2]) - except Exception: - raise - - # check remaining disk space of destination against the uncompressed size - remaining_disk_space = get_free_disk_space(abs_root_dir) - if not uncompressed_size < remaining_disk_space: - raise Exception("There is not enough space on disk ({}) for the extra files. " - "Please make sure that {}GB of free space is available then try again." - .format(abs_root_dir, uncompressed_size / FILESIZE_UNIT_THREE_INCREMENT)) - - # now check against the disk where we are doing the work - remaining_disk_space = get_free_disk_space(working_dir_path) - if not uncompressed_size < remaining_disk_space: - raise Exception("There is not enough space on disk ({}) to perform the operation. " - "Please make sure that {}GB of free space is available then try again." - .format(working_dir_path, uncompressed_size / FILESIZE_UNIT_THREE_INCREMENT)) - - # download the file, with 20 threads! - try: - with Downloader(DOWNLOADER_THREAD_COUNT) as downloader: - download_dir_path = os.path.join(working_dir_path, DOWNLOAD_DIR_NAME) - if not os.path.exists(download_dir_path): - os.mkdir(download_dir_path) - dest = os.path.join(download_dir_path, download_file_name) - - print "Downloading files from url {0} to {1}"\ - .format(download_url, dest) - files = downloader.download_file(download_url, dest, uncompressed_size) - except Exception: - downloader.close() - raise - - # if the download failed... - if not files: - raise Exception("Failed to finish downloading {0} after a few retries." - .format(download_file_name)) - - # make the downloaded parts a single file - multi_file_zip = MultiFile(files, 'rb') - - # check downloaded file against checksum - print "Checking downloaded contents' checksum." - downloaded_file_checksum = get_checksum_for_multi_file(multi_file_zip) - readable_checksum = downloaded_file_checksum.hexdigest() - if readable_checksum != expected_checksum: - remove_downloaded_files = True - raise Exception("The checksum of the downloaded file does not match the expected checksum. ") - - # check if unpack directory exists. clear it if it does. - delete_existing_attempts = 0 - delete_success = False - delete_attempts_max = 3 - if os.path.exists(unpack_dir_path): - while not delete_success and delete_existing_attempts < delete_attempts_max: - try: - shutil.rmtree(unpack_dir_path) - except (shutil.Error, WindowsError, DistutilsFileError) as removeError: - delete_existing_attempts += 1 - if delete_existing_attempts >= delete_attempts_max: - raise removeError - print ("{0}: {1}").format(type(removeError).__name__, removeError) - print ("Failed to remove files that already existed at {} before unpacking. Please ensure the files" - " are deletable by closing related applications (such as Asset Processor, " - "and the Lumberyard Editor), then try running this program again.").format(unpack_dir_path) - raw_input("Press ENTER to retry...") - except Exception: - raise - else: - delete_success = True - os.mkdir(unpack_dir_path) - - # unpack file to temp directory. - zip_file = zipfile.ZipFile(multi_file_zip, allowZip64=True) - try: - print "Extracting all files from {0} to {1}".format(download_file_name, unpack_dir_path) - - extract_progress_meter = ProgressMeter() - extract_progress_meter.action_label = "Extracting" - extract_progress_meter.target = float(uncompressed_size) - extract_progress_meter.report_eta = False - extract_progress_meter.report_speed = False - - extract_progress_meter.start() - - zip_file_info = zip_file.infolist() - - for file_path in zip_file_info: - zip_file.extract(file_path, path=unpack_dir_path) - extract_progress_meter.record_progress(file_path.file_size) - - extract_progress_meter.stop() - - except Exception: - raise Exception("Failed to extract files from {0}. ".format(files)) - finally: - zip_file.close() - multi_file_zip.close() - - num_unpacked_files = 0 - for root, dirs, files in os.walk(unpack_dir_path): - num_unpacked_files += len(files) - - # move temp to - print "Moving zip contents to final location." - copy_directory_contents(args, unpack_dir_path, abs_root_dir, uncompressed_size) - - except (shutil.Error, WindowsError, DistutilsFileError) as removeError: - print ("{0}: {1}").format(type(removeError).__name__, removeError) - print ("Failed to remove files that already existed at {} before unpacking. Please ensure the files are" - " deletable by closing related applications (such as Asset Processor, and the Lumberyard" - " Editor), then try running this program again.").format(abs_root_dir) - script_succeed = False - - except Exception as e: - print ("Failed to finish acquiring needed files: {} " + TRY_AGAIN_STRING).format(e) - script_succeed = False - - else: - remove_downloaded_files = True - script_succeed = True - - finally: - # clean up temp dir - if not args.keep: - - if remove_downloaded_files and os.path.exists(working_dir_path): - # printing a line new to have a separation from the other logs - print ("\nCleaning up temp files") - shutil.rmtree(working_dir_path) - elif os.path.exists(unpack_dir_path): - # printing a line new to have a separation from the other logs - print ("\nCleaning up temp files") - shutil.rmtree(unpack_dir_path) - - except KeyboardInterrupt: - print ("\nOperation aborted. Please perform manual cleanup, or re-run git_bootstrap.exe.\n\n") - sys.stdout.flush() - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap_test.py b/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap_test.py deleted file mode 100755 index e566b44a4e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/git_bootstrap_test.py +++ /dev/null @@ -1,208 +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. -# - -import bin_download -import contextlib -import io -import os -import shutil -import ssl -import sys -import unittest - - -@contextlib.contextmanager -def no_stdout(): - save_stdout = sys.stdout - sys.stdout = io.BytesIO() - - try: - yield - finally: - sys.stdout = save_stdout - - -class BadSslTestCase(unittest.TestCase): - def setUp(self): - self.working_dir_path = os.path.join(os.path.expandvars("%TEMP%"), "_temp") - self.download_file_name = "test_download.test" - self.destination = os.path.join(self.working_dir_path, self.download_file_name) - self.uncompressed_size = 1000000 - - if not os.path.exists(self.destination): - os.makedirs(self.destination) - - def tearDown(self): - if os.path.exists(self.destination): - shutil.rmtree(self.destination) - - def download_file(self, download_url): - try: - with bin_download.Downloader(20) as downloader: - with no_stdout(): - downloader.download_file(download_url, self.destination, self.uncompressed_size) - - except ssl.SSLError: - raise - - except ssl.CertificateError: - raise - - except Exception: - print "\tFATAL ERROR: Unhandled exception encountered." - raise - - return True - - def test_cloudfront_download(self): - self.assertTrue(self.download_file("https://s3-us-west-2.amazonaws.com/lumberyard-download-artifacts-bucket/" - "3rdParty/squish-ccr/20150601_lmbr_v1/filelist.1.0.0.common.json")) - - def test_expired(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://expired.badssl.com/") - - def test_wrong_host(self): - self.assertRaises(ssl.CertificateError, self.download_file, "https://wrong.host.badssl.com/") - - def test_self_signed(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://self-signed.badssl.com/") - - def test_untrusted_root(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://untrusted-root.badssl.com/") - - def test_incomplete_chain(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://incomplete-chain.badssl.com/") - - def test_sha256(self): - self.assertTrue(self.download_file("https://sha256.badssl.com/")) - - def test_1000_sans(self): - self.assertTrue(self.download_file("https://1000-sans.badssl.com/")) - - def test_ecc256(self): - self.assertTrue(self.download_file("https://ecc256.badssl.com/")) - - def test_ecc384(self): - self.assertTrue(self.download_file("https://ecc384.badssl.com/")) - - def test_cbc(self): - # cbc is supposed to be secure in TLS1_1 and TLS1_2 - self.assertTrue(self.download_file("https://cbc.badssl.com/")) - - def test_rc4_md5(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://rc4-md5.badssl.com/") - - def test_rc4(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://rc4.badssl.com/") - - def test_3des(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://3des.badssl.com/") - - def test_null(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://null.badssl.com/") - - def test_mozilla_intermediate(self): - self.assertTrue(self.download_file("https://mozilla-intermediate.badssl.com/")) - - def test_mozilla_modern(self): - self.assertTrue(self.download_file("https://mozilla-modern.badssl.com/")) - - def test_dh480(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://dh480.badssl.com/") - - def test_dh512(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://dh512.badssl.com/") - - def test_dh_small(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://dh-small.badssl.com/") - - def test_dh_composite(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://dh-composite.badssl.com/") - - def test_static_rsa(self): - # Static RSA is still supported in TLS1_2 but is probably going to be removed in TLS1_3 - self.assertTrue(self.download_file("https://static-rsa.badssl.com/")) - - def test_hsts(self): - self.assertTrue(self.download_file("https://hsts.badssl.com/")) - - def test_upgrade(self): - self.assertTrue(self.download_file("https://upgrade.badssl.com/")) - - def test_preloaded_hsts(self): - self.assertTrue(self.download_file("https://preloaded-hsts.badssl.com/")) - - def test_subdomain_preloaded_hsts(self): - self.assertRaises(ssl.CertificateError, self.download_file, "https://subdomain.preloaded-hsts.badssl.com/") - - def test_https_everywhere(self): - self.assertTrue(self.download_file("https://https-everywhere.badssl.com/")) - - def test_http(self): - self.assertTrue(self.download_file("https://http.badssl.com/")) - - def test_spoofed_favicon(self): - self.assertTrue(self.download_file("https://spoofed-favicon.badssl.com/")) - - def test_long_dashes(self): - self.assertTrue(self.download_file( - "https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/")) - - def test_long_without_dashes(self): - self.assertTrue(self.download_file( - "https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/")) - - def test_superfish(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://superfish.badssl.com/") - - def test_edellroot(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://edellroot.badssl.com/") - - def test_dsdtestprovider(self): - self.assertRaises(ssl.SSLError, self.download_file, "https://dsdtestprovider.badssl.com/") - - # I can't successfully load get CRL to work - # This is a new test in badssl.com is failing - # as well since I don't think Qt has support for it. - # "https://revoked.badssl.com/" - - # Excessive message size error - # "https://10000-sans.badssl.com/" - - # This check is platform specific. - # 8192-bit RSA keys were not supported in OSX between 2006 and 2015. - # "https://rsa8192.badssl.com/" - - # We don't download web pages - # "https://mixed-script.badssl.com/" - # "https://very.badssl.com/" - # mixed HTTP content in site - # "https://mixed.badssl.com/" - # implicit favicon redirects to HTTP - # "https://mixed-favicon.badssl.com/" - # "http://http-password.badssl.com/" - # "http://http-login.badssl.com/" - # "http://http-dynamic-login.badssl.com/" - # "http://http-credit-card.badssl.com/" - - # We're not yet sure how to reject mozilla old SSL certs. - # "https://mozilla-old.badssl.com/" - - # For some reason SSLv3 is used in these cases and we are blocking the use of SSLv3 - # "https://dh1024.badssl.com/" - # "https://dh2048.badssl.com/" - - # This test is failing in Setup Assistant as well - # "https://pinning-test.badssl.com/" - - -if __name__ == "__main__": - unittest.main() diff --git a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/bug_report.md b/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 686af41137..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -name: Bug Report -about: Create a bug report to help us improve. - ---- - -**Describe the bug** -Please provide a concise description of the bug. - -**Steps to reproduce** -Please provide steps to reproduce the bug. The more detail you provide, the more likely we'll be able to reproduce it. - -**Expected behavior** -Please provide a concise description of what you expected to happen. - -**Screenshots/Logs** -Please include any relevant screenshots and log files from your game project directory (e.g., C:\Amazon\lumberyard\1.15.0.0\dev\Cache\YOURPROJECT\pc\user\log). Note that you are posting to a public forum so please remove any sensitive information from your log files such as project name & path, IP address, credentials etc. - -**Lumberyard version** -State the version of Lumberyard in which you discovered this bug (e.g., v1.14.0.1 or v1.15.0.0 etc.). - -**[OPTIONAL] What is your role in game development?** -Are you a game designer, engineer, artist, producer, something else? - -**[OPTIONAL] Tell us about your project or studio.** -Briefly tell us about your project or studio. diff --git a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/feature_request.md b/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index f96f47cefe..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Feature Request -about: Suggest a feature you'd like to see developed. - ---- - -**Describe your feature request** -Please provide a concise description of the feature you'd like to see in Lumberyard. - -**Describe workarounds or alternatives you've considered** -Please provide a concise description of workarounds or alternative solutions you've considered. - -**[OPTIONAL] What is your role in game development?** -Are you a game designer, engineer, artist, producer, something else? - -**[OPTIONAL] Tell us about your project or studio.** -Briefly tell us about your project or studio. diff --git a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/question.md b/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index fa6e973928..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/inject/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Question -about: Ask a question to the community. - ---- - -**What is your question?** -Please ask your question here. - -**Which part of the engine are you asking about?** -Please indicate the component of the engine that your question relates to (e.g., Script Canvas, PhysX, Animation etc.). - -**Which version of Lumberyard are you using?** -State the Lumberyard version that you're using (e.g., v1.14.0.1 or v1.15.0.0 etc.). - -**[OPTIONAL] What is your role in game development?** -Are you a game designer, engineer, artist, producer, something else? - -**[OPTIONAL] Tell us about your project or studio.** -Briefly tell us about your project or studio. diff --git a/Tools/build/JenkinsScripts/distribution/git_release/inject/CONTRIBUTING.md b/Tools/build/JenkinsScripts/distribution/git_release/inject/CONTRIBUTING.md deleted file mode 100644 index b3a5ac3158..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/inject/CONTRIBUTING.md +++ /dev/null @@ -1,45 +0,0 @@ -# Contribution Guidelines -Thank you for visiting our contribution guidelines! An active and healthy development community is what makes a good game engine an exceptional game engine. As we focus on developing new features and resolving bugs with every version of Lumberyard, we want to hear from you. We are interested in seeing how you're using the engine and what improvements you're making while you work on your own game projects. This is why, in addition to our [GameDev Forums](https://gamedev.amazon.com/forums/index.html), [Tutorials](https://www.youtube.com/amazongamedev) and [Documentation](https://aws.amazon.com/documentation/lumberyard/), we provide you with the opportunity to share your features and improvements with your fellow developers. After you modify the core engine code, simply submit a pull request. - -To make it easy for you to contribute to our game engine, the Lumberyard development team adheres to the following coding conventions. We believe that these guidelines keep the engine code consistent and easy to understand so that you can spend less time interpreting code and more time coding. We look forward to your contributions! - -## Compiler Compatibility: -- Use the C++11 standard whenever possible. -- Stick to the C++11 features that are commonly supported by Microsoft Visual Studio 2013/2015 (refer to https://msdn.microsoft.com/en-us/library/hh567368.aspx). - -## Formatting: -- Lumberyard recommends using the Uncrustify code beautifier to keep C++ code consistent with the engine code. Refer to http://uncrustify.sourceforge.net/. -- Apply indentation in a consistent manner: - - Files should start without any indentation. - - Use a single additional level of indentation for each nested block of code. - - Indent all lines of a block by the same amount. - - Make lines a reasonable length. -- Indent preprocessor statements in a similar way to regular code. -- When positioning curly braces, open braces on a new line and keep them flush with the outer block's indentation. -- Always use curly braces for flow control statements. -- Each line of code should only include a single statement. -- Naming conventions for classes, functions, types and files should adhere to CamelCase and specify what the function does. -- All header files must include the directive, "#pragma once". -- Use forward declarations to minimize header file dependencies. Compile times are a concern so please put in the effort to minimize include chains. -- The following syntax should be used when including header files: #include -This rule helps disambiguate files from different packages that have the same name. might appear relatively often, but is far less likely to. - -## Classes: -- You should define a default constructor if your class defines member variables and has no other constructors. Unless you have a very specifically targeted optimization, you should initialize all variables to a known state even if the variable state is invalid. -- Do not assume any specific properties based on the choice of struct vs class; always use to check the actual properties -- Public declarations come before private declarations. Methods should be declared before data members. -- All methods that do not modify internal state should be const. All function parameters passed by pointer or reference should be marked const unless they are output parameters. -- Use the override keyword wherever possible and omit the keyword virtual when using override. -- Use the final keyword where its use can be justified. - -## Scoping: -- All of your code should be in at least a namespace named after the package and conform to the naming convention specified earlier in this document. -- Place a function's variable declarations in the narrowest possible scope and always initialize variables in their declaration. -- Static member or global variables that are concrete class objects are completely forbidden. If you must have a global object it should be a pointer, and it must be constructed and destroyed via appropriate functions. - -## Commenting Code: -Clear and concise communication is essential in keeping the code readable for everyone. Since comments are the main method for communication, please follow these guidelines for commenting the code: -- Use /// for comments. -- Use /**..*/ for block comments. -- Use @param, etc. for commands. -- Full sentences with good grammar are preferable to abbreviated notes. diff --git a/Tools/build/JenkinsScripts/distribution/git_release/inject/README.md b/Tools/build/JenkinsScripts/distribution/git_release/inject/README.md deleted file mode 100644 index 77384520c3..0000000000 --- a/Tools/build/JenkinsScripts/distribution/git_release/inject/README.md +++ /dev/null @@ -1,57 +0,0 @@ -![lmbr](http://d2tinsms4add52.cloudfront.net/github/readme_header.jpg) - -# Amazon Lumberyard -Amazon Lumberyard is a free, AAA game engine that gives you the tools you need to create high quality games. Deeply integrated with AWS and Twitch, Amazon Lumberyard includes full source code, allowing you to customize your project at any level. - -For more information, visit: https://aws.amazon.com/lumberyard/ - -## Acquiring Lumberyard source -Each release of Lumberyard exists as a separate branch in GitHub. You can get Lumberyard from GitHub using the following steps: - -### Fork the repository -Forking creates a copy of the Lumberyard repository in your GitHub account. Your fork becomes the remote repository into which you can push changes. - -### Create a branch -The GitHub workflow assumes your master branch is always deployable. Create a branch for your local project or fixes. - -For more information about branching, see the [GitHub documentation](https://guides.github.com/introduction/flow/). - -### Clone the repository -Cloning the repository copies your fork onto your computer. To clone the repository, click the "Clone or download" button on the GitHub website, and copy the resultant URL to the clipboard. In a command line window, type ```git clone [URL]```, where ```[URL]``` is the URL that you copied in the previous step. - -For more information about cloning a reposity, see the [GitHub documentation](https://help.github.com/articles/cloning-a-repository/). - - -### Downloading additive files -Once the repository exists locally on your machine, manually execute ```git_bootstrap.exe``` found at the root of the repository. This application will perform a download operation for __Lumberyard binaries that are required prior to using or building the engine__. This program uses AWS services to download the binaries. Monitor the health of AWS services on the [AWS Service Health Dashboard](https://status.aws.amazon.com/). - -### Running the Setup Assistant -```git_bootstrap.exe``` will launch the Setup Assistant when it completes. Setup Assistant lets you configure your environment and launch the Lumberyard Editor. - -## Contributing code to Lumberyard -You can submit changes or fixes to Lumberyard using pull requests. When you submit a pull request, the Lumberyard support team is notified and evaluates the code you submitted. You may be contacted to provide further detail or clarification while the support team evaluates your submitted code. - -### Best practices for submitting pull requests -Before submitting a pull request to a Lumberyard branch, please merge the latest changes from that branch into your project. We only accept pull requests on the latest version of a branch. - -For more information about working with pull requests, see the [GitHub documentation](https://help.github.com/articles/cloning-a-repository/). - -## Purpose of Lumberyard on GitHub -Lumberyard on GitHub provides a way for you to view and acquire the engine source code, and contribute by submitting pull requests. Lumberyard does not endorse any particular source control system for your personal use. - -## Lumberyard Documentation -Full Lumberyard documentation can be found here: -https://aws.amazon.com/documentation/lumberyard/ -We also have tutorials available at https://www.youtube.com/amazongamedev - -## License -Your use of Lumberyard is governed by the AWS Customer Agreement at https://aws.amazon.com/agreement/ and Lumberyard Service Terms at https://aws.amazon.com/serviceterms/#57._Amazon_Lumberyard_Engine. - -For complete copyright and license terms please see the LICENSE.txt file at the root of this distribution (the "License"). As a reminder, here are some key pieces to keep in mind when submitting changes/fixes and creating your own forks: -- If you submit a change/fix, we can use it without restriction, and other Lumberyard users can use it under the License. -- Only share forks in this GitHub repo (i.e., forks must be parented to https://github.com/aws/lumberyard). -- Your forks are governed by the License, and you must include the License.txt file with your fork. Please also add a note at the top explaining your modifications. -- If you use someone else’s fork from this repo, your use is subject to the License. -- Your fork may not enable the use of third-party compute, storage or database services. -- It's fine to connect to third-party platform services like Steamworks, Apple GameCenter, console platform services, etc. -To learn more, please see our FAQs https://aws.amazon.com/lumberyard/faq/#licensing. diff --git a/Tools/build/JenkinsScripts/distribution/inject_signed_binaries.py b/Tools/build/JenkinsScripts/distribution/inject_signed_binaries.py deleted file mode 100755 index 516bc4f56e..0000000000 --- a/Tools/build/JenkinsScripts/distribution/inject_signed_binaries.py +++ /dev/null @@ -1,167 +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. - -Description: - Release automation script that injects signed binary files into package zips - then generates new MD5 checksum files for the modified packages. -""" -import argparse -import os -import subprocess -import sys - -from AWS_PyTools.LyChecksum import getMD5ChecksumForSingleFile -from Installer.InstallerAutomation import defaultFilesToSign -from Installer.SignTool import signtoolVerifySign - -DEFAULT_FILES_TO_INJECT = defaultFilesToSign -DEFAULT_PLATFORMS = ['pc', 'provo', 'consoles'] -DEFAULT_WORKING_DIR = '%TEMP%/installerAuto' -DEFAULT_PATH_7ZIP = 'C:/7z.exe' - -DEFAULT_VERSION = os.environ.get('VERSION') -DEFAULT_P4_CL = os.environ.get('P4_CL') -DEFAULT_BUILD_NUMBER = os.environ.get('BUILD_NUMBER') - - -class InjectionError(Exception): pass - - -def create_md5_file(file_path, checksum): - """Write the provided checksum to an .MD5 file and return the file path.""" - md5_file = '{}.MD5'.format(file_path) - with open(md5_file, 'w') as f: - f.write(checksum) - return md5_file - - -def format_package_name(package_version, changelist, platform, build_number): - """Return a string of the package name in the standard format""" - package_name = 'lumberyard-{0}-{1}-{2}-{3}.zip'.format(package_version, changelist, platform, build_number) - return package_name - - -def verify_signed_files(binary_files, working_dir, verbose): - """Verifies that the binary files in the workspace are signed - - Function imported from Installer/SignTool.py to verify binary files. - Returns True if file is signed. - - Returns: - The list of relative paths for the verified signed files - - """ - signed_binary_files = [] - for b in binary_files: - binary_file_path = os.path.join(working_dir, b) - signed = signtoolVerifySign(binary_file_path, verbose) - if not signed: - raise InjectionError('Unsigned binary file found in workspace: {0}'.format(b)) - signed_binary_files.append(b) - return signed_binary_files - - -def print_result(description, list): - """Prints the result with formatting""" - list_new_line = '\n'.join(map(str, list)) - result = '\n'.join([description, list_new_line]) - print(result) - - -def generate_md5_checksums(updated_zips): - """Using a list of file paths, generate MD5 checksums. - - Function is imported from AWS_PyTools/LyChecksum.py to generate checksum - A file is then created for each checksum. - - Returns: - The list of paths for the generated .MD5 files. - - """ - md5_files = [] - for z in updated_zips: - checksum = getMD5ChecksumForSingleFile(z).hexdigest() - md5_file = create_md5_file(z, checksum) - md5_files.append(md5_file) - return md5_files - - -def inject_binaries(args): - """Inject signed binary files into package zips. - - Verify that the binary files are signed. - Write the signed binary list to a file seprated by new lines to supply to 7-Zip. - - Run command to inject signed binary into package zips. - Command line syntax: 7z.exe a -spf2 @ - - Returns: - The list of file paths for the updated package zips. - - """ - signed_binary_files = verify_signed_files(args.files_to_inject, args.working_dir, args.verbose) - - list_file_path = os.path.join(args.working_dir, 'list_file.txt') - with open(list_file_path, 'w') as list_file: - list_file.write('\n'.join(signed_binary_files)) - - updated_zips = [] - for p in args.platforms: - package_name = format_package_name(args.package_version, args.changelist, p, args.build_number) - package_path = os.path.join(args.working_dir, package_name) - try: - subprocess.check_call([args.path_7zip, 'a', '-spf2', package_path, '@{0}'.format(list_file_path)], - cwd=args.working_dir) - updated_zips.append(package_path) - except subprocess.CalledProcessError as e: - raise InjectionError('Error using 7z to inject signed binaries: {0}'.format(e)) - return updated_zips - - -def parse_args(): - """Setup arguments. Defaults to using build parameters and binary list also used by CODESIGN_Windows.""" - parser = argparse.ArgumentParser( - description='Inject signed binary files into package zips then generate new MD5 checksums') - parser.add_argument('-w', '--working-dir', default=DEFAULT_WORKING_DIR, - help='Directory where the binary files and package zips are located.') - parser.add_argument('-p', '--package-version', default=DEFAULT_VERSION, - help='. version of the target packages.') - parser.add_argument('-c', '--changelist', default=DEFAULT_P4_CL, - help='Perforce changelist for the target packages') - parser.add_argument('-b', '--build-number', default=DEFAULT_BUILD_NUMBER, - help='Perforce changelist for the target packages') - parser.add_argument('--files-to-inject', nargs='+', default=DEFAULT_FILES_TO_INJECT, - help='List of binaries to inject into the package zips. Defaults to the list used to sign the files.') - parser.add_argument('--platforms', nargs='+', default=DEFAULT_PLATFORMS, - help='Specifies which platform packages to inject.') - parser.add_argument('--path-7zip', default=DEFAULT_PATH_7ZIP, - help='Path for the 7zip executable.') - parser.add_argument('--verbose', action='store_true', - help='Verbose output on codesigning commands.') - args = parser.parse_args() - return args - - -def main(): - try: - args = parse_args() - updated_zips = inject_binaries(args) - md5_files = generate_md5_checksums(updated_zips) - - print_result('Package zips updated with signed binaries:', updated_zips) - print_result('Generated MD5 checksum files:', md5_files) - except InjectionError as e: - raise SystemExit('Injection Error: {}'.format(e)) - - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/ly_dep_version_tool.py b/Tools/build/JenkinsScripts/distribution/ly_dep_version_tool.py deleted file mode 100755 index 2e6355cf36..0000000000 --- a/Tools/build/JenkinsScripts/distribution/ly_dep_version_tool.py +++ /dev/null @@ -1,59 +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. -""" - -from optparse import OptionParser -import os, json, re, sys - -dirDescriptor = ".package.dir" -def main(): - parser = OptionParser() - parser.add_option( "-s", "--source", - dest="source", - help="Specify the boot-strap tool's metadata file to be parsed (i.e. C:/dev/SetupAssistantConfig.json)", - default="../../../../SetupAssistantConfig.json") - parser.add_option( "-o", "--outputfile", - dest="output", - help="Specify the output file of this tool. If it exists, it will be over-written.", - default="./3rdparty_versions.txt") - (options, args) = parser.parse_args() - - if not os.path.isfile(options.source): - print 'invalid sourcefile "{}"'.format(options.source) - return 2 - - ant_property_list = '' - - with open(options.source, 'r') as source: - source_json = json.load(source) - - sdks_list = source_json['SDKs'] - - for sdk_object in sdks_list: - identifier = sdk_object['identifier'].encode('ascii') - - if identifier: - subdir = sdk_object.get('source') - - ant_property_list += '{}={}\n'.format(identifier + dirDescriptor, subdir) - # Wwise LTX is distributed differently than other SDKs, and exists in two locations. - if identifier == "wwiseLtx": - justVersionDir = re.sub("Wwise/", "", subdir) - ant_property_list += '{}={}\n'.format("wwiseLtx.tool" + dirDescriptor, justVersionDir) - - with open(options.output, 'w') as output: - output.write(ant_property_list) - - print '\nANT Properties:' - print ant_property_list.strip() - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/modify_lylauncherconfig.py b/Tools/build/JenkinsScripts/distribution/modify_lylauncherconfig.py deleted file mode 100755 index aac7f82ae0..0000000000 --- a/Tools/build/JenkinsScripts/distribution/modify_lylauncherconfig.py +++ /dev/null @@ -1,24 +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. -""" - -import fileinput -import os -import stat - -os.chmod('SetupAssistantConfig.ini', stat.S_IWRITE) -for line in fileinput.input('SetupAssistantConfig.ini', inplace=1): - # Below is an example of how to modify the value for 'compileandroid'. Its commented out to demonstrate the ability to - # alter entries in this file in the future - #if line.startswith(';compileandroid'): - # print('compileandroid="enabled" ; compile runtime for android') - #else: - print line, \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/package_source_assets.bat b/Tools/build/JenkinsScripts/distribution/package_source_assets.bat deleted file mode 100644 index a390e2fad5..0000000000 --- a/Tools/build/JenkinsScripts/distribution/package_source_assets.bat +++ /dev/null @@ -1,44 +0,0 @@ -REM -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 - -@ECHO WARNING This batch file, %0, is deprecated. See ant script build.xml -EXIT 0 - -REM TBD: once the build.xml script gets past CB5 QA, remove the below lines -REM Until then, keep this to compare the build.xml behavior in CB5 to the CB4 behavior below -@echo #1 -IF EXIST .\Bin64vc141\rc\rc.exe ( - SET BINFOLDER=Bin64vc141 -) ELSE ( - ECHO Cannot find rc.exe - EXIT /b 1 -) - -.\%BINFOLDER%\rc\rc.exe /job=.\%BINFOLDER%\rc\RCJob_Build_RPGSample_paks.xml > BuildRPGSamplePaks.log -del TempRC\RPGsample /s /q -del Build\RPGSample /s /q - -@echo #2 -@echo Move (not copy) these files into another folder, zip it up so it retains the same folder structure. That way someone could just extract the .zip file and have everything go to the right place -xcopy RPGSample\*.dds SourceAssets\RPGSample /s /i -xcopy RPGSample\*.tif SourceAssets\RPGSample /s /i -xcopy RPGSample\*.psd SourceAssets\RPGSample /s /i - -del RPGSample\*.dds /s /q /f -del RPGSample\*.tif /s /q /f -del RPGSample\*.psd /s /q /f - - -@echo #3 We'll deliver the packaged engine and the assets that were moved in #2 separately, so they can choose to download the source art or not (an extra 15GB or so) - -@echo If they choose to extract the source art, they'll want to run -@echo .\%BINFOLDER%\rc\rc.exe /job=.\Bin64\rc\RCJob_Compile_RPGSample_Textures.xml \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/release_automation_tool.py b/Tools/build/JenkinsScripts/distribution/release_automation_tool.py deleted file mode 100755 index de1ab8423b..0000000000 --- a/Tools/build/JenkinsScripts/distribution/release_automation_tool.py +++ /dev/null @@ -1,47 +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. -""" - -from Installer import InstallerAutomation -from ThirdParty import thirdparty_bucket_fetch -import os - -def main(): - # make sure that current working directory is the directory that this - # script lives in - abspath = os.path.abspath(__file__) - dname = os.path.dirname(abspath) - os.chdir(dname) - - # parse InstallerAutomation args from execution of this script - os.chdir("Installer") - installerArgs = InstallerAutomation.createArgs() - InstallerAutomation.validateArgs(installerArgs) - os.chdir("..") - - # If we succeed InstallerAutomation validation (we would have asserted otherwise), - # then parse thirdparty_bucket_fetch args. - os.chdir("ThirdParty") - ladPackageArgs = thirdparty_bucket_fetch.parse_args() - ladPackageParams = thirdparty_bucket_fetch.PromoterParams(ladPackageArgs) - os.chdir("..") - - # if we succeeded that one too, then it is safe to run the scripts themselves - os.chdir("Installer") - InstallerAutomation.run(installerArgs) - - os.chdir("../ThirdParty") - thirdparty_bucket_fetch.run(ladPackageArgs, ladPackageParams) - - os.chdir("..") - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/s3multiput.py b/Tools/build/JenkinsScripts/distribution/s3multiput.py deleted file mode 100755 index 63fa30d967..0000000000 --- a/Tools/build/JenkinsScripts/distribution/s3multiput.py +++ /dev/null @@ -1,379 +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. -""" - -#!/usr/bin/python -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -# multipart portions copyright Fabian Topfstedt -# https://gist.github.com/924094 - - -import math -import mimetypes -from multiprocessing import Pool -import getopt, sys, os - -import boto -from boto.exception import S3ResponseError - -from boto.s3.connection import S3Connection -from filechunkio import FileChunkIO - -import time - -usage_string = """ -SYNOPSIS - s3put [-a/--access_key ] [-s/--secret_key ] - -b/--bucket [-c/--callback ] - [-d/--debug ] [-i/--ignore ] - [-n/--no_op] [-p/--prefix ] [-k/--key_prefix ] - [-q/--quiet] [-g/--grant grant] [-w/--no_overwrite] [-r/--reduced] path - - Where - access_key - Your AWS Access Key ID. If not supplied, boto will - use the value of the environment variable - AWS_ACCESS_KEY_ID - secret_key - Your AWS Secret Access Key. If not supplied, boto - will use the value of the environment variable - AWS_SECRET_ACCESS_KEY - bucket_name - The name of the S3 bucket the file(s) should be - copied to. - path - A path to a directory or file that represents the items - to be uploaded. If the path points to an individual file, - that file will be uploaded to the specified bucket. If the - path points to a directory, s3_it will recursively traverse - the directory and upload all files to the specified bucket. - debug_level - 0 means no debug output (default), 1 means normal - debug output from boto, and 2 means boto debug output - plus request/response output from httplib - ignore_dirs - a comma-separated list of directory names that will - be ignored and not uploaded to S3. - num_cb - The number of progress callbacks to display. The default - is zero which means no callbacks. If you supplied a value - of "-c 10" for example, the progress callback would be - called 10 times for each file transferred. - prefix - A file path prefix that will be stripped from the full - path of the file when determining the key name in S3. - For example, if the full path of a file is: - /home/foo/bar/fie.baz - and the prefix is specified as "-p /home/foo/" the - resulting key name in S3 will be: - /bar/fie.baz - The prefix must end in a trailing separator and if it - does not then one will be added. - key_prefix - A prefix to be added to the S3 key name, after any - stripping of the file path is done based on the - "-p/--prefix" option. - reduced - Use Reduced Redundancy storage - grant - A canned ACL policy that will be granted on each file - transferred to S3. The value of provided must be one - of the "canned" ACL policies supported by S3: - private|public-read|public-read-write|authenticated-read - no_overwrite - No files will be overwritten on S3, if the file/key - exists on s3 it will be kept. This is useful for - resuming interrupted transfers. Note this is not a - sync, even if the file has been updated locally if - the key exists on s3 the file on s3 will not be - updated. - - If the -n option is provided, no files will be transferred to S3 but - informational messages will be printed about what would happen. -""" -def usage(): - print usage_string - sys.exit() - -def submit_cb(bytes_so_far, total_bytes): - print '%d bytes transferred / %d bytes total' % (bytes_so_far, total_bytes) - -_last_cb_end = None # XXX blargh! -def init_throttle(): - global _last_cb_end - _last_cb_end = time.time() - -def throttle_cb(bytes_so_far, total_bytes): - global _last_cb_end - # print '%d bytes transferred / %d bytes total' % (bytes_so_far, total_bytes) - - d = time.time() - _last_cb_end - time.sleep(1.0 - d) - _last_cb_end = time.time() - -def get_key_name(fullpath, prefix, key_prefix): - key_name = fullpath[len(prefix):] - l = key_name.split(os.sep) - return key_prefix + '/'.join(l) - -def _upload_part(bucketname, aws_key, aws_secret, multipart_id, part_num, - source_path, offset, bytes, debug, cb, num_cb, amount_of_retries=10): - if debug == 1: - print "_upload_part(%s, %s, %s)" % (source_path, offset, bytes) - """ - Uploads a part with retries. - """ - def _upload(retries_left=amount_of_retries): - try: - if debug == 1: - print 'Start uploading part #%d ...' % part_num - conn = S3Connection(aws_key, aws_secret) - conn.debug = debug - bucket = conn.get_bucket(bucketname) - for mp in bucket.get_all_multipart_uploads(): - if mp.id == multipart_id: - with FileChunkIO(source_path, 'r', offset=offset, - bytes=bytes) as fp: - mp.upload_part_from_file(fp=fp, part_num=part_num, cb=cb, num_cb=num_cb) - break - except Exception, exc: - if retries_left: - _upload(retries_left=retries_left - 1) - else: - print 'Failed uploading part #%d' % part_num - raise exc - else: - if debug == 1: - print '... Uploaded part #%d' % part_num - - _upload() - -def upload(bucketname, aws_key, aws_secret, source_path, keyname, - reduced, debug, cb, num_cb, - acl='private', headers={}, guess_mimetype=True, parallel_processes=4, throttle_kbps=None): - """ - Parallel multipart upload. - """ - conn = S3Connection(aws_key, aws_secret) - conn.debug = debug - bucket = conn.get_bucket(bucketname) - - if guess_mimetype: - mtype = mimetypes.guess_type(keyname)[0] or 'application/octet-stream' - headers.update({'Content-Type': mtype}) - - mp = bucket.initiate_multipart_upload(keyname, headers=headers, reduced_redundancy=reduced) - - source_size = os.stat(source_path).st_size - bytes_per_chunk = max(int(math.sqrt(5242880) * math.sqrt(source_size)), - 5242880) - chunk_amount = int(math.ceil(source_size / float(bytes_per_chunk))) - - if parallel_processes == 0: - print "doing serial upload" - if throttle_kbps: - print "throttling to %d kbps" % throttle_kbps - - for i in range(chunk_amount): - offset = i * bytes_per_chunk - remaining_bytes = source_size - offset - bytes = min([bytes_per_chunk, remaining_bytes]) - part_num = i + 1 - - if throttle_kbps: - chunks = bytes / (throttle_kbps * 1024) - print "uploading %d bytes in %d chunks" % (bytes, chunks) - num_cb = chunks - cb = throttle_cb - init_throttle() - - _upload_part(bucketname, aws_key, aws_secret, mp.id, part_num, - source_path, offset, bytes, debug, cb, num_cb, amount_of_retries=2) - else: - pool = Pool(processes=parallel_processes) - for i in range(chunk_amount): - offset = i * bytes_per_chunk - remaining_bytes = source_size - offset - bytes = min([bytes_per_chunk, remaining_bytes]) - part_num = i + 1 - pool.apply_async(_upload_part, [bucketname, aws_key, aws_secret, mp.id, - part_num, source_path, offset, bytes, debug, cb, num_cb]) - pool.close() - pool.join() - - if len(mp.get_all_parts()) == chunk_amount: - mp.complete_upload() - key = bucket.get_key(keyname) - #key.set_acl(acl) - else: - mp.cancel_upload() - - -def main(): - - # default values - aws_access_key_id = None - aws_secret_access_key = None - bucket_name = '' - ignore_dirs = [] - total = 0 - debug = 0 - cb = None - num_cb = 0 - quiet = False - no_op = False - prefix = '/' - key_prefix = '' - grant = None - no_overwrite = False - reduced = False - num_workers = 4 - throttle_kbps=None - - try: - opts, args = getopt.getopt(sys.argv[1:], 'a:b:c::d:g:hi:k:np:qs:wr', - ['access_key=', 'bucket=', 'callback=', 'debug=', 'help', 'grant=', - 'ignore=', 'key_prefix=', 'no_op', 'prefix=', 'quiet', 'secret_key=', - 'no_overwrite', 'reduced', 'throttle=', 'num_workers=']) - except getopt.GetoptError, e: - print e - usage() - - # parse opts - for o, a in opts: - if o in ('-h', '--help'): - usage() - if o in ('-a', '--access_key'): - aws_access_key_id = a - if o in ('-b', '--bucket'): - bucket_name = a - if o in ('-c', '--callback'): - num_cb = int(a) - cb = submit_cb - if o in ('-d', '--debug'): - debug = int(a) - if o in ('-g', '--grant'): - grant = a - if o in ('-i', '--ignore'): - ignore_dirs = a.split(',') - if o in ('-n', '--no_op'): - no_op = True - if o in ('w', '--no_overwrite'): - no_overwrite = True - if o in ('-p', '--prefix'): - prefix = a - if prefix[-1] != os.sep: - prefix = prefix + os.sep - if o in ('-k', '--key_prefix'): - key_prefix = a - if o in ('-q', '--quiet'): - quiet = True - if o in ('-s', '--secret_key'): - aws_secret_access_key = a - if o in ('-r', '--reduced'): - reduced = True - if o in ('--throttle'): # XXX this will interfere with cb params - throttle_kbps = int(a) - if o in ('--num_workers'): - num_workers = int(a) - - if len(args) != 1: - usage() - - path = os.path.expanduser(args[0]) - path = os.path.expandvars(path) - path = os.path.abspath(path) - - if not bucket_name: - print "bucket name is required!" - usage() - - c = boto.connect_s3(aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key) - c.debug = debug - b = c.get_bucket(bucket_name) - - # upload a directory of files recursively - if os.path.isdir(path): - if no_overwrite: - if not quiet: - print 'Getting list of existing keys to check against' - keys = [] - for key in b.list(get_key_name(path, prefix, key_prefix)): - keys.append(key.name) - for root, dirs, files in os.walk(path): - for ignore in ignore_dirs: - if ignore in dirs: - dirs.remove(ignore) - for file in files: - fullpath = os.path.join(root, file) - key_name = get_key_name(fullpath, prefix, key_prefix) - copy_file = True - if no_overwrite: - if key_name in keys: - copy_file = False - if not quiet: - print 'Skipping %s as it exists in s3' % file - - if copy_file: - if not quiet: - print 'Copying %s to %s/%s' % (file, bucket_name, key_name) - - if not no_op: - if os.stat(fullpath).st_size == 0: - # 0-byte files don't work and also don't need multipart upload - k = b.new_key(key_name) - k.set_contents_from_filename(fullpath, cb=cb, num_cb=num_cb, - policy=grant, reduced_redundancy=reduced) - else: - upload(bucket_name, aws_access_key_id, - aws_secret_access_key, fullpath, key_name, - reduced, debug, cb, num_cb, grant or 'private', - parallel_processes=num_workers, throttle_kbps=throttle_kbps) - total += 1 - - # upload a single file - elif os.path.isfile(path): - key_name = get_key_name(os.path.abspath(path), prefix, key_prefix) - copy_file = True - if no_overwrite: - if b.get_key(key_name): - copy_file = False - if not quiet: - print 'Skipping %s as it exists in s3' % path - - if copy_file: - if not quiet: - print 'Copying %s to %s/%s' % (path, bucket_name, key_name) - - if not no_op: - if os.stat(path).st_size == 0: - # 0-byte files don't work and also don't need multipart upload - k = b.new_key(key_name) - k.set_contents_from_filename(path, cb=cb, num_cb=num_cb, policy=grant, - reduced_redundancy=reduced) - else: - upload(bucket_name, aws_access_key_id, - aws_secret_access_key, path, key_name, - reduced, debug, cb, num_cb, grant or 'private', - parallel_processes=num_workers, throttle_kbps=throttle_kbps) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/s3put.py b/Tools/build/JenkinsScripts/distribution/s3put.py deleted file mode 100755 index 95a2f06048..0000000000 --- a/Tools/build/JenkinsScripts/distribution/s3put.py +++ /dev/null @@ -1,450 +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. -""" - -#!C:\Python27\python.exe -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import getopt -import sys -import os -import boto - -from boto.compat import six - -try: - # multipart portions copyright Fabian Topfstedt - # https://gist.github.com/924094 - - import math - import mimetypes - from multiprocessing import Pool - from boto.s3.connection import S3Connection - from filechunkio import FileChunkIO - multipart_capable = True - usage_flag_multipart_capable = """ [--multipart]""" - usage_string_multipart_capable = """ - multipart - Upload files as multiple parts. This needs filechunkio. - Requires ListBucket, ListMultipartUploadParts, - ListBucketMultipartUploads and PutObject permissions.""" -except ImportError as err: - multipart_capable = False - usage_flag_multipart_capable = "" - if six.PY2: - attribute = 'message' - else: - attribute = 'msg' - usage_string_multipart_capable = '\n\n "' + \ - getattr(err, attribute)[len('No module named '):] + \ - '" is missing for multipart support ' - - -DEFAULT_REGION = 'us-east-1' - -usage_string = """ -SYNOPSIS - s3put [-a/--access_key ] [-s/--secret_key ] - -b/--bucket [-c/--callback ] - [-d/--debug ] [-i/--ignore ] - [-n/--no_op] [-p/--prefix ] [-k/--key_prefix ] - [-q/--quiet] [-g/--grant grant] [-w/--no_overwrite] [-r/--reduced] - [--header] [--region ] [--host ]""" + \ - usage_flag_multipart_capable + """ path [path...] - - Where - access_key - Your AWS Access Key ID. If not supplied, boto will - use the value of the environment variable - AWS_ACCESS_KEY_ID - secret_key - Your AWS Secret Access Key. If not supplied, boto - will use the value of the environment variable - AWS_SECRET_ACCESS_KEY - bucket_name - The name of the S3 bucket the file(s) should be - copied to. - path - A path to a directory or file that represents the items - to be uploaded. If the path points to an individual file, - that file will be uploaded to the specified bucket. If the - path points to a directory, it will recursively traverse - the directory and upload all files to the specified bucket. - debug_level - 0 means no debug output (default), 1 means normal - debug output from boto, and 2 means boto debug output - plus request/response output from httplib - ignore_dirs - a comma-separated list of directory names that will - be ignored and not uploaded to S3. - num_cb - The number of progress callbacks to display. The default - is zero which means no callbacks. If you supplied a value - of "-c 10" for example, the progress callback would be - called 10 times for each file transferred. - prefix - A file path prefix that will be stripped from the full - path of the file when determining the key name in S3. - For example, if the full path of a file is: - /home/foo/bar/fie.baz - and the prefix is specified as "-p /home/foo/" the - resulting key name in S3 will be: - /bar/fie.baz - The prefix must end in a trailing separator and if it - does not then one will be added. - key_prefix - A prefix to be added to the S3 key name, after any - stripping of the file path is done based on the - "-p/--prefix" option. - reduced - Use Reduced Redundancy storage - grant - A canned ACL policy that will be granted on each file - transferred to S3. The value of provided must be one - of the "canned" ACL policies supported by S3: - private|public-read|public-read-write|authenticated-read - no_overwrite - No files will be overwritten on S3, if the file/key - exists on s3 it will be kept. This is useful for - resuming interrupted transfers. Note this is not a - sync, even if the file has been updated locally if - the key exists on s3 the file on s3 will not be - updated. - header - key=value pairs of extra header(s) to pass along in the - request - region - Manually set a region for buckets that are not in the US - classic region. Normally the region is autodetected, but - setting this yourself is more efficient. - host - Hostname override, for using an endpoint other then AWS S3 -""" + usage_string_multipart_capable + """ - - - If the -n option is provided, no files will be transferred to S3 but - informational messages will be printed about what would happen. -""" - - -def usage(status=1): - print(usage_string) - sys.exit(status) - - -def submit_cb(bytes_so_far, total_bytes): - print('%d bytes transferred / %d bytes total' % (bytes_so_far, total_bytes)) - - -def get_key_name(fullpath, prefix, key_prefix): - if fullpath.startswith(prefix): - key_name = fullpath[len(prefix):] - else: - key_name = fullpath - l = key_name.split(os.sep) - return key_prefix + '/'.join(l) - - -def _upload_part(bucketname, aws_key, aws_secret, multipart_id, part_num, - source_path, offset, bytes, debug, cb, num_cb, - amount_of_retries=10): - """ - Uploads a part with retries. - """ - if debug == 1: - print("_upload_part(%s, %s, %s)" % (source_path, offset, bytes)) - - def _upload(retries_left=amount_of_retries): - try: - if debug == 1: - print('Start uploading part #%d ...' % part_num) - conn = S3Connection(aws_key, aws_secret) - conn.debug = debug - bucket = conn.get_bucket(bucketname) - for mp in bucket.get_all_multipart_uploads(): - if mp.id == multipart_id: - with FileChunkIO(source_path, 'r', offset=offset, - bytes=bytes) as fp: - mp.upload_part_from_file(fp=fp, part_num=part_num, - cb=cb, num_cb=num_cb) - break - except Exception as exc: - if retries_left: - _upload(retries_left=retries_left - 1) - else: - print('Failed uploading part #%d' % part_num) - raise exc - else: - if debug == 1: - print('... Uploaded part #%d' % part_num) - - _upload() - -def check_valid_region(conn, region): - if conn is None: - print('Invalid region (%s)' % region) - sys.exit(1) - -def multipart_upload(bucketname, aws_key, aws_secret, source_path, keyname, - reduced, debug, cb, num_cb, acl='private', headers={}, - guess_mimetype=True, parallel_processes=4, - region=DEFAULT_REGION): - """ - Parallel multipart upload. - """ - conn = boto.s3.connect_to_region(region, aws_access_key_id=aws_key, - aws_secret_access_key=aws_secret) - check_valid_region(conn, region) - conn.debug = debug - bucket = conn.get_bucket(bucketname) - - if guess_mimetype: - mtype = mimetypes.guess_type(keyname)[0] or 'application/octet-stream' - headers.update({'Content-Type': mtype}) - - mp = bucket.initiate_multipart_upload(keyname, headers=headers, - reduced_redundancy=reduced) - - source_size = os.stat(source_path).st_size - bytes_per_chunk = max(int(math.sqrt(5242880) * math.sqrt(source_size)), - 5242880) - chunk_amount = int(math.ceil(source_size / float(bytes_per_chunk))) - - pool = Pool(processes=parallel_processes) - for i in range(chunk_amount): - offset = i * bytes_per_chunk - remaining_bytes = source_size - offset - bytes = min([bytes_per_chunk, remaining_bytes]) - part_num = i + 1 - pool.apply_async(_upload_part, [bucketname, aws_key, aws_secret, mp.id, - part_num, source_path, offset, bytes, - debug, cb, num_cb]) - pool.close() - pool.join() - - if len(mp.get_all_parts()) == chunk_amount: - mp.complete_upload() - key = bucket.get_key(keyname) - key.set_acl(acl) - else: - mp.cancel_upload() - - -def singlepart_upload(bucket, key_name, fullpath, *kargs, **kwargs): - """ - Single upload. - """ - k = bucket.new_key(key_name) - k.set_contents_from_filename(fullpath, *kargs, **kwargs) - - -def expand_path(path): - path = os.path.expanduser(path) - path = os.path.expandvars(path) - return os.path.abspath(path) - - -def main(): - - # default values - aws_access_key_id = None - aws_secret_access_key = None - bucket_name = '' - ignore_dirs = [] - debug = 0 - cb = None - num_cb = 0 - quiet = False - no_op = False - prefix = '/' - key_prefix = '' - grant = None - no_overwrite = False - reduced = False - headers = {} - host = None - multipart_requested = False - region = None - - try: - opts, args = getopt.getopt( - sys.argv[1:], 'a:b:c::d:g:hi:k:np:qs:wr', - ['access_key=', 'bucket=', 'callback=', 'debug=', 'help', 'grant=', - 'ignore=', 'key_prefix=', 'no_op', 'prefix=', 'quiet', - 'secret_key=', 'no_overwrite', 'reduced', 'header=', 'multipart', - 'host=', 'region=']) - except: - usage(1) - - # parse opts - for o, a in opts: - if o in ('-h', '--help'): - usage(0) - if o in ('-a', '--access_key'): - aws_access_key_id = a - if o in ('-b', '--bucket'): - bucket_name = a - if o in ('-c', '--callback'): - num_cb = int(a) - cb = submit_cb - if o in ('-d', '--debug'): - debug = int(a) - if o in ('-g', '--grant'): - grant = a - if o in ('-i', '--ignore'): - ignore_dirs = a.split(',') - if o in ('-n', '--no_op'): - no_op = True - if o in ('-w', '--no_overwrite'): - no_overwrite = True - if o in ('-p', '--prefix'): - prefix = a - if prefix[-1] != os.sep: - prefix = prefix + os.sep - prefix = expand_path(prefix) - if o in ('-k', '--key_prefix'): - key_prefix = a - if o in ('-q', '--quiet'): - quiet = True - if o in ('-s', '--secret_key'): - aws_secret_access_key = a - if o in ('-r', '--reduced'): - reduced = True - if o == '--header': - (k, v) = a.split("=", 1) - headers[k] = v - if o == '--host': - host = a - if o == '--multipart': - if multipart_capable: - multipart_requested = True - else: - print("multipart upload requested but not capable") - sys.exit(4) - if o == '--region': - regions = boto.s3.regions() - for region_info in regions: - if region_info.name == a: - region = a - break - else: - raise ValueError('Invalid region %s specified' % a) - - if len(args) < 1: - usage(2) - - if not bucket_name: - print("bucket name is required!") - usage(3) - - connect_args = { - 'aws_access_key_id': aws_access_key_id, - 'aws_secret_access_key': aws_secret_access_key - } - - if host: - connect_args['host'] = host - - c = boto.s3.connect_to_region(region or DEFAULT_REGION, **connect_args) - check_valid_region(c, region or DEFAULT_REGION) - c.debug = debug - b = c.get_bucket(bucket_name, validate=False) - - # Attempt to determine location and warn if no --host or --region - # arguments were passed. Then try to automagically figure out - # what should have been passed and fix it. - if host is None and region is None: - try: - location = b.get_location() - - # Classic region will be '', any other will have a name - if location: - print('Bucket exists in %s but no host or region given!' % location) - - # Override for EU, which is really Ireland according to the docs - if location == 'EU': - location = 'eu-west-1' - - print('Automatically setting region to %s' % location) - - # Here we create a new connection, and then take the existing - # bucket and set it to use the new connection - c = boto.s3.connect_to_region(location, **connect_args) - c.debug = debug - b.connection = c - except Exception as e: - if debug > 0: - print(e) - print('Could not get bucket region info, skipping...') - - existing_keys_to_check_against = [] - files_to_check_for_upload = [] - - for path in args: - path = expand_path(path) - # upload a directory of files recursively - if os.path.isdir(path): - if no_overwrite: - if not quiet: - print('Getting list of existing keys to check against') - for key in b.list(get_key_name(path, prefix, key_prefix)): - existing_keys_to_check_against.append(key.name) - for root, dirs, files in os.walk(path): - for ignore in ignore_dirs: - if ignore in dirs: - dirs.remove(ignore) - for path in files: - if path.startswith("."): - continue - files_to_check_for_upload.append(os.path.join(root, path)) - - # upload a single file - elif os.path.isfile(path): - fullpath = os.path.abspath(path) - key_name = get_key_name(fullpath, prefix, key_prefix) - files_to_check_for_upload.append(fullpath) - existing_keys_to_check_against.append(key_name) - - # we are trying to upload something unknown - else: - print("I don't know what %s is, so i can't upload it" % path) - - for fullpath in files_to_check_for_upload: - key_name = get_key_name(fullpath, prefix, key_prefix) - - if no_overwrite and key_name in existing_keys_to_check_against: - if b.get_key(key_name): - if not quiet: - print('Skipping %s as it exists in s3' % fullpath) - continue - - if not quiet: - print('Copying %s to %s/%s' % (fullpath, bucket_name, key_name)) - - if not no_op: - # 0-byte files don't work and also don't need multipart upload - if os.stat(fullpath).st_size != 0 and multipart_capable and \ - multipart_requested: - multipart_upload(bucket_name, aws_access_key_id, - aws_secret_access_key, fullpath, key_name, - reduced, debug, cb, num_cb, - grant or 'private', headers, - region=region or DEFAULT_REGION) - else: - singlepart_upload(b, key_name, fullpath, cb=cb, num_cb=num_cb, - policy=grant, reduced_redundancy=reduced, - headers=headers) - -if __name__ == "__main__": - main() diff --git a/Tools/build/JenkinsScripts/distribution/update_version_strings.py b/Tools/build/JenkinsScripts/distribution/update_version_strings.py deleted file mode 100755 index a546cb172a..0000000000 --- a/Tools/build/JenkinsScripts/distribution/update_version_strings.py +++ /dev/null @@ -1,66 +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. -""" - -import argparse -import datetime -import os -import re -import shutil -import stat -import sys - -# Files requiring embedded version string -waf_default_settings = "./dev/_WAF_/default_settings.json" - -def update_version_strings(args): - current_version = fetch_current_version(args) - print 'Storing version: ' + current_version +" to " + waf_default_settings - - # preserve the developer's work and make it re-runnable - suffix = datetime.datetime.now().strftime("%y%m%d_%H%M%S") - tempfn = waf_default_settings + '-' + suffix - - shutil.move(waf_default_settings,tempfn) #preserve file attribs with move not copy - shutil.copyfile( tempfn, waf_default_settings) # make a writable copy for ourselves - print 'Original json settings saved to ' + tempfn - - with open( waf_default_settings, "r+" ) as file: - fc = file.read() # currently default_settings.json is small enough to slurp - fc = re.sub( r'(\"Build\s+Options"\s*:\s*\[[^\]]+\"default_value.+\")((\d+\.){2,4}\d+)\"', r'\g<1>' + current_version + '"', fc, flags=re.IGNORECASE|re.MULTILINE ) - file.seek( 0 ) # empty the file at byte 0 - file.truncate() - file.write( fc ) - return - -def fetch_current_version(args): - changelist_number = int(args.changelist_number) - # Below is how Lumberyard fits a changelist > 64K into a windows compatible version string that maxes out at 64K - upper_word = (changelist_number >> 16) & 0xFFFF - lower_word = changelist_number & 0xFFFF - return (args.major + '.' + args.minor + '.' + str(upper_word) + '.' + str(lower_word)) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('changelist_number', help='changelist number to embed into dlls') - parser.add_argument('major', help='major version number') - parser.add_argument('minor', help='minor version number') - args = parser.parse_args() - # Inability to set the version string is a warning not an error. Do not stop the build. - try: - update_version_strings(args) - except: - print "FATAL ERROR: Unable to set version string in " + waf_user_settings + ": check for file not found, not writable, or version= option not found" - sys.exit(1) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/web/.htaccess b/Tools/build/JenkinsScripts/distribution/web/.htaccess deleted file mode 100644 index bccb71a302..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ -Authtype Basic -AuthName "Lumberyard HTML authentication" -AuthUserFile /var/www/html/lybuilds/.htpasswd -Require valid-user - diff --git a/Tools/build/JenkinsScripts/distribution/web/.htpasswd b/Tools/build/JenkinsScripts/distribution/web/.htpasswd deleted file mode 100644 index 608e04cdd5..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/.htpasswd +++ /dev/null @@ -1 +0,0 @@ -lumbery:$apr1$Kuzti5tP$EDIIG5pMBni0lNkxLI3F6/ diff --git a/Tools/build/JenkinsScripts/distribution/web/config.php b/Tools/build/JenkinsScripts/distribution/web/config.php deleted file mode 100644 index f6f45ff2ae..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/config.php +++ /dev/null @@ -1,10 +0,0 @@ - 'pogchamp', - 'expiry' => '60', - 'sql_username' => 'lumbery', - 'sql_pass' => 'Builder99', - 'sql_database_name' => 'lybuilds', - 'sql_host' => 'localhost' - ); -?> diff --git a/Tools/build/JenkinsScripts/distribution/web/css/fetch.css b/Tools/build/JenkinsScripts/distribution/web/css/fetch.css deleted file mode 100644 index 349b78292d..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/css/fetch.css +++ /dev/null @@ -1,56 +0,0 @@ -#nicelist { - width: 250px; -} - -#content { - width: 800px; - margin-left: auto; - margin-right: auto; - margin-top:30px; -} - -h2 { - font: 400 40px/1.5 Helvetica, Verdana, sans-serif; - margin: 0; - padding: 0; -} - -h3 { - font: 200 20px/1.5 Lucida Grande, Verdana, sans-serif; - margin: 0; - padding: 0; -} - -ul { - list-style-type: none; - margin: 0; - padding: 0; -} - -li { - font: 200 20px/1.5 Helvetica, Verdana, sans-serif; - border-bottom: 1px solid #ccc; -} - -li:last-child { - border: none; -} - -li a { - text-decoration: none; - color: #6ca4c8; - display: block; - width: 400px; - - -webkit-transition: font-size 0.3s ease, background-color 0.3s ease; - -moz-transition: font-size 0.3s ease, background-color 0.3s ease; - -o-transition: font-size 0.3s ease, background-color 0.3s ease; - -ms-transition: font-size 0.3s ease, background-color 0.3s ease; - transition: font-size 0.3s ease, background-color 0.3s ease; -} - -li a:hover { - font-size: 30px; - background: #f6f6f6; -} - \ No newline at end of file diff --git a/Tools/build/JenkinsScripts/distribution/web/css/kappa.css b/Tools/build/JenkinsScripts/distribution/web/css/kappa.css deleted file mode 100644 index c5414e75c7..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/css/kappa.css +++ /dev/null @@ -1,154 +0,0 @@ -/* - * * Copyright (c) 2012-2013 Thibaut Courouble - * * http://www.cssflow.com - * * - * * Licensed under the MIT License: - * * http://www.opensource.org/licenses/mit-license.php - * */ - -body { - font: 13px/20px 'Lucida Grande', Tahoma, Verdana, sans-serif; - color: #404040; -} - -.container { - margin: 80px auto; - width: 640px; -} - -.login { - position: relative; - margin: 0 auto; - padding: 20px 20px 20px; - width: 310px; - background: white; - border-radius: 3px; - @include box-shadow(0 0 200px rgba(white, .5), 0 1px 2px rgba(black, .3)); - - &:before { - content: ''; - position: absolute; - top: -8px; right: -8px; bottom: -8px; left: -8px; - z-index: -1; - background: rgba(black, .08); - border-radius: 4px; - } - - h1 { - margin: -20px -20px 21px; - line-height: 40px; - font-size: 15px; - font-weight: bold; - color: #555; - text-align: center; - text-shadow: 0 1px white; - background: #f3f3f3; - border-bottom: 1px solid #cfcfcf; - border-radius: 3px 3px 0 0; - @include linear-gradient(top, whiteffd, #eef2f5); - @include box-shadow(0 1px #f5f5f5); - } - - p { margin: 20px 0 0; } - p:first-child { margin-top: 0; } - - input[type=text], input[type=password] { width: 278px; } - - p.remember_me { - float: left; - line-height: 31px; - - label { - font-size: 12px; - color: #777; - cursor: pointer; - } - - input { - position: relative; - bottom: 1px; - margin-right: 4px; - vertical-align: middle; - } - } - - p.submit { text-align: right; } -} - -.login-help { - margin: 20px 0; - font-size: 11px; - color: white; - text-align: center; - text-shadow: 0 1px #2a85a1; - - a { - color: #cce7fa; - text-decoration: none; - - &:hover { text-decoration: underline; } - } -} - -:-moz-placeholder { - color: #c9c9c9 !important; - font-size: 13px; -} - -::-webkit-input-placeholder { - color: #ccc; - font-size: 13px; -} - -input { - font-family: 'Lucida Grande', Tahoma, Verdana, sans-serif; - font-size: 14px; -} - -input[type=text], input[type=password] { - margin: 5px; - padding: 0 10px; - width: 200px; - height: 34px; - color: #404040; - background: white; - border: 1px solid; - border-color: #c4c4c4 #d1d1d1 #d4d4d4; - border-radius: 2px; - outline: 5px solid #eff4f7; - -moz-outline-radius: 3px; // Can we get this on WebKit please? - @include box-shadow(inset 0 1px 3px rgba(black, .12)); - - &:focus { - border-color: #7dc9e2; - outline-color: #dceefc; - outline-offset: 0; // WebKit sets this to -1 by default - } -} - -input[type=submit] { - padding: 0 18px; - height: 29px; - font-size: 12px; - font-weight: bold; - color: #527881; - text-shadow: 0 1px #e3f1f1; - background: #cde5ef; - border: 1px solid; - border-color: #b4ccce #b3c0c8 #9eb9c2; - border-radius: 16px; - outline: 0; - @include box-sizing(content-box); // Firefox sets this to border-box by default - @include linear-gradient(top, #edf5f8, #cde5ef); - @include box-shadow(inset 0 1px white, 0 1px 2px rgba(black, .15)); - - &:active { - background: #cde5ef; - border-color: #9eb9c2 #b3c0c8 #b4ccce; - @include box-shadow(inset 0 0 3px rgba(black, .2)); - } -} - -.lt-ie9 { - input[type=text], input[type=password] { line-height: 34px; } -} diff --git a/Tools/build/JenkinsScripts/distribution/web/css/style.css b/Tools/build/JenkinsScripts/distribution/web/css/style.css deleted file mode 100644 index b2774d6d49..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/css/style.css +++ /dev/null @@ -1,208 +0,0 @@ -/*----------------------------------------------------------------------------- -| Main HTML page Classes --------------------------------------------------------------------------------*/ -.clear:after { - clear: both; - content: ""; - display: block; -} -html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { - padding: 0px; - border: 0px; - border-collapse: separate; - border-spacing: 0px; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - text-decoration: none; - left: auto; -} -html, body { - height: 100%; - width: 100%; - margin: 0px; -} -::-moz-selection{ color: #fff; background: #707070; } -::selection { color: #fff; background: #707070; } -body { - font-family: Helvetica, Arial, sans-serif; - font-size: 12px; - line-height: 17px; - color: #676767; - background: repeat 0 0 #ffffff; -} - -a { - -webkit-transition:all 0.14s ease 0s; - -moz-transition:all 0.14s ease 0s; - -o-transition:all 0.14s ease 0s; - outline:none; -} -a:hover { - color: #444; -} -.title, .title a { - text-decoration: none; -} -.title a:hover { -} -img, iframe { - float: none; - position: static; -} -.alignleft { - float:left; - margin: 10px 20px 10px 0; -} -.alignright { - float:right; - margin: 10px 0 10px 20px; -} -.aligncenter { - display: block; - margin: 10px auto 10px auto; -} -.text-align-right { - text-align: right; -} -.text-align-left { - text-align: left; -} -.text-align-center { - text-align: center; -} -.divider { - float: left; - width: 100%; - height: 70px; -} -.divider-border { - border-top: 2px solid #eee; - float: left; - width: 100%; - margin: 40px 0; -} -/*-------------------------------------------------- - MAIN CONTENT ----------------------------------------------------*/ -#wrapper { - width: 100%; - background-color: transparent; -} -.content-wrapper { - width: 960px; - margin: 0 auto; - padding: 0 0; - border-bottom-width: 0px; - border-top: 0px solid #eee; - box-shadow: none; - border-right-width: 0px; - border-left-width: 0px; - background-color: transparent; - padding-bottom: 20px; -} -#header-wrapper { -} -.header { - width: 960px; - padding: 0; - margin: 0; - position:relative; - border-bottom: 2px solid #eee; -} -#contact-fullwidth.header { - border-bottom: none; - margin: 0 auto; -} -#logo { - margin-top: 35px; -} -#logo, #logo a { - float: left; -} -#logo a { -} - -/*---------------------------------------------------------------- - FONTS ------------------------------------------------------------------*/ -.menubar_font { - font-size: 18px; - color: white; - font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif; -} - -.menubar_subfont { - font-size: 18px; - color: white; - font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif; -} - -.header_font_01 { - font-size: 24px; - color: black; - text-align: center; - font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif; -} - -.title_font { - font-size: 40px; - color: black; - font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif; - margin-left: 100px; - float: left; -} - -.sidebar_text { - font-size: 12px; - color: black; - font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif; - text-align: left; -} - -/*---------------------------------------------------------------- - IMAGES ------------------------------------------------------------------*/ -.graph_image { - text-align: center; -} - - -/*---------------------------------------------------------------- - OTHER STUFF ------------------------------------------------------------------*/ -/*-----Side Bar Styles-----*/ -.sidebar_backdrop { - box-shadow: black 0.2em 0.2em 0.1em; - background-color: #ff9933; - padding: 5px 5px 5px 5px; - -} - -.sidebar_column { - vertical-align: top; - padding-right: 5px; - -} - -.sidebar_column p:hover { - background: #E65C00; - padding: 5px 5px 5px 5px; -} - -.main_table { - margin-left: auto; - margin-right: auto; -} - -.main_banners { - text-align: center; -} - -.main_banners img { - transition: transform 0.1s ease; -} - -.main_banners img:hover { - transform: scale(0.97); -} diff --git a/Tools/build/JenkinsScripts/distribution/web/fetch_files.php b/Tools/build/JenkinsScripts/distribution/web/fetch_files.php deleted file mode 100644 index f98c90a68b..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/fetch_files.php +++ /dev/null @@ -1,49 +0,0 @@ - - - Lumberyard Distribution Portal - - - - -\n"; - echo "

Lumberyard Secure File Distribution

\n"; - echo "
\n"; - echo "
    \n"; - foreach ($result as $key => $jsons) { - $parts = explode('/', rtrim($key, '/')); - echo "
  • " . $parts[3] . "
  • \n"; - } - echo "
\n"; - echo "
\n"; - echo "\n"; - - mysql_close($connection); -?> - - diff --git a/Tools/build/JenkinsScripts/distribution/web/images/Favicon.ico b/Tools/build/JenkinsScripts/distribution/web/images/Favicon.ico deleted file mode 100644 index aad996e191..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/images/Favicon.ico +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d75a3785f8422d67887e5501cc9e1261f2e15bf3464f8b40299014faff0ee0ef -size 16958 diff --git a/Tools/build/JenkinsScripts/distribution/web/index.html b/Tools/build/JenkinsScripts/distribution/web/index.html deleted file mode 100644 index 0d3fb3979a..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - Lumberyard Distribution Portal - - - - - -
- - -
- - - - diff --git a/Tools/build/JenkinsScripts/distribution/web/index.php b/Tools/build/JenkinsScripts/distribution/web/index.php deleted file mode 100644 index c5afb6392c..0000000000 --- a/Tools/build/JenkinsScripts/distribution/web/index.php +++ /dev/null @@ -1,59 +0,0 @@ - - - Lumberyard Distribution Portal - - - - - -\n"; - echo " \n"; - echo " \n"; - echo "

Lumberyard Secure File Distribution

\n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo "

Bucket: " . $bucket . "

\n"; - echo "

Link will expire on: " . date('Y:m:d H:i:s', time() + $expiry) . "

\n"; - echo " \n"; - echo " \n"; - echo "

\n"; - echo "

Available Files:

\n"; - echo " \n"; - echo " \n"; - foreach ($result as $key => $jsons) { - echo " \n"; - } -?> - - - - - diff --git a/python/get_python.bat b/python/get_python.bat index bde19e4eb3..e9f18441b5 100644 --- a/python/get_python.bat +++ b/python/get_python.bat @@ -30,7 +30,7 @@ IF !ERRORLEVEL!==0 ( ) cd /D %CMD_DIR%\.. -REM IF you update this logic, update it in Tools/build/JenkinsScripts/build/Platform/Windows/env_windows.cmd +REM IF you update this logic, update it in scripts/build/Platform/Windows/env_windows.cmd REM If cmake is not found on path, try a known location, using LY_CMAKE_PATH as the first fallback where /Q cmake IF NOT !ERRORLEVEL!==0 ( diff --git a/python/get_python.sh b/python/get_python.sh index 509cd9ef94..780f1bbdd8 100755 --- a/python/get_python.sh +++ b/python/get_python.sh @@ -27,7 +27,7 @@ cd $DIR # the version number below is only used if cmake isn't already on your path. # if you update this version number, remember to update the one(s) in the other platform -# files, as well as in Tools/build/Jenkins/... +# files, as well as in scripts/build/... ./python.sh --version > /dev/null python_exitcode=$? @@ -55,9 +55,9 @@ if ! [ -x "$(command -v cmake)" ]; then fi LY_CMAKE_PATH=$LY_3RDPARTY_PATH/CMake/3.19.1/$PAL/$CMAKE_FOLDER_RELATIVE_TO_ROOT # if you change the version number, change it also in: - # Tools/build/JenkinsScripts/build/Platform/Mac/env_mac.sh + # scripts/build/Platform/Mac/env_mac.sh # and - # Tools/build/JenkinsScripts/build/Platform/Linux/env_linux.sh + # scripts/build/Platform/Linux/env_linux.sh fi export PATH=$LY_CMAKE_PATH:$PATH diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index d313cc40ea..21f3411e8c 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -201,7 +201,7 @@ def CheckoutBootstrapScripts(String branchName) { sparseCheckoutPaths: [ [ $class: "SparseCheckoutPath", path: "scripts/build/Jenkins/" ], [ $class: "SparseCheckoutPath", path: "scripts/build/bootstrap/" ], - [ $class: "SparseCheckoutPath", path: "Tools/build/JenkinsScripts/build/Platform" ] + [ $class: "SparseCheckoutPath", path: "scripts/build/Platform" ] ] ], [ diff --git a/scripts/build/Jenkins/lumberyard.json b/scripts/build/Jenkins/lumberyard.json index a174b7b449..3468409d2a 100644 --- a/scripts/build/Jenkins/lumberyard.json +++ b/scripts/build/Jenkins/lumberyard.json @@ -1,12 +1,12 @@ { - "BUILD_ENTRY_POINT": "Tools/build/JenkinsScripts/build/ci_build.py", + "BUILD_ENTRY_POINT": "scripts/build/ci_build.py", "PIPELINE_CONFIGS": [ - "Tools/build/JenkinsScripts/build/Platform/*/pipeline.json", - "restricted/*/Tools/build/JenkinsScripts/build/pipeline.json" + "scripts/build/Platform/*/pipeline.json", + "restricted/*/scripts/build/pipeline.json" ], "BUILD_CONFIGS": [ - "Tools/build/JenkinsScripts/build/Platform/*/build_config.json", - "restricted/*/Tools/build/JenkinsScripts/build/build_config.json" + "scripts/build/Platform/*/build_config.json", + "restricted/*/scripts/build/build_config.json" ], "PYTHON_DIR": "python" } diff --git a/Tools/build/JenkinsScripts/build/Platform/Android/build_and_run_unit_tests.cmd b/scripts/build/Platform/Android/build_and_run_unit_tests.cmd similarity index 74% rename from Tools/build/JenkinsScripts/build/Platform/Android/build_and_run_unit_tests.cmd rename to scripts/build/Platform/Android/build_and_run_unit_tests.cmd index 7e2372cd60..fbb31f95ec 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Android/build_and_run_unit_tests.cmd +++ b/scripts/build/Platform/Android/build_and_run_unit_tests.cmd @@ -30,8 +30,8 @@ IF NOT EXIST "%LY_ANDROID_SDK%" ( SET ANDROID_SDK_ROOT=%LY_ANDROID_SDK% ECHO "ANDROID_SDK_ROOT=!ANDROID_SDK_ROOT!" SET PYTHON=python\python.cmd -ECHO [ci_build] %PYTHON% Tools\build\JenkinsScripts\build\Platform\Android\run_test_on_android_simulator.py --android-sdk-path %LY_ANDROID_SDK% --build-path %OUTPUT_DIRECTORY% --build-config %CONFIGURATION% -CALL %PYTHON% Tools\build\JenkinsScripts\build\Platform\Android\run_test_on_android_simulator.py --android-sdk-path %LY_ANDROID_SDK% --build-path %OUTPUT_DIRECTORY% --build-config %CONFIGURATION% +ECHO [ci_build] %PYTHON% scripts\build\Platform\Android\run_test_on_android_simulator.py --android-sdk-path %LY_ANDROID_SDK% --build-path %OUTPUT_DIRECTORY% --build-config %CONFIGURATION% +CALL %PYTHON% scripts\build\Platform\Android\run_test_on_android_simulator.py --android-sdk-path %LY_ANDROID_SDK% --build-path %OUTPUT_DIRECTORY% --build-config %CONFIGURATION% IF NOT %ERRORLEVEL%==0 GOTO :popd_error EXIT /b 0 diff --git a/Tools/build/JenkinsScripts/build/Platform/Android/build_config.json b/scripts/build/Platform/Android/build_config.json similarity index 98% rename from Tools/build/JenkinsScripts/build/Platform/Android/build_config.json rename to scripts/build/Platform/Android/build_config.json index 2b10e8b26b..e5b41973e0 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Android/build_config.json +++ b/scripts/build/Platform/Android/build_config.json @@ -21,7 +21,7 @@ ], "COMMAND":"../Windows/python_windows.cmd", "PARAMETERS": { - "SCRIPT_PATH":"Tools/build/JenkinsScripts/build/ci_build_metrics.py", + "SCRIPT_PATH":"scripts/build/ci_build_metrics.py", "SCRIPT_PARAMETERS":"--platform Android --jobname \"!JOB_NAME!\" --jobnumber \"!BUILD_NUMBER!\" --jobnode \"!NODE_NAME!\" --changelist \"!CHANGE_ID!\"" } }, diff --git a/Tools/build/JenkinsScripts/build/Platform/Android/gradle_windows.cmd b/scripts/build/Platform/Android/gradle_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Android/gradle_windows.cmd rename to scripts/build/Platform/Android/gradle_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Android/pipeline.json b/scripts/build/Platform/Android/pipeline.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Android/pipeline.json rename to scripts/build/Platform/Android/pipeline.json diff --git a/Tools/build/JenkinsScripts/build/Platform/Android/run_test_on_android_simulator.py b/scripts/build/Platform/Android/run_test_on_android_simulator.py similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Android/run_test_on_android_simulator.py rename to scripts/build/Platform/Android/run_test_on_android_simulator.py diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/asset_linux.sh b/scripts/build/Platform/Linux/asset_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/asset_linux.sh rename to scripts/build/Platform/Linux/asset_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/build_asset_linux.sh b/scripts/build/Platform/Linux/build_asset_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/build_asset_linux.sh rename to scripts/build/Platform/Linux/build_asset_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json b/scripts/build/Platform/Linux/build_config.json similarity index 98% rename from Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json rename to scripts/build/Platform/Linux/build_config.json index a1676902f9..d7f5ddc9d0 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Linux/build_config.json +++ b/scripts/build/Platform/Linux/build_config.json @@ -23,7 +23,7 @@ ], "COMMAND": "python_linux.sh", "PARAMETERS": { - "SCRIPT_PATH": "Tools/build/JenkinsScripts/build/ci_build_metrics.py", + "SCRIPT_PATH": "scripts/build/ci_build_metrics.py", "SCRIPT_PARAMETERS": "--platform Linux --jobname '${JOB_NAME}' --jobnumber '${BUILD_NUMBER}' --jobnode '${NODE_NAME}' --changelist '${CHANGE_ID}'" } }, diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/build_linux.sh b/scripts/build/Platform/Linux/build_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/build_linux.sh rename to scripts/build/Platform/Linux/build_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/build_test_linux.sh b/scripts/build/Platform/Linux/build_test_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/build_test_linux.sh rename to scripts/build/Platform/Linux/build_test_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/clean_linux.sh b/scripts/build/Platform/Linux/clean_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/clean_linux.sh rename to scripts/build/Platform/Linux/clean_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/env_linux.sh b/scripts/build/Platform/Linux/env_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/env_linux.sh rename to scripts/build/Platform/Linux/env_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/pipeline.json b/scripts/build/Platform/Linux/pipeline.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/pipeline.json rename to scripts/build/Platform/Linux/pipeline.json diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/python_linux.sh b/scripts/build/Platform/Linux/python_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/python_linux.sh rename to scripts/build/Platform/Linux/python_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Linux/test_linux.sh b/scripts/build/Platform/Linux/test_linux.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Linux/test_linux.sh rename to scripts/build/Platform/Linux/test_linux.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/asset_mac.sh b/scripts/build/Platform/Mac/asset_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/asset_mac.sh rename to scripts/build/Platform/Mac/asset_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/build_asset_mac.sh b/scripts/build/Platform/Mac/build_asset_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/build_asset_mac.sh rename to scripts/build/Platform/Mac/build_asset_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json b/scripts/build/Platform/Mac/build_config.json similarity index 98% rename from Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json rename to scripts/build/Platform/Mac/build_config.json index e7e1193062..f816117331 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Mac/build_config.json +++ b/scripts/build/Platform/Mac/build_config.json @@ -22,7 +22,7 @@ ], "COMMAND": "python_mac.sh", "PARAMETERS": { - "SCRIPT_PATH": "Tools/build/JenkinsScripts/build/ci_build_metrics.py", + "SCRIPT_PATH": "scripts/build/ci_build_metrics.py", "SCRIPT_PARAMETERS": "--platform Mac --jobname '${JOB_NAME}' --jobnumber '${BUILD_NUMBER}' --jobnode '${NODE_NAME}' --changelist '${CHANGE_ID}'" } }, diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/build_mac.sh b/scripts/build/Platform/Mac/build_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/build_mac.sh rename to scripts/build/Platform/Mac/build_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/build_test_mac.sh b/scripts/build/Platform/Mac/build_test_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/build_test_mac.sh rename to scripts/build/Platform/Mac/build_test_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/clean_mac.sh b/scripts/build/Platform/Mac/clean_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/clean_mac.sh rename to scripts/build/Platform/Mac/clean_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/env_mac.sh b/scripts/build/Platform/Mac/env_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/env_mac.sh rename to scripts/build/Platform/Mac/env_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/pipeline.json b/scripts/build/Platform/Mac/pipeline.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/pipeline.json rename to scripts/build/Platform/Mac/pipeline.json diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/python_mac.sh b/scripts/build/Platform/Mac/python_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/python_mac.sh rename to scripts/build/Platform/Mac/python_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Mac/test_mac.sh b/scripts/build/Platform/Mac/test_mac.sh similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Mac/test_mac.sh rename to scripts/build/Platform/Mac/test_mac.sh diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/asset_windows.cmd b/scripts/build/Platform/Windows/asset_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/asset_windows.cmd rename to scripts/build/Platform/Windows/asset_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/build_asset_windows.cmd b/scripts/build/Platform/Windows/build_asset_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/build_asset_windows.cmd rename to scripts/build/Platform/Windows/build_asset_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json similarity index 98% rename from Tools/build/JenkinsScripts/build/Platform/Windows/build_config.json rename to scripts/build/Platform/Windows/build_config.json index 0ccdf2234b..a1290a254f 100644 --- a/Tools/build/JenkinsScripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -38,7 +38,7 @@ "TAGS": [], "COMMAND": "python_windows.cmd", "PARAMETERS": { - "SCRIPT_PATH": "Tools/build/JenkinsScripts/build/scrubbing_job.py" + "SCRIPT_PATH": "scripts/build/scrubbing_job.py" } }, "validation": { @@ -54,7 +54,7 @@ ], "COMMAND": "python_windows.cmd", "PARAMETERS": { - "SCRIPT_PATH": "Tools/build/JenkinsScripts/build/ci_build_metrics.py", + "SCRIPT_PATH": "scripts/build/ci_build_metrics.py", "SCRIPT_PARAMETERS": "--platform Windows --jobname \"!JOB_NAME!\" --jobnumber \"!BUILD_NUMBER!\" --jobnode \"!NODE_NAME!\" --changelist \"!CHANGE_ID!\"" } }, diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/build_ninja_windows.cmd b/scripts/build/Platform/Windows/build_ninja_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/build_ninja_windows.cmd rename to scripts/build/Platform/Windows/build_ninja_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/build_test_windows.cmd b/scripts/build/Platform/Windows/build_test_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/build_test_windows.cmd rename to scripts/build/Platform/Windows/build_test_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/build_windows.cmd b/scripts/build/Platform/Windows/build_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/build_windows.cmd rename to scripts/build/Platform/Windows/build_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/clean_windows.cmd b/scripts/build/Platform/Windows/clean_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/clean_windows.cmd rename to scripts/build/Platform/Windows/clean_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/env_windows.cmd b/scripts/build/Platform/Windows/env_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/env_windows.cmd rename to scripts/build/Platform/Windows/env_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/package_build_config.json b/scripts/build/Platform/Windows/package_build_config.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/package_build_config.json rename to scripts/build/Platform/Windows/package_build_config.json diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/pipeline.json b/scripts/build/Platform/Windows/pipeline.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/pipeline.json rename to scripts/build/Platform/Windows/pipeline.json diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/python_windows.cmd b/scripts/build/Platform/Windows/python_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/python_windows.cmd rename to scripts/build/Platform/Windows/python_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/Windows/test_windows.cmd b/scripts/build/Platform/Windows/test_windows.cmd similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/Windows/test_windows.cmd rename to scripts/build/Platform/Windows/test_windows.cmd diff --git a/Tools/build/JenkinsScripts/build/Platform/iOS/build_config.json b/scripts/build/Platform/iOS/build_config.json similarity index 98% rename from Tools/build/JenkinsScripts/build/Platform/iOS/build_config.json rename to scripts/build/Platform/iOS/build_config.json index ed465227d2..921262e267 100644 --- a/Tools/build/JenkinsScripts/build/Platform/iOS/build_config.json +++ b/scripts/build/Platform/iOS/build_config.json @@ -13,7 +13,7 @@ ], "COMMAND": "../Mac/python_mac.sh", "PARAMETERS": { - "SCRIPT_PATH": "Tools/build/JenkinsScripts/build/ci_build_metrics.py", + "SCRIPT_PATH": "scripts/build/ci_build_metrics.py", "SCRIPT_PARAMETERS": "--platform iOS --jobname '${JOB_NAME}' --jobnumber '${BUILD_NUMBER}' --jobnode '${NODE_NAME}' --changelist '${CHANGE_ID}'" } }, diff --git a/Tools/build/JenkinsScripts/build/Platform/iOS/pipeline.json b/scripts/build/Platform/iOS/pipeline.json similarity index 100% rename from Tools/build/JenkinsScripts/build/Platform/iOS/pipeline.json rename to scripts/build/Platform/iOS/pipeline.json diff --git a/Tools/build/JenkinsScripts/build/ci_build.py b/scripts/build/ci_build.py similarity index 98% rename from Tools/build/JenkinsScripts/build/ci_build.py rename to scripts/build/ci_build.py index bb656945f6..5d5df46361 100755 --- a/Tools/build/JenkinsScripts/build/ci_build.py +++ b/scripts/build/ci_build.py @@ -39,7 +39,7 @@ def parse_args(): def build(build_config_filename, build_platform, build_type): # Read build_config and locate build_type current_dir = os.path.dirname(os.path.abspath(__file__)) - cwd_dir = os.path.abspath(os.path.join(current_dir, '../../../..')) # engine's root + cwd_dir = os.path.abspath(os.path.join(current_dir, '../..')) # engine's root config_dir = os.path.abspath(os.path.join(current_dir, 'Platform', build_platform)) build_config_abspath = os.path.join(config_dir, build_config_filename) if not os.path.exists(build_config_abspath): diff --git a/Tools/build/JenkinsScripts/build/ci_build_metrics.py b/scripts/build/ci_build_metrics.py similarity index 99% rename from Tools/build/JenkinsScripts/build/ci_build_metrics.py rename to scripts/build/ci_build_metrics.py index b140afff9e..b732429948 100755 --- a/Tools/build/JenkinsScripts/build/ci_build_metrics.py +++ b/scripts/build/ci_build_metrics.py @@ -114,7 +114,7 @@ def gather_build_metrics(current_dir, build_config_filename, platform): config_dir = os.path.abspath(os.path.join(current_dir, 'Platform', platform)) build_config_abspath = os.path.join(config_dir, build_config_filename) if not os.path.exists(build_config_abspath): - cwd_dir = os.path.abspath(os.path.join(current_dir, '../../../..')) # engine's root + cwd_dir = os.path.abspath(os.path.join(current_dir, '../..')) # engine's root config_dir = os.path.abspath(os.path.join(cwd_dir, 'restricted', platform, os.path.relpath(current_dir, cwd_dir))) build_config_abspath = os.path.join(config_dir, build_config_filename) @@ -268,7 +268,7 @@ if __name__ == "__main__": # Read build_config current_dir = os.path.dirname(os.path.abspath(__file__)) - engine_dir = os.path.abspath(os.path.join(current_dir, '../../../..')) # engine's root + engine_dir = os.path.abspath(os.path.join(current_dir, '../..')) # engine's root timestamp = datetime.datetime.now() build_metrics = gather_build_metrics(current_dir, args.build_config_filename, args.platform) @@ -290,7 +290,7 @@ if __name__ == "__main__": json.dump(metrics, metric_file, sort_keys=True, indent=4) # transfer - upload_script = os.path.join(current_dir, 'utils', 'upload_to_s3.py') + upload_script = os.path.join(current_dir, 'tools', 'upload_to_s3.py') upload_to_s3(upload_script, os.path.join(engine_dir, 'build_metrics'), 'ly-jenkins-cmake-metrics', args.jobname) # submit diff --git a/scripts/build/package/package.py b/scripts/build/package/package.py index 9225264a75..96b39f0753 100755 --- a/scripts/build/package/package.py +++ b/scripts/build/package/package.py @@ -16,7 +16,7 @@ import progressbar from optparse import OptionParser from PackageEnv import PackageEnv cur_dir = cur_dir = os.path.dirname(os.path.abspath(__file__)) -sys.path.insert(0, f'{cur_dir}/../../../Tools/build/JenkinsScripts/build') +sys.path.insert(0, f'{cur_dir}/..') from ci_build import build from util import * from glob3 import glob diff --git a/Tools/build/JenkinsScripts/build/submit_metrics.py b/scripts/build/submit_metrics.py similarity index 100% rename from Tools/build/JenkinsScripts/build/submit_metrics.py rename to scripts/build/submit_metrics.py diff --git a/Tools/build/JenkinsScripts/distribution/scrubbing/canary.txt b/scripts/scrubbing/canary.txt similarity index 100% rename from Tools/build/JenkinsScripts/distribution/scrubbing/canary.txt rename to scripts/scrubbing/canary.txt diff --git a/Tools/build/JenkinsScripts/build/scrubbing_job.py b/scripts/scrubbing/scrubbing_job.py similarity index 78% rename from Tools/build/JenkinsScripts/build/scrubbing_job.py rename to scripts/scrubbing/scrubbing_job.py index 6c5ca16c91..6ffffb512b 100755 --- a/Tools/build/JenkinsScripts/build/scrubbing_job.py +++ b/scripts/scrubbing/scrubbing_job.py @@ -9,22 +9,24 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -import utils.util import os import sys +cur_dir = cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.abspath(f'{cur_dir}/../build/package')) +import util # Run validator success = True -validator_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../distribution/scrubbing/validator.py') -engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))) +validator_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'validator.py') +engine_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) if sys.platform == 'win32': python = os.path.join(engine_root, 'python', 'python.cmd') else: python = os.path.join(engine_root, 'python', 'python.sh') args = [python, validator_path, '--package_platform', 'Windows', '--package_type', 'all', engine_root] -return_code = utils.util.safe_execute_system_call(args) +return_code = util.safe_execute_system_call(args) if return_code != 0: success = False if not success: - utils.util.error('Restricted file validator failed.') + util.error('Restricted file validator failed.') print('Restricted file validator completed successfully.') diff --git a/Tools/build/JenkinsScripts/distribution/scrubbing/validator.py b/scripts/scrubbing/validator.py similarity index 99% rename from Tools/build/JenkinsScripts/distribution/scrubbing/validator.py rename to scripts/scrubbing/validator.py index c71aab770c..e442e443c8 100755 --- a/Tools/build/JenkinsScripts/distribution/scrubbing/validator.py +++ b/scripts/scrubbing/validator.py @@ -32,7 +32,7 @@ else: from io import StringIO import validator_data_LEGAL_REVIEW_REQUIRED # pull in the data we need to configure this tool -sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', '..', '..', 'scripts', 'build', 'package')) +sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'build', 'package')) from glob_to_regex import generate_include_exclude_regexes class Validator(object): diff --git a/Tools/build/JenkinsScripts/distribution/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py b/scripts/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py similarity index 87% rename from Tools/build/JenkinsScripts/distribution/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py rename to scripts/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py index 2ee975583f..1299ef67fe 100755 --- a/Tools/build/JenkinsScripts/distribution/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py +++ b/scripts/scrubbing/validator_data_LEGAL_REVIEW_REQUIRED.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# Anyone seeking to modify this file must follow the process on this wiki: https://wiki.agscollab.com/display/lmbr/Modifying+validator_data.py+File +# Anyone seeking to modify this file must follow the process, contact sig-build # Notice that this is not a JSON file, even though it is almost a valid JSON # data file. @@ -44,15 +44,17 @@ restricted_platforms = {} def find_restricted_platforms(): this_path = Path(__file__).resolve() - root_folder = this_path.parents[5] + root_folder = this_path.parents[2] relative_path = os.path.relpath(this_path.parent, root_folder) - for dir in [f.path for f in os.scandir(os.path.join(root_folder, 'restricted')) if f.is_dir()]: - sys.path.append(os.path.join(dir, relative_path)) - try: - module = __import__('{}_data_LEGAL_REVIEW_REQUIRED'.format(os.path.basename(dir).lower()), locals(), globals()) - module.add_restricted_platform(restricted_platforms) - except ModuleNotFoundError: - pass + restricted_path = os.path.join(root_folder, 'restricted') + if os.path.exists(restricted_path): + for dir in [f.path for f in os.scandir(restricted_path) if f.is_dir()]: + sys.path.append(os.path.join(dir, relative_path)) + try: + module = __import__('{}_data_LEGAL_REVIEW_REQUIRED'.format(os.path.basename(dir).lower()), locals(), globals()) + module.add_restricted_platform(restricted_platforms) + except ModuleNotFoundError: + pass find_restricted_platforms() From a1f0baeefffb280064ad46568580410715fcbc49 Mon Sep 17 00:00:00 2001 From: Brian Herrera Date: Wed, 14 Apr 2021 14:43:01 -0700 Subject: [PATCH 047/122] Prevent skipping build if it's from a pull request Also add safe navigation operator on parameters. This avoids encoutering NullPointerException when accessing build parameters on the first build since these values will be set to null. --- scripts/build/Jenkins/Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 21f3411e8c..177ac5199d 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -270,7 +270,7 @@ def PreBuildCommonSteps(Map pipelineConfig, String projectName, String pipeline, if(env.IS_UNIX) pythonCmd = 'sudo -E python -u ' else pythonCmd = 'python -u ' - if(env.RECREATE_VOLUME.toBoolean()) { + if(env.RECREATE_VOLUME?.toBoolean()) { palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action delete --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Deleting volume') } timeout(5) { @@ -291,7 +291,7 @@ def PreBuildCommonSteps(Map pipelineConfig, String projectName, String pipeline, // Cleanup previous repo location, we are currently at the root of the workspace, if we have a .git folder // we need to cleanup. Once all branches take this relocation, we can remove this - if(env.CLEAN_WORKSPACE.toBoolean() || fileExists("${workspace}/.git")) { + if(env.CLEAN_WORKSPACE?.toBoolean() || fileExists("${workspace}/.git")) { if(fileExists(workspace)) { palRmDir(workspace) } @@ -315,7 +315,7 @@ def PreBuildCommonSteps(Map pipelineConfig, String projectName, String pipeline, script: 'python/get_python.bat' } - if(env.CLEAN_OUTPUT_DIRECTORY.toBoolean() || env.CLEAN_ASSETS.toBoolean()) { + if(env.CLEAN_OUTPUT_DIRECTORY?.toBoolean() || env.CLEAN_ASSETS?.toBoolean()) { def command = "${pipelineConfig.BUILD_ENTRY_POINT} --platform ${platform} --type clean" if (env.IS_UNIX) { sh label: "Running ${platform} clean", @@ -457,7 +457,7 @@ try { } } - if(env.BUILD_NUMBER == '1') { + if(env.BUILD_NUMBER == '1' && !branchName.startsWith('PR-')) { // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 currentBuild.result = 'SUCCESS' From 7609248c49e947a79fb3f391481109dde8935b07 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 14 Apr 2021 15:42:24 -0700 Subject: [PATCH 048/122] Fix build errors --- ..._iOS.mm => O3DEApplicationDelegate_iOS.mm} | 20 +++++++++---------- ...lication_iOS.mm => O3DEApplication_iOS.mm} | 8 ++++---- .../Platform/iOS/platform_ios_files.cmake | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) rename Code/LauncherUnified/Platform/iOS/{LumberyardApplicationDelegate_iOS.mm => O3DEApplicationDelegate_iOS.mm} (86%) rename Code/LauncherUnified/Platform/iOS/{LumberyardApplication_iOS.mm => O3DEApplication_iOS.mm} (92%) diff --git a/Code/LauncherUnified/Platform/iOS/LumberyardApplicationDelegate_iOS.mm b/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm similarity index 86% rename from Code/LauncherUnified/Platform/iOS/LumberyardApplicationDelegate_iOS.mm rename to Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm index fc589a4780..ca7ab2def0 100644 --- a/Code/LauncherUnified/Platform/iOS/LumberyardApplicationDelegate_iOS.mm +++ b/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm @@ -39,15 +39,15 @@ namespace } -@interface LumberyardApplicationDelegate_iOS : NSObject +@interface O3DEApplicationDelegate_iOS : NSObject { } -@end // LumberyardApplicationDelegate_iOS Interface +@end // O3DEApplicationDelegate_iOS Interface -@implementation LumberyardApplicationDelegate_iOS +@implementation O3DEApplicationDelegate_iOS -- (int)runLumberyardApplication +- (int)runO3DEApplication { #if AZ_TESTS_ENABLED @@ -55,7 +55,7 @@ namespace return static_cast(ReturnCode::ErrUnitTestNotSupported); #else - using namespace LumberyardLauncher; + using namespace O3DELauncher; PlatformMainInfo mainInfo; mainInfo.m_updateResourceLimits = IncreaseResourceLimits; @@ -79,19 +79,19 @@ namespace #endif // AZ_TESTS_ENABLED } -- (void)launchLumberyardApplication +- (void)launchO3DEApplication { - const int exitCode = [self runLumberyardApplication]; + const int exitCode = [self runO3DEApplication]; exit(exitCode); } - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - // prevent the lumberyard runtime from running when launched in a xctest environment, otherwise the + // prevent the o3de runtime from running when launched in a xctest environment, otherwise the // testing framework will kill the "app" due to the lengthy bootstrap process if ([[NSProcessInfo processInfo] environment][@"XCTestConfigurationFilePath"] == nil) { - [self performSelector:@selector(launchLumberyardApplication) withObject:nil afterDelay:0.0]; + [self performSelector:@selector(launchO3DEApplication) withObject:nil afterDelay:0.0]; } return YES; } @@ -132,4 +132,4 @@ namespace &AzFramework::IosLifecycleEvents::Bus::Events::OnDidReceiveMemoryWarning); } -@end // LumberyardApplicationDelegate_iOS Implementation +@end // O3DEApplicationDelegate_iOS Implementation diff --git a/Code/LauncherUnified/Platform/iOS/LumberyardApplication_iOS.mm b/Code/LauncherUnified/Platform/iOS/O3DEApplication_iOS.mm similarity index 92% rename from Code/LauncherUnified/Platform/iOS/LumberyardApplication_iOS.mm rename to Code/LauncherUnified/Platform/iOS/O3DEApplication_iOS.mm index f2fa9498d5..c76c2f69ab 100644 --- a/Code/LauncherUnified/Platform/iOS/LumberyardApplication_iOS.mm +++ b/Code/LauncherUnified/Platform/iOS/O3DEApplication_iOS.mm @@ -16,12 +16,12 @@ #include -@interface LumberyardApplication_iOS : UIApplication +@interface O3DEApplication_iOS : UIApplication { } -@end // LumberyardApplication_iOS Interface +@end // O3DEApplication_iOS Interface -@implementation LumberyardApplication_iOS +@implementation O3DEApplication_iOS - (void)touchesBegan: (NSSet*)touches withEvent: (UIEvent*)event { @@ -65,4 +65,4 @@ [self touchesEnded: touches withEvent: event]; } -@end // LumberyardApplication_iOS Implementation +@end // O3DEApplication_iOS Implementation diff --git a/Code/LauncherUnified/Platform/iOS/platform_ios_files.cmake b/Code/LauncherUnified/Platform/iOS/platform_ios_files.cmake index c1a642481f..d5711ed04c 100644 --- a/Code/LauncherUnified/Platform/iOS/platform_ios_files.cmake +++ b/Code/LauncherUnified/Platform/iOS/platform_ios_files.cmake @@ -13,8 +13,8 @@ set(FILES Launcher_iOS.mm Launcher_Traits_iOS.h Launcher_Traits_Platform.h - LumberyardApplication_iOS.mm - LumberyardApplicationDelegate_iOS.mm + O3DEApplication_iOS.mm + O3DEApplicationDelegate_iOS.mm ../Common/Apple/Launcher_Apple.mm ../Common/Apple/Launcher_Apple.h ../Common/UnixLike/Launcher_UnixLike.cpp From f7aabebb375e9bd0e4e3b1dff4661ea3827aa1ca Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 14 Apr 2021 16:56:23 -0700 Subject: [PATCH 049/122] Fix context menu popping up when it shouldn't --- Code/Sandbox/Editor/LegacyViewportCameraController.cpp | 9 +++++++++ Code/Sandbox/Editor/LegacyViewportCameraController.h | 1 + 2 files changed, 10 insertions(+) diff --git a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp index 44b722d222..7a33dff377 100644 --- a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp +++ b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp @@ -96,6 +96,11 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove( speedScale *= gSettings.cameraFastMoveSpeed; } + if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode) + { + m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength(); + } + if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode) { Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); @@ -343,11 +348,15 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra } shouldCaptureCursor = true; + // Record how much the cursor has been moved to see if we should own the mouse up event. + m_totalMouseMoveDelta = 0; } else if (state == InputChannel::State::Ended) { m_inZoomMode = false; m_inRotateMode = false; + // If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it. + shouldConsumeEvent = m_totalMouseMoveDelta > 2; shouldCaptureCursor = false; } } diff --git a/Code/Sandbox/Editor/LegacyViewportCameraController.h b/Code/Sandbox/Editor/LegacyViewportCameraController.h index 3f211f49b7..b4a36f44a5 100644 --- a/Code/Sandbox/Editor/LegacyViewportCameraController.h +++ b/Code/Sandbox/Editor/LegacyViewportCameraController.h @@ -58,6 +58,7 @@ namespace SandboxEditor bool m_inMoveMode = false; bool m_inOrbitMode = false; bool m_inZoomMode = false; + int m_totalMouseMoveDelta = 0; float m_orbitDistance = 10.f; float m_moveSpeed = 1.f; AZ::Vector3 m_orbitTarget = {}; From 8b265d2e8d73c6ebd8100a08b06606704e630e81 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 14 Apr 2021 17:38:57 -0700 Subject: [PATCH 050/122] Initial version that I need to test out (#60) LYN-2585 Add cmake/install job to Jenkins --- scripts/build/Jenkins/Jenkinsfile | 5 +++++ scripts/build/Platform/Windows/build_config.json | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 177ac5199d..3d9ddd0411 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -214,6 +214,11 @@ def CheckoutBootstrapScripts(String branchName) { } def CheckoutRepo(boolean disableSubmodules = false) { + + if (!fileExists(ENGINE_REPOSITORY_NAME)) { + palMkdir(ENGINE_REPOSITORY_NAME) + } + palSh('git lfs uninstall', 'Git LFS Uninstall') // Prevent git from pulling lfs objects during checkout if(fileExists('.git')) { diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index a1290a254f..666c0ab5e7 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -281,5 +281,19 @@ "CMAKE_TARGET": "ALL_BUILD", "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo" } + }, + "install_profile_vs2019": { + "TAGS": [ + "nightly" + ], + "COMMAND": "build_windows.cmd", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build\\windows_vs2019", + "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DCMAKE_INSTALL_PREFIX=build\\install", + "CMAKE_LY_PROJECTS": "", + "CMAKE_TARGET": "INSTALL", + "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo" + } } } From a23a2fba65bef0248bf16eb03a90046d5e65d594 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 14 Apr 2021 17:47:37 -0700 Subject: [PATCH 051/122] PR feedback --- .../Code/Source/Material/EditorMaterialComponentSlot.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 5c22a0974e..871bb7f83f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -172,10 +172,6 @@ namespace AZ { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, sourcePath); } - else - { - EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); - } } void EditorMaterialComponentSlot::Clear() @@ -277,7 +273,7 @@ namespace AZ QAction* action = nullptr; - menu.addAction("Open Material Editor", [this]() { OpenMaterialEditor(); }); + menu.addAction("Open Material Editor", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); }); action = menu.addAction("Clear", [this]() { Clear(); }); action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); From 45faa26ffd6ebb2d99d6c0dc2d226eb4a47501a6 Mon Sep 17 00:00:00 2001 From: karlberg Date: Wed, 14 Apr 2021 17:50:04 -0700 Subject: [PATCH 052/122] Some initial updates for eventual support of locally predicted input processing --- .../AutoGen/AutoComponentTypes_Header.jinja | 7 +++++ ...tionPlayerInputComponent.AutoComponent.xml | 4 +-- .../LocalPredictionPlayerInputComponent.cpp | 2 +- .../LocalPredictionPlayerInputComponent.h | 2 +- .../Components/NetworkTransformComponent.h | 1 - .../Code/Source/NetworkInput/NetworkInput.cpp | 26 ++++++++++++++----- .../Code/Source/NetworkInput/NetworkInput.h | 17 +++++++----- .../NetworkInput/NetworkInputVector.cpp | 4 +-- .../Source/NetworkInput/NetworkInputVector.h | 6 ++--- 9 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja index 22365e685c..090bd4f0e0 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja @@ -1,6 +1,7 @@ #pragma once #include +#include namespace AZ { @@ -17,7 +18,13 @@ namespace {{ Namespace }} {% set ComponentName = Component.attrib['Name'] %} {{ ComponentName }}, {% endfor %} + Count }; + static_assert(ComponentTypes::Count < static_cast(Multiplayer::InvalidNetComponentId), "ComponentId overflow"); + //! For reflecting multiplayer components into the serialize, edit, and behaviour contexts. void CreateComponentDescriptors(AZStd::list& descriptors); + + //! For creating multiplayer component network inputs. + void CreateComponentNetworkInput(); } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index faeaf8d0cc..d38ebbb1b8 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 6ff27ebe6c..24986148c4 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -47,7 +47,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection ( - [[maybe_unused]] const Multiplayer::NetworkInputId& inputId, + [[maybe_unused]] const Multiplayer::ClientInputId& inputId, [[maybe_unused]] const AzNetworking::PacketEncodingBuffer& correction ) { diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h index d7029ed0a1..b332315799 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h @@ -42,6 +42,6 @@ namespace Multiplayer void HandleSendClientInput(const Multiplayer::NetworkInputVector& inputArray, const uint32_t& stateHash, const AzNetworking::PacketEncodingBuffer& clientState) override; void HandleSendMigrateClientInput(const Multiplayer::MigrateNetworkInputVector& inputArray) override; - void HandleSendClientInputCorrection(const Multiplayer::NetworkInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override; + void HandleSendClientInputCorrection(const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h index 2ae3ab4bb9..2a3b5fb3cc 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h @@ -54,6 +54,5 @@ namespace Multiplayer void OnTransformChangedEvent(const AZ::Transform& worldTm); AZ::TransformChangedEvent::Handler m_transformChangedHandler; - AZ::ScheduledEvent m_transformChangeEvent; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index 5991e0391d..a02bc4209d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -33,22 +33,36 @@ namespace Multiplayer return *this; } - void NetworkInput::SetNetworkInputId(NetworkInputId inputId) + void NetworkInput::SetClientInputId(ClientInputId inputId) { m_inputId = inputId; } - NetworkInputId NetworkInput::GetNetworkInputId() const + ClientInputId NetworkInput::GetClientInputId() const { return m_inputId; } - - NetworkInputId& NetworkInput::ModifyNetworkInputId() + ClientInputId& NetworkInput::ModifyClientInputId() { return m_inputId; } + void NetworkInput::SetServerTimeMs(AZ::TimeMs serverTimeMs) + { + m_serverTimeMs = serverTimeMs; + } + + AZ::TimeMs NetworkInput::GetServerTimeMs() const + { + return m_serverTimeMs; + } + + AZ::TimeMs& NetworkInput::ModifyServerTimeMs() + { + return m_serverTimeMs; + } + void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent) { m_wasAttached = true; @@ -62,7 +76,6 @@ namespace Multiplayer bool NetworkInput::Serialize(AzNetworking::ISerializer& serializer) { - //static_assert(UINT8_MAX >= Multiplayer::ComponentTypes::c_Count, "Expected fewer than 255 components, this code needs to be updated"); if (!serializer.Serialize(m_inputId, "InputId")) { return false; @@ -135,8 +148,9 @@ namespace Multiplayer void NetworkInput::CopyInternal(const NetworkInput& rhs) { m_inputId = rhs.m_inputId; + m_serverTimeMs = rhs.m_serverTimeMs; m_componentInputs.resize(rhs.m_componentInputs.size()); - for (int i = 0; i < rhs.m_componentInputs.size(); ++i) + for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i) { if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetComponentId() != rhs.m_componentInputs[i]->GetComponentId()) { diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h index 9d0cb6849d..43768c4196 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h @@ -21,7 +21,7 @@ namespace Multiplayer // Forwards class NetBindComponent; - AZ_TYPE_SAFE_INTEGRAL(NetworkInputId, uint16_t); + AZ_TYPE_SAFE_INTEGRAL(ClientInputId, uint16_t); //! @class NetworkInput //! @brief A single networked client input command. @@ -38,9 +38,13 @@ namespace Multiplayer NetworkInput(const NetworkInput&); NetworkInput& operator= (const NetworkInput&); - void SetNetworkInputId(NetworkInputId inputId); - NetworkInputId GetNetworkInputId() const; - NetworkInputId& ModifyNetworkInputId(); + void SetClientInputId(ClientInputId inputId); + ClientInputId GetClientInputId() const; + ClientInputId& ModifyClientInputId(); + + void SetServerTimeMs(AZ::TimeMs serverTimeMs); + AZ::TimeMs GetServerTimeMs() const; + AZ::TimeMs& ModifyServerTimeMs(); void AttachNetBindComponent(NetBindComponent* netBindComponent); @@ -67,10 +71,11 @@ namespace Multiplayer void CopyInternal(const NetworkInput& rhs); MultiplayerComponentInputVector m_componentInputs; - NetworkInputId m_inputId = NetworkInputId{ 0 }; + ClientInputId m_inputId = ClientInputId{ 0 }; + AZ::TimeMs m_serverTimeMs = AZ::TimeMs{ 0 }; ConstNetworkEntityHandle m_owner; bool m_wasAttached = false; }; } -AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetworkInputId); +AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::ClientInputId); diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp index 6f35bdc5fa..466a112e12 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp @@ -48,12 +48,12 @@ namespace Multiplayer return m_inputs[index].m_networkInput; } - void NetworkInputVector::SetPreviousInputId(NetworkInputId previousInputId) + void NetworkInputVector::SetPreviousInputId(ClientInputId previousInputId) { m_previousInputId = previousInputId; } - NetworkInputId NetworkInputVector::GetPreviousInputId() const + ClientInputId NetworkInputVector::GetPreviousInputId() const { return m_previousInputId; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h index 63332aa9c2..be41495577 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h @@ -32,8 +32,8 @@ namespace Multiplayer NetworkInput& operator[](uint32_t index); const NetworkInput& operator[](uint32_t index) const; - void SetPreviousInputId(NetworkInputId previousInputId); - NetworkInputId GetPreviousInputId() const; + void SetPreviousInputId(ClientInputId previousInputId); + ClientInputId GetPreviousInputId() const; bool Serialize(AzNetworking::ISerializer& serializer); @@ -48,7 +48,7 @@ namespace Multiplayer ConstNetworkEntityHandle m_owner; AZStd::fixed_vector m_inputs; - NetworkInputId m_previousInputId; + ClientInputId m_previousInputId; }; //! @class MigrateNetworkInputVector From 2410d299c1ba6de8392751f0c9f6b0e7b72e8b03 Mon Sep 17 00:00:00 2001 From: srikappa Date: Wed, 14 Apr 2021 17:51:15 -0700 Subject: [PATCH 053/122] Make creation of new prefabs use a relative path to the project --- .../Prefab/PrefabPublicHandler.cpp | 2 +- .../Prefab/PrefabPublicHandler.h | 2 +- .../Prefab/PrefabPublicInterface.h | 2 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 16 ++++++++++++++-- .../UI/Prefab/PrefabIntegrationManager.h | 4 ++++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 417a524e77..26191c97af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -58,7 +58,7 @@ namespace AzToolsFramework m_prefabUndoCache.Destroy(); } - PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) + PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) { // Retrieve entityList from entityIds EntityList inputEntityList; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 46a7f946ba..80f28d7edb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -42,7 +42,7 @@ namespace AzToolsFramework void UnregisterPrefabPublicHandlerInterface(); // PrefabPublicInterface... - PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) override; + PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) override; PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) override; PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override; PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h index 81a5258d91..4e59729ab2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h @@ -49,7 +49,7 @@ namespace AzToolsFramework * @param filePath The path for the new prefab file. * @return An outcome object; on failure, it comes with an error message detailing the cause of the error. */ - virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) = 0; + virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0; /** * Instantiate a prefab from a prefab file. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 1e71b545b5..6ce3fdc755 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,12 @@ namespace AzToolsFramework { namespace Prefab { + EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr; PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr; + PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; + const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; void PrefabUserSettings::Reflect(AZ::ReflectContext* context) @@ -79,6 +83,13 @@ namespace AzToolsFramework return; } + s_prefabLoaderInterface = AZ::Interface::Get(); + if (s_prefabLoaderInterface == nullptr) + { + AZ_Assert(false, "Prefab - could not get PrefabLoaderInterface on PrefabIntegrationManager construction."); + return; + } + EditorContextMenuBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); @@ -320,14 +331,15 @@ namespace AzToolsFramework GenerateSuggestedFilenameFromEntities(prefabRootEntities, suggestedName); - if (!QueryUserForPrefabSaveLocation(suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath)) + if (!QueryUserForPrefabSaveLocation( + suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath)) { // User canceled prefab creation, or error prevented continuation. return; } } - auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath); + auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data())); if (!createPrefabOutcome.IsSuccess()) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 66a047df28..c9b846aa5b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -29,6 +29,9 @@ namespace AzToolsFramework { namespace Prefab { + + class PrefabLoaderInterface; + //! Structure for saving/retrieving user settings related to prefab workflows. class PrefabUserSettings : public AZ::UserSettings @@ -129,6 +132,7 @@ namespace AzToolsFramework static EditorEntityUiInterface* s_editorEntityUiInterface; static PrefabPublicInterface* s_prefabPublicInterface; static PrefabEditInterface* s_prefabEditInterface; + static PrefabLoaderInterface* s_prefabLoaderInterface; }; } } From 243af5f697155ff8489d0a310ceaae1bd84eb90b Mon Sep 17 00:00:00 2001 From: pruiksma Date: Wed, 14 Apr 2021 23:13:31 -0500 Subject: [PATCH 054/122] ATOM-15240 Fixing thumbnails attempting to use a feature processor that no longer exists. Adding simple point and simple spot feature processors to the thumbnail scene descriptor. --- .../Rendering/ThumbnailRendererSteps/InitializeStep.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp index 238cbb3a3c..2a447ce3ec 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp @@ -54,8 +54,9 @@ namespace AZ RPI::SceneDescriptor sceneDesc; sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor"); sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor"); + sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimplePointLightFeatureProcessor"); + sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimpleSpotLightFeatureProcessor"); sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor"); - sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SpotLightFeatureProcessor"); // There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow flickering [ATOM-13568] // as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now. // Possibly re-enable with [GFX TODO][ATOM-13639] From fa7f61cf0d7bc89f14447e160b7cb70c604e0b07 Mon Sep 17 00:00:00 2001 From: qingtao Date: Wed, 14 Apr 2021 22:48:46 -0700 Subject: [PATCH 055/122] ATOM-13791 Editor: ImGui profiling tools doesn't work correctly due to disabled RenderPipelines - Added pause/resume button to ImGui Profiler to pause/resume profiling - Added showing pass execution timeline - Change TimestampResult to include both begin tick and duration tick. Update some function names of TimestampResult. - Update some functions names in Pass. - Stop showing accumulated time for ParentPass. - Fixed a crash issue with ImGuiManager which doesn't have default font. --- .gitignore | 1 + .../ProfilingCaptureSystemComponent.cpp | 4 +- .../Atom/RPI.Public/GpuQuery/GpuQueryTypes.h | 17 +- .../Include/Atom/RPI.Public/Pass/ParentPass.h | 1 - .../Code/Include/Atom/RPI.Public/Pass/Pass.h | 8 +- .../RPI.Public/GpuQuery/GpuQueryTypes.cpp | 46 ++- .../Source/RPI.Public/Pass/ParentPass.cpp | 15 +- .../RPI/Code/Source/RPI.Public/Pass/Pass.cpp | 18 +- .../Source/RPI.Public/Pass/RenderPass.cpp | 2 +- .../Viewport/PerformanceMonitorComponent.cpp | 4 +- .../Include/Atom/Utils/ImGuiGpuProfiler.h | 33 ++- .../Include/Atom/Utils/ImGuiGpuProfiler.inl | 262 ++++++++++++++---- Gems/ImGui/Code/Source/ImGuiManager.cpp | 4 + 13 files changed, 291 insertions(+), 124 deletions(-) diff --git a/.gitignore b/.gitignore index 24af068c53..eb24d72701 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ _savebackup/ #Output folder for test results when running Automated Tests TestResults/** *.swatches +/imgui.ini diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 38c30d67a6..9cc98a15ec 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -186,7 +186,7 @@ namespace AZ { for (const RPI::Pass* pass : passes) { - m_timestampEntries.push_back({ pass->GetName(), pass->GetTimestampResult().GetTimestampInNanoseconds() }); + m_timestampEntries.push_back({pass->GetName(), pass->GetLatestTimestampResult().GetDurationInNanoseconds()}); } } @@ -223,7 +223,7 @@ namespace AZ { for (const RPI::Pass* pass : passes) { - m_pipelineStatisticsEntries.push_back({ pass->GetName(), pass->GetPipelineStatisticsResult() }); + m_pipelineStatisticsEntries.push_back({pass->GetName(), pass->GetLatestPipelineStatisticsResult()}); } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h index 80a72aaf55..ae86557170 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include @@ -43,15 +44,19 @@ namespace AZ { public: TimestampResult() = default; - TimestampResult(uint64_t timestampInTicks); - TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh); - TimestampResult(AZStd::array_view&& timestampResultArray); + TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass); - uint64_t GetTimestampInNanoseconds() const; - uint64_t GetTimestampInTicks() const; + uint64_t GetDurationInNanoseconds() const; + uint64_t GetDurationInTicks() const; + uint64_t GetTimestampBeginInTicks() const; + + void Add(const TimestampResult& extent); private: - uint64_t m_timestampInTicks = 0u; + // the timestamp of begin and duration in ticks. + uint64_t m_begin = 0; + uint64_t m_duration = 0; + RHI::HardwareQueueClass m_hardwareQueueClass = RHI::HardwareQueueClass::Graphics; }; //! The structure that is used to read back the results form the PipelineStatistics queries diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h index 9317158437..b4f63a7099 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h @@ -122,7 +122,6 @@ namespace AZ private: // RPI::Pass overrides... - TimestampResult GetTimestampResultInternal() const override; PipelineStatisticsResult GetPipelineStatisticsResultInternal() const override; // --- Hierarchy related functions --- diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h index ae249a5f45..b0d6bd4117 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h @@ -211,11 +211,11 @@ namespace AZ //! Prints the pass virtual void DebugPrint() const; - //! Return the Timestamp result of this pass - TimestampResult GetTimestampResult() const; + //! Return the latest Timestamp result of this pass + TimestampResult GetLatestTimestampResult() const; - //! Return the PipelineStatistic result of this pass - PipelineStatisticsResult GetPipelineStatisticsResult() const; + //! Return the latest PipelineStatistic result of this pass + PipelineStatisticsResult GetLatestPipelineStatisticsResult() const; //! Enables/Disables Timestamp queries for this pass virtual void SetTimestampQueryEnabled(bool enable); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp index a1b2ece4dc..715964651f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp @@ -21,41 +21,39 @@ namespace AZ namespace RPI { // --- TimestampResult --- - - TimestampResult::TimestampResult(uint64_t timestampInTicks) + TimestampResult::TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass) { - m_timestampInTicks = timestampInTicks; + AZ_Assert(endTick >= beginTick, "TimestampResult: bad inputs"); + m_begin = beginTick; + m_duration = endTick - beginTick; + m_hardwareQueueClass = hardwareQueueClass; } - TimestampResult::TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh) - { - const uint64_t low = AZStd::min(timestampQueryResultLow, timestampQueryResultHigh); - const uint64_t high = AZStd::max(timestampQueryResultLow, timestampQueryResultHigh); - - m_timestampInTicks = high - low; - } - - TimestampResult::TimestampResult(AZStd::array_view&& timestampResultArray) - { - // Loop through all the child passes, and accumulate all the timestampTicks - for (const TimestampResult& timestampResult : timestampResultArray) - { - m_timestampInTicks += timestampResult.m_timestampInTicks; - } - } - - uint64_t TimestampResult::GetTimestampInNanoseconds() const + uint64_t TimestampResult::GetDurationInNanoseconds() const { const RHI::Ptr device = RHI::GetRHIDevice(); - const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_timestampInTicks, RHI::HardwareQueueClass::Graphics); + const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_duration, m_hardwareQueueClass); const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds); return static_cast(timeInNanoseconds.count()); } - uint64_t TimestampResult::GetTimestampInTicks() const + uint64_t TimestampResult::GetDurationInTicks() const { - return m_timestampInTicks; + return m_duration; + } + + uint64_t TimestampResult::GetTimestampBeginInTicks() const + { + return m_begin; + } + + void TimestampResult::Add(const TimestampResult& extent) + { + uint64_t end1 = m_begin + m_duration; + uint64_t end2 = extent.m_begin + extent.m_duration; + m_begin = m_begin < extent.m_begin ? m_begin : extent.m_begin; + m_duration = (end1 > end2 ? end1 : end2) - m_begin; } // --- PipelineStatisticsResult --- diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp index 6314ae376e..106ef82bf1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp @@ -393,19 +393,6 @@ namespace AZ } } - TimestampResult ParentPass::GetTimestampResultInternal() const - { - AZStd::vector timestampResultArray; - timestampResultArray.reserve(m_children.size()); - - // Calculate the Timestamp result by summing all of its child's TimestampResults - for (const Ptr& childPass : m_children) - { - timestampResultArray.emplace_back(childPass->GetTimestampResult()); - } - return TimestampResult(timestampResultArray); - } - PipelineStatisticsResult ParentPass::GetPipelineStatisticsResultInternal() const { AZStd::vector pipelineStatisticsResultArray; @@ -414,7 +401,7 @@ namespace AZ // Calculate the PipelineStatistics result by summing all of its child's PipelineStatistics for (const Ptr& childPass : m_children) { - pipelineStatisticsResultArray.emplace_back(childPass->GetPipelineStatisticsResult()); + pipelineStatisticsResultArray.emplace_back(childPass->GetLatestPipelineStatisticsResult()); } return PipelineStatisticsResult(pipelineStatisticsResultArray); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index 5ecf293efe..9401d1a9e0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -1273,24 +1273,14 @@ namespace AZ } } - TimestampResult Pass::GetTimestampResult() const + TimestampResult Pass::GetLatestTimestampResult() const { - if (IsEnabled() && IsTimestampQueryEnabled()) - { - return GetTimestampResultInternal(); - } - - return TimestampResult(); + return GetTimestampResultInternal(); } - PipelineStatisticsResult Pass::GetPipelineStatisticsResult() const + PipelineStatisticsResult Pass::GetLatestPipelineStatisticsResult() const { - if (IsEnabled() && IsPipelineStatisticsQueryEnabled()) - { - return GetPipelineStatisticsResultInternal(); - } - - return PipelineStatisticsResult(); + return GetPipelineStatisticsResultInternal(); } TimestampResult Pass::GetTimestampResultInternal() const 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 19a4f3d302..1fad385fa6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -539,7 +539,7 @@ namespace AZ const uint32_t TimestampResultQueryCount = 2u; uint64_t timestampResult[TimestampResultQueryCount] = {0}; query->GetLatestResult(×tampResult, sizeof(uint64_t) * TimestampResultQueryCount); - m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1]); + m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1], RHI::HardwareQueueClass::Graphics); }); ExecuteOnPipelineStatisticsQuery([this](RHI::Ptr query) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp index afe3cc6fb6..513bedb55f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp @@ -109,8 +109,8 @@ namespace MaterialEditor AZ::RHI::Ptr rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass(); if (rootPass) { - AZ::RPI::TimestampResult timestampResult = rootPass->GetTimestampResult(); - double gpuFrameTimeMs = aznumeric_cast(timestampResult.GetTimestampInNanoseconds()) / 1000000; + AZ::RPI::TimestampResult timestampResult = rootPass->GetLatestTimestampResult(); + double gpuFrameTimeMs = aznumeric_cast(timestampResult.GetDurationInNanoseconds()) / 1000000; m_gpuFrameTimeMs.PushSample(gpuFrameTimeMs); } } diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h index 8936f15e55..6520844edd 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h @@ -93,7 +93,9 @@ namespace AZ ImGuiPipelineStatisticsView(); //! Draw the PipelineStatistics window. - void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& m_timestampEntryDatabase); + void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, + AZStd::unordered_map& m_timestampEntryDatabase, + AZ::RHI::Ptr rootPass); //! Total number of columns (Attribute columns + PassName column). static const uint32_t HeaderAttributeCount = PassEntry::PipelineStatisticsAttributeCount + 1u; @@ -139,6 +141,9 @@ namespace AZ // ImGui filter used to filter passes by the user's input. ImGuiTextFilter m_passFilter; + + // Pause and showing the pipeline statistics result when it's paused. + bool m_paused = false; }; class ImGuiTimestampView @@ -180,9 +185,19 @@ namespace AZ Count }; + // Timestamp refresh type . + enum class RefreshType : int32_t + { + Realtime = 0, + OncePerSecond, + Count + }; + public: //! Draw the Timestamp window. - void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& m_timestampEntryDatabase); + void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, + AZStd::unordered_map& m_timestampEntryDatabase, + AZ::RHI::Ptr rootPass); private: // Draw option for the hierarchical view of the passes. @@ -223,6 +238,20 @@ namespace AZ // ImGui filter used to filter passes. ImGuiTextFilter m_passFilter; + + // Pause and showing the timestamp result when it's paused. + bool m_paused = false; + + // Hide non-parent passes which has 0 execution time. + bool m_hideZeroPasses = false; + + // Show pass execution timeline + bool m_showTimeline = false; + + // Controls how often the timestamp data is refreshed + RefreshType m_refreshType = RefreshType::OncePerSecond; + AZStd::sys_time_t m_lastUpdateTimeMicroSecond; + }; class ImGuiGpuProfiler diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index a2b29f3fb7..c00533f740 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -105,9 +105,9 @@ namespace AZ // [GFX TODO][ATOM-4001] Cache the timestamp and PipelineStatistics results. // Get the query results from the passes. - m_timestampResult = pass->GetTimestampResult(); + m_timestampResult = pass->GetLatestTimestampResult(); - const RPI::PipelineStatisticsResult rps = pass->GetPipelineStatisticsResult(); + const RPI::PipelineStatisticsResult rps = pass->GetLatestPipelineStatisticsResult(); m_pipelineStatistics = { rps.m_vertexCount, rps.m_primitiveCount, rps.m_vertexShaderInvocationCount, rps.m_rasterizedPrimitiveCount, rps.m_renderedPrimitiveCount, rps.m_pixelShaderInvocationCount, rps.m_computeShaderInvocationCount }; @@ -153,7 +153,9 @@ namespace AZ } - inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& passEntryDatabase) + inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw, + const PassEntry* rootPassEntry, AZStd::unordered_map& passEntryDatabase, + AZ::RHI::Ptr rootPass) { // Early out if nothing is supposed to be drawn if (!draw) @@ -188,12 +190,6 @@ namespace AZ continue; } - // Filter out disabled passes for the PipelineStatistics window if necessary. - if (!m_showDisabledPasses && !passEntry.IsPipelineStatisticsEnabled()) - { - continue; - } - // Filter out parent passes if necessary. if (!m_showParentPasses && passEntry.m_isParent) { @@ -230,6 +226,13 @@ namespace AZ // Start drawing the PipelineStatistics window. if (ImGui::Begin("PipelineStatistics Window", &draw, ImGuiWindowFlags_NoResize)) { + // Pause/unpause the profiling + if (ImGui::Button(m_paused ? "Resume" : "Pause")) + { + m_paused = !m_paused; + rootPass->SetPipelineStatisticsQueryEnabled(!m_paused); + } + ImGui::Columns(2, "HeaderColumns"); // Draw the statistics of the RootPass. @@ -426,23 +429,16 @@ namespace AZ } AZStd::string label; - if (passEntry->IsPipelineStatisticsEnabled()) + if (rootEntry && m_showAttributeContribution) { - if (rootEntry && m_showAttributeContribution) - { - label = AZStd::string::format("%llu (%u%%)", - static_cast(passEntry->m_pipelineStatistics[attributeIdx]), - static_cast(normalized * 100.0f)); - } - else - { - label = AZStd::string::format("%llu", - static_cast(passEntry->m_pipelineStatistics[attributeIdx])); - } + label = AZStd::string::format("%llu (%u%%)", + static_cast(passEntry->m_pipelineStatistics[attributeIdx]), + static_cast(normalized * 100.0f)); } else { - label = "-"; + label = AZStd::string::format("%llu", + static_cast(passEntry->m_pipelineStatistics[attributeIdx])); } if (rootEntry) @@ -523,7 +519,9 @@ namespace AZ // --- ImGuiTimestampView --- - inline void ImGuiTimestampView::DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& timestampEntryDatabase) + inline void ImGuiTimestampView::DrawTimestampWindow( + bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& timestampEntryDatabase, + AZ::RHI::Ptr rootPass) { // Early out if nothing is supposed to be drawn if (!draw) @@ -534,10 +532,28 @@ namespace AZ // Clear the references from the previous frame. m_passEntryReferences.clear(); + // pass entry grid based on its timestamp + AZStd::vector sortedPassEntries; + AZStd::vector> sortedPassGrid; + // Set the child of the parent, only if it passes the filter. for (auto& passEntryIt : timestampEntryDatabase) { PassEntry* passEntry = &passEntryIt.second; + + // Collect all pass entries with non-zero durations + if (passEntry->m_timestampResult.GetDurationInTicks() > 0) + { + sortedPassEntries.push_back(passEntry); + } + + // Skip the pass if the pass' timestamp duration is 0 + if (m_hideZeroPasses && (!passEntry->m_isParent) && passEntry->m_timestampResult.GetDurationInTicks() == 0) + { + continue; + } + + // Only add pass if it pass the filter. if (m_passFilter.PassFilter(passEntry->m_name.GetCStr())) { if (passEntry->m_parent && !passEntry->m_linked) @@ -545,19 +561,94 @@ namespace AZ passEntry->m_parent->LinkChild(passEntry); } - AZ_Assert(m_passEntryReferences.size() < TimestampEntryCount, "Too many PassEntry references. Increase the size of the array."); + AZ_Assert( + m_passEntryReferences.size() < TimestampEntryCount, + "Too many PassEntry references. Increase the size of the array."); m_passEntryReferences.push_back(passEntry); } } + // Sort the pass entries based on their starting time and duration + AZStd::sort(sortedPassEntries.begin(), sortedPassEntries.end(), [](const PassEntry* passEntry1, const PassEntry* passEntry2) { + if (passEntry1->m_timestampResult.GetTimestampBeginInTicks() == passEntry2->m_timestampResult.GetTimestampBeginInTicks()) + { + return passEntry1->m_timestampResult.GetDurationInTicks() < passEntry2->m_timestampResult.GetDurationInTicks(); + } + return passEntry1->m_timestampResult.GetTimestampBeginInTicks() < passEntry2->m_timestampResult.GetTimestampBeginInTicks(); + }); + + // calculate the total GPU duration. + RPI::TimestampResult gpuTimestamp; + if (sortedPassEntries.size() > 0) + { + gpuTimestamp = sortedPassEntries.front()->m_timestampResult; + gpuTimestamp.Add(sortedPassEntries.back()->m_timestampResult); + } + + // Add a pass to the pass grid which none of the pass's timestamp range won't overlap each other. + // Search each row until the pass can be added to the end of row without overlap the previous one. + for (auto& passEntry : sortedPassEntries) + { + auto row = sortedPassGrid.begin(); + for (; row != sortedPassGrid.end(); row++) + { + if (row->empty()) + { + break; + } + auto last = (*row).back(); + if (passEntry->m_timestampResult.GetTimestampBeginInTicks() >= + last->m_timestampResult.GetTimestampBeginInTicks() + last->m_timestampResult.GetDurationInTicks()) + { + row->push_back(passEntry); + break; + } + } + if (row == sortedPassGrid.end()) + { + sortedPassGrid.push_back(); + sortedPassGrid.back().push_back(passEntry); + } + } + + // Refresh timestamp query + bool needEnable = false; + if (!m_paused) + { + if (m_refreshType == RefreshType::OncePerSecond) + { + auto now = AZStd::GetTimeNowMicroSecond(); + if (m_lastUpdateTimeMicroSecond == 0 || now - m_lastUpdateTimeMicroSecond > 1000000) + { + needEnable = true; + m_lastUpdateTimeMicroSecond = now; + } + } + else if (m_refreshType == RefreshType::Realtime) + { + needEnable = true; + } + } + + if (rootPass->IsTimestampQueryEnabled() != needEnable) + { + rootPass->SetTimestampQueryEnabled(needEnable); + } + const ImVec2 windowSize(680.0f, 620.0f); ImGui::SetNextWindowSize(windowSize, ImGuiCond_Always); if (ImGui::Begin("Timestamp View", &draw, ImGuiWindowFlags_NoResize)) { // Draw the header. { + // Pause/unpause the profiling + if (ImGui::Button(m_paused? "Resume":"Pause")) + { + m_paused = !m_paused; + } + // Draw the frame time (GPU). - const AZStd::string formattedTimestamp = FormatTimestampLabel(rootPassEntry->m_interpolatedTimestampInNanoseconds); + const AZStd::string formattedTimestamp = FormatTimestampLabel(gpuTimestamp.GetDurationInNanoseconds()); const AZStd::string headerFrameTime = AZStd::string::format("Total frame duration (GPU): %s", formattedTimestamp.c_str()); ImGui::Text(headerFrameTime.c_str()); @@ -566,6 +657,17 @@ namespace AZ ImGui::SameLine(); ImGui::RadioButton("Flat", reinterpret_cast(&m_viewType), static_cast(ProfilerViewType::Flat)); + // Draw the refresh option + ImGui::RadioButton("Realtime", reinterpret_cast(&m_refreshType), static_cast(RefreshType::Realtime)); + ImGui::SameLine(); + ImGui::RadioButton("Once Per Second", reinterpret_cast(&m_refreshType), static_cast(RefreshType::OncePerSecond)); + + // Show/hide non-parent passes which have zero execution time + ImGui::Checkbox("Hide Zero Cost Passes", &m_hideZeroPasses); + + // Show/hide the timeline bar of all the passes which has non-zero execution time + ImGui::Checkbox("Show Timeline", &m_showTimeline); + // Draw advanced options. const ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None; GpuProfilerImGuiHelper::TreeNode("Advanced options", flags, [this](bool unrolled) @@ -587,6 +689,56 @@ namespace AZ ImGui::Separator(); + // Draw the pass entry grid + if (!sortedPassEntries.empty() && m_showTimeline) + { + const float passBarHeight = 20.f; + const float passBarSpace = 3.f; + float areaWidth = ImGui::GetContentRegionAvail().x - 20.f; + + if (ImGui::BeginChild("Timeline", ImVec2(areaWidth, (passBarHeight + passBarSpace) * sortedPassGrid.size()), false)) + { + // start tick and end tick for the area + uint64_t areaStartTick = sortedPassEntries.front()->m_timestampResult.GetTimestampBeginInTicks(); + uint64_t areaEndTick = sortedPassEntries.back()->m_timestampResult.GetTimestampBeginInTicks() + + sortedPassEntries.back()->m_timestampResult.GetDurationInTicks(); + uint64_t areaDurationInTicks = areaEndTick - areaStartTick; + + float rowStartY = 0.f; + for (auto& row : sortedPassGrid) + { + // row start y + for (auto passEntry : row) + { + // button start and end + float buttonStartX = (passEntry->m_timestampResult.GetTimestampBeginInTicks() - areaStartTick) * areaWidth / + areaDurationInTicks; + float buttonWidth = passEntry->m_timestampResult.GetDurationInTicks() * areaWidth / areaDurationInTicks; + ImGui::SetCursorPosX(buttonStartX); + ImGui::SetCursorPosY(rowStartY); + + // Adds a button and the hover colors. + ImGui::Button(passEntry->m_name.GetCStr(), ImVec2(buttonWidth, passBarHeight)); + + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); + ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); + ImGui::Text("Duration in ticks: %u", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); + ImGui::EndTooltip(); + } + } + + rowStartY += passBarHeight + passBarSpace; + } + } + ImGui::EndChild(); + + ImGui::Separator(); + } + // Draw the timestamp view. { static const AZStd::array(TimestampMetricUnit::Count)> MetricUnitText = @@ -713,20 +865,18 @@ namespace AZ const auto drawWorkloadBar = [this](const AZStd::string& entryTime, const PassEntry* entry) { ImGui::NextColumn(); - ImGui::Text(entryTime.c_str()); - ImGui::NextColumn(); - - // Only draw the workload bar when the entry is enabled. - if (entry->IsTimestampEnabled()) + if (entry->m_isParent) { - DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); + ImGui::NextColumn(); + ImGui::NextColumn(); } else { - ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled"); + ImGui::Text(entryTime.c_str()); + ImGui::NextColumn(); + DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); + ImGui::NextColumn(); } - - ImGui::NextColumn(); }; static const auto createHoverMarker = [](const char* text) @@ -800,23 +950,17 @@ namespace AZ // Draw the flat view. for (const PassEntry* entry : m_passEntryReferences) { + if (entry->m_isParent) + { + continue; + } const AZStd::string entryTime = FormatTimestampLabel(entry->m_interpolatedTimestampInNanoseconds); ImGui::Text(entry->m_name.GetCStr()); ImGui::NextColumn(); ImGui::Text(entryTime.c_str()); ImGui::NextColumn(); - - // Only draw the workload bar if the entry is enabled. - if (entry->IsTimestampEnabled()) - { - DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); - } - else - { - ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled"); - } - + DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); ImGui::NextColumn(); } } @@ -890,23 +1034,33 @@ namespace AZ // Update the PassEntry database. const PassEntry* rootPassEntryRef = CreatePassEntries(rootPass); + bool wasDraw = draw; + GpuProfilerImGuiHelper::Begin("Gpu Profiler", &draw, ImGuiWindowFlags_NoResize, [this, &rootPass]() { - ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView); + if (ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView)) + { + rootPass->SetTimestampQueryEnabled(m_drawTimestampView); + } ImGui::Spacing(); - ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView); + if(ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView)) + { + rootPass->SetPipelineStatisticsQueryEnabled(m_drawPipelineStatisticsView); + } }); // Draw the PipelineStatistics window. - m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase); + m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase, rootPass); // Draw the PipelineStatistics window. - m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase); + m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase, rootPass); - // [GFX TODO][ATOM-13792] Optimization: ImGui GpuProfiler Pass hierarchy traversal. - // Enable/Disable the Timestamp and PipelineStatistics on the RootPass - rootPass->SetTimestampQueryEnabled(draw && m_drawTimestampView); - rootPass->SetPipelineStatisticsQueryEnabled(draw && m_drawPipelineStatisticsView); + //closing window + if (wasDraw && !draw) + { + rootPass->SetTimestampQueryEnabled(false); + rootPass->SetPipelineStatisticsQueryEnabled(false); + } } inline void ImGuiGpuProfiler::InterpolatePassEntries(AZStd::unordered_map& passEntryDatabase, float weight) const @@ -918,7 +1072,7 @@ namespace AZ { // Interpolate the timestamps. const double interpolated = Lerp(static_cast(oldEntryIt->second.m_interpolatedTimestampInNanoseconds), - static_cast(entry.second.m_timestampResult.GetTimestampInNanoseconds()), + static_cast(entry.second.m_timestampResult.GetDurationInNanoseconds()), static_cast(weight)); entry.second.m_interpolatedTimestampInNanoseconds = static_cast(interpolated); } diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index 697cc61f86..c446c98175 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -222,6 +222,10 @@ void ImGuiManager::Initialize() io.DisplaySize.x = 1920; io.DisplaySize.y = 1080; + // Create a default font + io.Fonts->AddFontDefault(); + io.Fonts->Build(); + // Broadcast ImGui Ready to Listeners ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnImGuiInitialize); m_currentControllerIndex = -1; From 7c5f7181ebb538d04586b9e088ce740db82c6320 Mon Sep 17 00:00:00 2001 From: hultonha Date: Thu, 15 Apr 2021 10:32:46 +0100 Subject: [PATCH 056/122] updates following review feedback - remove explicit resize and update concrete type to alias --- .../AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp | 4 ++-- .../AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 09adaf38cb..6077a66682 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -31,10 +31,10 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kStringType: { - JsonByteStream* valAsByteStream = static_cast(outputValue); - JsonByteStream buffer(inputValue.GetStringLength()); + JsonByteStream buffer; if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength())) { + JsonByteStream* valAsByteStream = static_cast(outputValue); *valAsByteStream = AZStd::move(buffer); return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp index e5a1f5e6bb..6e3c8cec60 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp @@ -69,7 +69,7 @@ namespace AZ jsonContext->Serializer()->HandlesType(); jsonContext->Serializer()->HandlesType(); - jsonContext->Serializer()->HandlesType>(); + jsonContext->Serializer()->HandlesType(); jsonContext->Serializer() ->HandlesType() From 11081aeddd95360825eaeafe486ea4feda93b55c Mon Sep 17 00:00:00 2001 From: jjjoness <82226755+jjjoness@users.noreply.github.com> Date: Thu, 15 Apr 2021 11:01:08 +0100 Subject: [PATCH 057/122] Changed logo to O3DE --- Code/Sandbox/Editor/AboutDialog.cpp | 2 +- Code/Sandbox/Editor/AboutDialog.ui | 63 ++++++++++++----------- Code/Sandbox/Editor/StartupLogoDialog.cpp | 2 +- Code/Sandbox/Editor/StartupLogoDialog.qrc | 2 +- Code/Sandbox/Editor/StartupLogoDialog.ui | 8 +-- Code/Sandbox/Editor/lumberyard_logo.svg | 41 --------------- Code/Sandbox/Editor/o3de_logo.svg | 22 ++++++++ 7 files changed, 63 insertions(+), 77 deletions(-) delete mode 100644 Code/Sandbox/Editor/lumberyard_logo.svg create mode 100644 Code/Sandbox/Editor/o3de_logo.svg diff --git a/Code/Sandbox/Editor/AboutDialog.cpp b/Code/Sandbox/Editor/AboutDialog.cpp index e1cd4c7bb0..d9cf722d1f 100644 --- a/Code/Sandbox/Editor/AboutDialog.cpp +++ b/Code/Sandbox/Editor/AboutDialog.cpp @@ -56,7 +56,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Draw the Open 3D Engine logo from svg - m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); + m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); // Prevent re-sizing setFixedSize(m_enforcedWidth, m_enforcedHeight); diff --git a/Code/Sandbox/Editor/AboutDialog.ui b/Code/Sandbox/Editor/AboutDialog.ui index 0eb2881600..67767c0de1 100644 --- a/Code/Sandbox/Editor/AboutDialog.ui +++ b/Code/Sandbox/Editor/AboutDialog.ui @@ -60,35 +60,35 @@ 5 - - - - 4 - - - 12 - - - 9 - - - - - - 250 - 60 - - - - - 250 - 60 - - - - - - + + + + 4 + + + 12 + + + 9 + + + + + + 161 + 49 + + + + + 161 + 49 + + + + + + @@ -251,6 +251,11 @@ + + QSvgWidget + QWidget +
qsvgwidget.h
+
ClickableLabel QLabel diff --git a/Code/Sandbox/Editor/StartupLogoDialog.cpp b/Code/Sandbox/Editor/StartupLogoDialog.cpp index 38cf1bc5f6..c3d584b030 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.cpp +++ b/Code/Sandbox/Editor/StartupLogoDialog.cpp @@ -49,7 +49,7 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Draw the Open 3D Engine logo from svg - m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); + m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); m_ui->m_TransparentConfidential->setObjectName("copyrightNotice"); m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText); diff --git a/Code/Sandbox/Editor/StartupLogoDialog.qrc b/Code/Sandbox/Editor/StartupLogoDialog.qrc index 55c93b427c..29730ef9c7 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.qrc +++ b/Code/Sandbox/Editor/StartupLogoDialog.qrc @@ -1,6 +1,6 @@ - lumberyard_logo.svg + o3de_logo.svg splashscreen_1_27.png diff --git a/Code/Sandbox/Editor/StartupLogoDialog.ui b/Code/Sandbox/Editor/StartupLogoDialog.ui index f14355de8c..6e01808a84 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.ui +++ b/Code/Sandbox/Editor/StartupLogoDialog.ui @@ -42,14 +42,14 @@ - 250 - 60 + 161 + 49 - 250 - 60 + 161 + 50 diff --git a/Code/Sandbox/Editor/lumberyard_logo.svg b/Code/Sandbox/Editor/lumberyard_logo.svg deleted file mode 100644 index fe5f2fbdcd..0000000000 --- a/Code/Sandbox/Editor/lumberyard_logo.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - background - - - - Layer 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Sandbox/Editor/o3de_logo.svg b/Code/Sandbox/Editor/o3de_logo.svg new file mode 100644 index 0000000000..ac746c07a5 --- /dev/null +++ b/Code/Sandbox/Editor/o3de_logo.svg @@ -0,0 +1,22 @@ + + + Group 12 + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 20c1454e4b0b626a9bec6c7eb81c400aa6516f58 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Thu, 15 Apr 2021 03:41:20 -0700 Subject: [PATCH 058/122] Added the ShaderRead buffer bind flag to the static and dynamic input assembly pools, and one creation of a static input assembly buffer. --- Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp | 4 ++-- Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp index fd2d029ddb..491f57deec 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp @@ -100,12 +100,12 @@ namespace AZ bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; case CommonBufferPoolType::StaticInputAssembly: - bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly; + bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::ShaderRead; bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device; bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; case CommonBufferPoolType::DynamicInputAssembly: - bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly; + bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::ShaderRead; bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host; bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h index 0a6cfafee7..bea6de5898 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h @@ -98,7 +98,7 @@ namespace WhiteBox // specify the data format for vertex stream data AZ::RHI::BufferDescriptor bufferDescriptor; - bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly; + bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly | AZ::RHI::BufferBindFlags::ShaderRead; bufferDescriptor.m_byteCount = bufferSize; bufferDescriptor.m_alignment = elementSize; From 23cf2d5d68d807e40252affdc00fe362ca6c784b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Tue, 13 Apr 2021 15:03:21 +0100 Subject: [PATCH 059/122] SystemComponent is now only build in PhysX.Static, instead of most of the Physx projects. --- .../AzFramework/Physics/SystemBus.h | 7 -- Gems/Blast/Code/Tests/Mocks/BlastMocks.h | 3 - .../Code/Tests/Mocks/PhysicsSystem.h | 1 - Gems/PhysX/Code/Editor/EditorWindow.cpp | 3 + Gems/PhysX/Code/Editor/EditorWindow.h | 7 ++ .../Components/EditorSystemComponent.cpp | 20 +++- .../Source/Components/EditorSystemComponent.h | 5 + Gems/PhysX/Code/Source/SystemComponent.cpp | 91 ------------------- Gems/PhysX/Code/Source/SystemComponent.h | 16 ---- .../Code/Tests/CharacterControllerTests.cpp | 50 +++++++++- .../Code/physx_editor_shared_files.cmake | 2 - .../PhysX/Code/physx_editor_tests_files.cmake | 2 - Gems/PhysX/Code/physx_files.cmake | 2 + Gems/PhysX/Code/physx_shared_files.cmake | 2 - Gems/PhysX/Code/physx_tests_files.cmake | 2 - 15 files changed, 82 insertions(+), 131 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h index c303e14636..717f9e023c 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h @@ -142,13 +142,6 @@ namespace Physics virtual AZStd::shared_ptr CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0; - /// Adds an appropriate collider component to the entity based on the provided shape configuration. - /// @param entity Entity where the component should be added to. - /// @param colliderConfiguration Configuration of the collider. - /// @param shapeConfiguration Configuration of the shape of the collider. - /// @param addEditorComponents Tells whether to add the Editor version of the collider component or the Game one. - virtual void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) = 0; - /// Releases the mesh object created by the physics backend. /// @param nativeMeshObject Pointer to the mesh object. virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0; diff --git a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h index 0ac1f6c27e..95a16c311f 100644 --- a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h +++ b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h @@ -213,9 +213,6 @@ namespace Blast CreateShape, AZStd::shared_ptr( const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&)); - MOCK_METHOD4( - AddColliderComponentToEntity, - void(AZ::Entity*, const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&, bool)); MOCK_METHOD1(ReleaseNativeMeshObject, void(void*)); MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr(const Physics::MaterialConfiguration&)); MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h index 0b20632884..1219e34448 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h @@ -33,7 +33,6 @@ namespace Physics BusDisconnect(); } MOCK_METHOD2(CreateShape, AZStd::shared_ptr(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration)); - MOCK_METHOD4(AddColliderComponentToEntity, void(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents)); MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject)); MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr(const Physics::MaterialConfiguration& materialConfiguration)); MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr()); diff --git a/Gems/PhysX/Code/Editor/EditorWindow.cpp b/Gems/PhysX/Code/Editor/EditorWindow.cpp index 41b2991c2a..c8d6715838 100644 --- a/Gems/PhysX/Code/Editor/EditorWindow.cpp +++ b/Gems/PhysX/Code/Editor/EditorWindow.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include namespace PhysX { diff --git a/Gems/PhysX/Code/Editor/EditorWindow.h b/Gems/PhysX/Code/Editor/EditorWindow.h index 34f1906d43..86f72f70f2 100644 --- a/Gems/PhysX/Code/Editor/EditorWindow.h +++ b/Gems/PhysX/Code/Editor/EditorWindow.h @@ -19,6 +19,7 @@ namespace AzPhysics { class CollisionConfiguration; + struct SceneConfiguration; } namespace Ui @@ -28,6 +29,12 @@ namespace Ui namespace PhysX { + struct PhysXSystemConfiguration; + namespace Debug + { + struct DebugConfiguration; + } + namespace Editor { /// Window pane wrapper for the PhysX Configuration Widget. diff --git a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp index 2f4b389795..516b958adb 100644 --- a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp +++ b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp @@ -18,13 +18,15 @@ #include #include #include -#include -#include #include #include #include +#include +#include +#include +#include #include namespace PhysX @@ -116,18 +118,20 @@ namespace PhysX { AzPhysics::SceneConfiguration editorWorldConfiguration = physicsSystem->GetDefaultSceneConfiguration(); editorWorldConfiguration.m_sceneName = AzPhysics::EditorPhysicsSceneName; - editorWorldConfiguration.m_sceneName = "EditorScene"; m_editorWorldSceneHandle = physicsSystem->AddScene(editorWorldConfiguration); } PhysX::RegisterConfigStringLineEditHandler(); // Register custom unique string line edit control + PhysX::Editor::RegisterPropertyTypes(); + AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); } void EditorSystemComponent::Deactivate() { AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); Physics::EditorWorldBus::Handler::BusDisconnect(); if (auto* physicsSystem = AZ::Interface::Get()) @@ -164,6 +168,16 @@ namespace PhysX } } + void EditorSystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) + { + + } + + void EditorSystemComponent::NotifyRegisterViews() + { + PhysX::Editor::EditorWindow::RegisterViewClass(); + } + AZ::Data::AssetId EditorSystemComponent::GenerateSurfaceTypesLibrary() { AZ::Data::AssetId resultAssetId; diff --git a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h index cba542ce84..9ebca05ccd 100644 --- a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h +++ b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h @@ -30,6 +30,7 @@ namespace PhysX : public AZ::Component , public Physics::EditorWorldBus::Handler , private AzToolsFramework::EditorEntityContextNotificationBus::Handler + , private AzToolsFramework::EditorEvents::Bus::Handler { public: AZ_COMPONENT(EditorSystemComponent, "{560F08DC-94F5-4D29-9AD4-CDFB3B57C654}"); @@ -60,6 +61,10 @@ namespace PhysX void OnStartPlayInEditorBegin() override; void OnStopPlayInEditor() override; + // AztoolsFramework::EditorEvents::Bus::Handler + void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; + void NotifyRegisterViews() override; + AZ::Data::AssetId GenerateSurfaceTypesLibrary(); AzPhysics::SceneHandle m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle; diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index 6de54a7593..8210492fe7 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -15,38 +15,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include #include -#include -#include -#include #include #include #include #include #include -#ifdef PHYSX_EDITOR -#include -#include -#include -#include -#include -#endif - #include #include @@ -233,21 +213,11 @@ namespace PhysX Physics::CollisionRequestBus::Handler::BusConnect(); Physics::CharacterSystemRequestBus::Handler::BusConnect(); -#ifdef PHYSX_EDITOR - PhysX::Editor::RegisterPropertyTypes(); - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); -#endif - ActivatePhysXSystem(); } void SystemComponent::Deactivate() { -#ifdef PHYSX_EDITOR - AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); -#endif AZ::TickBus::Handler::BusDisconnect(); Physics::CharacterSystemRequestBus::Handler::BusDisconnect(); Physics::CollisionRequestBus::Handler::BusDisconnect(); @@ -272,19 +242,6 @@ namespace PhysX m_assetHandlers.clear(); //this need to be after m_physXSystem->Shutdown(); For it will drop the default material library reference. } -#ifdef PHYSX_EDITOR - - // AztoolsFramework::EditorEvents::Bus::Handler overrides - void SystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) - { - } - - void SystemComponent::NotifyRegisterViews() - { - PhysX::Editor::EditorWindow::RegisterViewClass(); - } -#endif - physx::PxConvexMesh* SystemComponent::CreateConvexMesh(const void* vertices, AZ::u32 vertexNum, AZ::u32 vertexStride) { physx::PxConvexMeshDesc desc; @@ -464,54 +421,6 @@ namespace PhysX } } - void SystemComponent::AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, [[maybe_unused]] bool addEditorComponents) - { - [[maybe_unused]] Physics::ShapeType shapeType = shapeConfiguration.GetShapeType(); - -#ifdef PHYSX_EDITOR - if (addEditorComponents) - { - entity->CreateComponent(colliderConfiguration, shapeConfiguration); - } - else -#else - { - if (shapeType == Physics::ShapeType::Sphere) - { - const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast(shapeConfiguration); - auto sphereColliderComponent = entity->CreateComponent(); - sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(sphereConfiguration)) }); - } - else if (shapeType == Physics::ShapeType::Box) - { - const Physics::BoxShapeConfiguration& boxConfiguration = static_cast(shapeConfiguration); - auto boxColliderComponent = entity->CreateComponent(); - boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(boxConfiguration)) }); - } - else if (shapeType == Physics::ShapeType::Capsule) - { - const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast(shapeConfiguration); - auto capsuleColliderComponent = entity->CreateComponent(); - capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(capsuleConfiguration)) }); - } - } - - AZ_Error("PhysX System", !addEditorComponents, "AddColliderComponentToEntity(): Trying to add an Editor collider component in a stand alone build.", - static_cast(shapeType)); - -#endif - { - AZ_Error("PhysX System", shapeType == Physics::ShapeType::Sphere || shapeType == Physics::ShapeType::Box || shapeType == Physics::ShapeType::Capsule, - "AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast(shapeType)); - } - } - // Physics::CharacterSystemRequestBus AZStd::unique_ptr SystemComponent::CreateCharacter(const Physics::CharacterConfiguration& characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) diff --git a/Gems/PhysX/Code/Source/SystemComponent.h b/Gems/PhysX/Code/Source/SystemComponent.h index c074a2032d..8c4ac0d836 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.h +++ b/Gems/PhysX/Code/Source/SystemComponent.h @@ -36,9 +36,6 @@ #include #include -#ifdef PHYSX_EDITOR -#include -#endif namespace AzPhysics { struct StaticRigidBodyConfiguration; @@ -61,10 +58,6 @@ namespace PhysX , public Physics::SystemRequestBus::Handler , public PhysX::SystemRequestsBus::Handler , public Physics::CharacterSystemRequestBus::Handler -#ifdef PHYSX_EDITOR - , public AzToolsFramework::EditorEntityContextNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler -#endif , private Physics::CollisionRequestBus::Handler , private AZ::TickBus::Handler { @@ -100,8 +93,6 @@ namespace PhysX bool CookTriangleMeshToMemory(const AZ::Vector3* vertices, AZ::u32 vertexCount, const AZ::u32* indices, AZ::u32 indexCount, AZStd::vector& result) override; - void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) override; - physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override; physx::PxCooking* GetCooking() override; @@ -125,13 +116,6 @@ namespace PhysX void Activate() override; void Deactivate() override; -#ifdef PHYSX_EDITOR - - // AztoolsFramework::EditorEvents::Bus::Handler overrides - void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; - void NotifyRegisterViews() override; -#endif - // Physics::SystemRequestBus::Handler AZStd::shared_ptr CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration) override; AZStd::shared_ptr CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) override; diff --git a/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp b/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp index d5b961ada7..218571c01c 100644 --- a/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp +++ b/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,6 +33,51 @@ namespace PhysX { + namespace Internal + { + void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration) + { + Physics::ShapeType shapeType = shapeConfiguration.GetShapeType(); + + switch (shapeType) + { + case Physics::ShapeType::Sphere: + { + const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast(shapeConfiguration); + auto sphereColliderComponent = entity->CreateComponent(); + sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(sphereConfiguration)) }); + } + break; + case Physics::ShapeType::Box: + { + const Physics::BoxShapeConfiguration& boxConfiguration = static_cast(shapeConfiguration); + auto boxColliderComponent = entity->CreateComponent(); + boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(boxConfiguration)) }); + } + break; + case Physics::ShapeType::Capsule: + { + const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast(shapeConfiguration); + auto capsuleColliderComponent = entity->CreateComponent(); + capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(capsuleConfiguration)) }); + } + break; + default: + { + AZ_Error("PhysX", false, + "AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast(shapeType)); + } + break; + } + } + } + // transform for a floor centred at x = 0, y = 0, with top at level z = 0 static const AZ::Transform DefaultFloorTransform = AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(-0.5f)); @@ -367,8 +414,7 @@ namespace PhysX auto triggerEntity = AZStd::make_unique("TriggerEntity"); triggerEntity->CreateComponent()->SetWorldTM(AZ::Transform::Identity()); triggerEntity->CreateComponent(PhysX::StaticRigidBodyComponentTypeId); - Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::AddColliderComponentToEntity, - triggerEntity.get(), triggerConfig, boxConfig, false); + Internal::AddColliderComponentToEntity(triggerEntity.get(), triggerConfig, boxConfig); triggerEntity->Init(); triggerEntity->Activate(); diff --git a/Gems/PhysX/Code/physx_editor_shared_files.cmake b/Gems/PhysX/Code/physx_editor_shared_files.cmake index 2a84c4e380..b743efb6aa 100644 --- a/Gems/PhysX/Code/physx_editor_shared_files.cmake +++ b/Gems/PhysX/Code/physx_editor_shared_files.cmake @@ -11,6 +11,4 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h ) diff --git a/Gems/PhysX/Code/physx_editor_tests_files.cmake b/Gems/PhysX/Code/physx_editor_tests_files.cmake index 202e688a76..1e6ccde75f 100644 --- a/Gems/PhysX/Code/physx_editor_tests_files.cmake +++ b/Gems/PhysX/Code/physx_editor_tests_files.cmake @@ -11,8 +11,6 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h Tests/PhysXTestCommon.cpp Tests/PhysXTestCommon.h Tests/ColliderScalingTests.cpp diff --git a/Gems/PhysX/Code/physx_files.cmake b/Gems/PhysX/Code/physx_files.cmake index c850479f53..ed2d59b8aa 100644 --- a/Gems/PhysX/Code/physx_files.cmake +++ b/Gems/PhysX/Code/physx_files.cmake @@ -12,6 +12,8 @@ set(FILES Source/PhysX_precompiled.cpp Source/PhysX_precompiled.h + Source/SystemComponent.cpp + Source/SystemComponent.h Include/PhysX/SystemComponentBus.h Include/PhysX/ColliderComponentBus.h Include/PhysX/NativeTypeIdentifiers.h diff --git a/Gems/PhysX/Code/physx_shared_files.cmake b/Gems/PhysX/Code/physx_shared_files.cmake index 9451f44648..1b7c17f5f5 100644 --- a/Gems/PhysX/Code/physx_shared_files.cmake +++ b/Gems/PhysX/Code/physx_shared_files.cmake @@ -11,8 +11,6 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h Source/ComponentDescriptors.cpp Source/ComponentDescriptors.h ) diff --git a/Gems/PhysX/Code/physx_tests_files.cmake b/Gems/PhysX/Code/physx_tests_files.cmake index adf0f587d2..406aed64a7 100644 --- a/Gems/PhysX/Code/physx_tests_files.cmake +++ b/Gems/PhysX/Code/physx_tests_files.cmake @@ -10,8 +10,6 @@ # set(FILES - Source/SystemComponent.cpp - Source/SystemComponent.h Source/ComponentDescriptors.cpp Source/ComponentDescriptors.h Tests/PhysXComponentBusTests.cpp From ebebc05cd1709369171fdd87885c5de92a295a51 Mon Sep 17 00:00:00 2001 From: Ulugbek Adilbekov Date: Thu, 15 Apr 2021 16:16:31 +0100 Subject: [PATCH 060/122] Reenable Blast Automated tests (#42) Co-authored-by: Ulugbek Adilbekov --- .../Gem/Code/runtime_dependencies.cmake | 2 +- .../Gem/Code/tool_dependencies.cmake | 1 + .../Gem/PythonTests/Blast/TestSuite_Active.py | 14 +++++----- .../Gem/PythonTests/CMakeLists.txt | 26 +++++++++---------- AutomatedTesting/default.blastconfiguration | 2 +- .../Editor/EditorBlastMeshDataComponent.cpp | 2 +- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/runtime_dependencies.cmake index d281f64954..c8e66740e4 100644 --- a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/runtime_dependencies.cmake @@ -42,7 +42,6 @@ set(GEM_DEPENDENCIES Gem::SurfaceData Gem::GradientSignal Gem::Vegetation - Gem::Atom_RHI.Private Gem::Atom_RPI.Private Gem::Atom_Feature_Common @@ -54,4 +53,5 @@ set(GEM_DEPENDENCIES Gem::ImguiAtom Gem::Atom_AtomBridge Gem::AtomFont + Gem::Blast ) diff --git a/AutomatedTesting/Gem/Code/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/tool_dependencies.cmake index 22132da686..8c5da63f42 100644 --- a/AutomatedTesting/Gem/Code/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/tool_dependencies.cmake @@ -68,4 +68,5 @@ set(GEM_DEPENDENCIES Gem::ImguiAtom Gem::AtomFont Gem::AtomToolsFramework.Editor + Gem::Blast.Editor ) diff --git a/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py b/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py index 947ea8363d..066a55c78c 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py @@ -27,28 +27,28 @@ from base import TestAutomationBase class TestAutomation(TestAutomationBase): def test_ActorSplitsAfterCollision(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterCollision as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterRadialDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterRadialDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterCapsuleDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterCapsuleDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterImpactSpreadDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterImpactSpreadDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterShearDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterShearDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterTriangleDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterTriangleDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterStressDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterStressDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) \ No newline at end of file + self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 3bd5f84312..ea9c365978 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -135,20 +135,18 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) endif() ## Blast ## -# Disabled until AutomatedTesting runs with Atom. -# if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) -# ly_add_pytest( -# NAME AutomatedTesting::BlastTests -# TEST_SERIAL TRUE -# PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py -# TIMEOUT 500 -# RUNTIME_DEPENDENCIES -# Legacy::Editor -# Legacy::CryRenderNULL -# AZ::AssetProcessor -# AutomatedTesting.Assets -# ) -# endif() +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_pytest( + NAME AutomatedTesting::BlastTests + TEST_SERIAL TRUE + PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py + TIMEOUT 3600 + RUNTIME_DEPENDENCIES + Legacy::Editor + AZ::AssetProcessor + AutomatedTesting.Assets + ) +endif() ############# diff --git a/AutomatedTesting/default.blastconfiguration b/AutomatedTesting/default.blastconfiguration index 96a23ecbb8..6318a5002f 100644 --- a/AutomatedTesting/default.blastconfiguration +++ b/AutomatedTesting/default.blastconfiguration @@ -1,6 +1,6 @@ - + diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index d2aa81900b..51789f68da 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -179,7 +179,7 @@ namespace Blast void EditorBlastMeshDataComponent::RegisterModel() { - if (m_meshFeatureProcessor && m_meshAssets[0].GetId().IsValid()) + if (m_meshFeatureProcessor && !m_meshAssets.empty() && m_meshAssets[0].GetId().IsValid()) { AZ::Render::MaterialAssignmentMap materials; AZ::Render::MaterialComponentRequestBus::EventResult( From 582b098ed227a26b2f9548fe1990f52b2cd01ef0 Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 17:06:56 +0100 Subject: [PATCH 061/122] removing unused local variable --- Gems/PhysX/Code/Source/BaseColliderComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp index c67cc105d8..c8581efcb7 100644 --- a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp @@ -330,7 +330,6 @@ namespace PhysX } const bool hasNonUniformScale = (AZ::NonUniformScaleRequestBus::FindFirstHandler(GetEntityId()) != nullptr); - AZ::u8 subdivisionLevel = physicsAssetConfiguration.m_subdivisionLevel; Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, physicsAssetConfiguration.m_subdivisionLevel, m_shapes); From 7ff0c5c33a8c0fefe23c5f4fcb8f08073580db0d Mon Sep 17 00:00:00 2001 From: hultonha Date: Thu, 15 Apr 2021 18:17:02 +0100 Subject: [PATCH 062/122] fix reserve call that should have been resize - add extra handling to output error --- .../Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp | 12 ++++++++++-- .../Code/Source/Asset/EditorWhiteBoxMeshAsset.h | 1 + .../Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp | 2 +- Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp index 69d7c03fce..cd308aef0f 100644 --- a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp @@ -86,7 +86,7 @@ namespace WhiteBox { success = assetHandler->SaveAssetData(meshAsset, &fileStream); AZ_Printf( - "EditorWhiteBoxComponent", "Save %s. Location: %s", success ? "succeeded" : "failed", + "EditorWhiteBoxMeshAsset", "Save %s. Location: %s", success ? "succeeded" : "failed", absoluteFilePath.c_str()); } } @@ -229,7 +229,15 @@ namespace WhiteBox { if (asset == m_meshAsset) { - AZ_Warning("EditorWhiteBoxComponent", false, "OnAssetError: %s", asset.GetHint().c_str()); + AZ_Warning("EditorWhiteBoxMeshAsset", false, "OnAssetError: %s", asset.GetHint().c_str()); + } + } + + void EditorWhiteBoxMeshAsset::OnAssetReloadError(AZ::Data::Asset asset) + { + if (asset == m_meshAsset) + { + AZ_Warning("EditorWhiteBoxMeshAsset", false, "OnAssetReloadError: %s", asset.GetHint().c_str()); } } diff --git a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h index 2001808668..caa56dce1a 100644 --- a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h +++ b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h @@ -82,6 +82,7 @@ namespace WhiteBox void OnAssetReady(AZ::Data::Asset asset) override; void OnAssetReloaded(AZ::Data::Asset asset) override; void OnAssetError(AZ::Data::Asset asset) override; + void OnAssetReloadError(AZ::Data::Asset asset) override; // WhiteBoxMeshAssetNotificationBus ... void OnWhiteBoxMeshAssetModified(AZ::Data::Asset asset) override; diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index 72a754f05f..7aa12777e0 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -113,7 +113,7 @@ namespace WhiteBox const auto size = stream->GetLength(); Api::WhiteBoxMeshStream whiteBoxData; - whiteBoxData.reserve(size); + whiteBoxData.resize(size); stream->Read(size, whiteBoxData.data()); diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index fbab501e8f..03f2545ae1 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3407,6 +3407,11 @@ namespace WhiteBox { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); + if (input.empty()) + { + return false; + } + std::string inputStr; inputStr.reserve(input.size()); AZStd::copy(input.cbegin(), input.cend(), AZStd::back_inserter(inputStr)); From 2baa0db2de534ec97e20cda27b27cb046ea5ff04 Mon Sep 17 00:00:00 2001 From: guthadam Date: Thu, 15 Apr 2021 12:38:07 -0500 Subject: [PATCH 063/122] Standardizing dialog button boxes across material editor and component Making dialogs modal https://jira.agscollab.com/browse/ATOM-15173 https://jira.agscollab.com/browse/ATOM-15174 --- .../CreateMaterialDialog.cpp | 2 + .../PresetBrowserDialog.cpp | 1 + .../EditorMaterialComponentExporter.cpp | 21 +++----- .../EditorMaterialComponentInspector.cpp | 14 +++-- .../EditorMaterialModelUvNameMapInspector.cpp | 54 ++++++++----------- 5 files changed, 42 insertions(+), 50 deletions(-) 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 d3b5432624..20d1b587b5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp @@ -37,6 +37,8 @@ namespace MaterialEditor //Connect ok and cancel buttons QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + setModal(true); } void CreateMaterialDialog::InitMaterialTypeSelection() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp index a00490c0b9..f37a047126 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp @@ -35,6 +35,7 @@ namespace MaterialEditor SetupPresetList(); SetupSearchWidget(); SetupDialogButtons(); + setModal(true); } void PresetBrowserDialog::SetupPresetList() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index b8d1b1df28..34cc53a326 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -25,6 +25,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include +#include #include #include #include @@ -215,19 +216,10 @@ namespace AZ tableWidget->sortItems(MaterialSlotColumn); // Create the bottom row of the dialog with action buttons for exporting or canceling the operation - QWidget* buttonRow = new QWidget(&dialog); - buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - - QPushButton* confirmButton = new QPushButton("Confirm", buttonRow); - QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { dialog.accept(); }); - - QPushButton* cancelButton = new QPushButton("Cancel", buttonRow); - QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [&dialog] { dialog.reject(); }); - - QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow); - buttonLayout->addStretch(); - buttonLayout->addWidget(confirmButton); - buttonLayout->addWidget(cancelButton); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); // Create a heading label for the top of the dialog QLabel* labelWidget = new QLabel("\nSelect the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.\n", &dialog); @@ -236,8 +228,9 @@ namespace AZ QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); dialogLayout->addWidget(labelWidget); dialogLayout->addWidget(tableWidget); - dialogLayout->addWidget(buttonRow); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index d2400f52a3..cbc3222694 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -37,6 +37,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include +#include #include #include #include @@ -534,7 +535,7 @@ namespace AZ inspector->Populate(); inspector->SetOverrides(propertyOverrideMap); - // Create the menu bottom row with actions for exporting or canceling the operation + // Create the menu botton QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); @@ -546,10 +547,6 @@ namespace AZ action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); }); action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); }); - menu.addSeparator(); - action = menu.addAction("Confirm Changes", [&] { dialog.accept(); }); - action = menu.addAction("Cancel Changes", [&] { dialog.reject(); }); - menu.addSeparator(); action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); }); action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); }); @@ -563,12 +560,19 @@ namespace AZ menu.exec(QCursor::pos()); }); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); }); QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); dialogLayout->addWidget(menuButton); dialogLayout->addWidget(inspector); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp index f562f555f0..d05b618f53 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp @@ -32,8 +32,11 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include -#include +#include #include +#include +#include +#include #include AZ_POP_DISABLE_WARNING @@ -286,42 +289,31 @@ namespace AZ MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog); inspector->Populate(); - // Create the bottom row of the dialog with action buttons for exporting or canceling the operation - QWidget* buttonRow = new QWidget(&dialog); - buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + // Create the menu botton + QToolButton* menuButton = new QToolButton(&dialog); + menuButton->setAutoRaise(true); + menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); + menuButton->setVisible(true); + QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() { + QAction* action = nullptr; - QPushButton* revertButton = new QPushButton("Revert", buttonRow); - QObject::connect(revertButton, &QPushButton::clicked, revertButton, [inspector, matModUvOverrides] { - inspector->SetUvNameMap(matModUvOverrides); - }); + QMenu menu(&dialog); + action = menu.addAction("Clear", [&] { inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); }); + action = menu.addAction("Revert", [&] { inspector->SetUvNameMap(matModUvOverrides);; }); + menu.exec(QCursor::pos()); + }); - QPushButton* clearButton = new QPushButton("Clear", buttonRow); - QObject::connect(clearButton, &QPushButton::clicked, clearButton, [inspector] { - inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); - }); - - QPushButton* confirmButton = new QPushButton("Confirm", buttonRow); - QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { - dialog.accept(); - }); - - QPushButton* cancelButton = new QPushButton("Cancel", buttonRow); - QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [inspector, matModUvOverrides, &dialog] { - inspector->SetUvNameMap(matModUvOverrides); - dialog.reject(); - }); - - QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow); - buttonLayout->addStretch(); - buttonLayout->addWidget(revertButton); - buttonLayout->addWidget(clearButton); - buttonLayout->addWidget(confirmButton); - buttonLayout->addWidget(cancelButton); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); + dialogLayout->addWidget(menuButton); dialogLayout->addWidget(inspector); - dialogLayout->addWidget(buttonRow); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. From a81ca4490fef9f5120fb16b86d8d5b1ca9287ff2 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 10:42:34 -0700 Subject: [PATCH 064/122] Move EMotionFX's OpenGL dependency to 3rd Party and make sure Mac builds successfully --- Gems/EMotionFX/Code/CMakeLists.txt | 6 ------ .../Editor/Platform/Mac/platform_mac.cmake | 8 +------ cmake/3rdParty/FindOpenGLInterface.cmake | 21 +++++++++++++++++++ .../Platform/Mac/OpenGLInterface_mac.cmake | 16 ++++++++++++++ .../Platform/Mac/cmake_mac_files.cmake | 1 + cmake/3rdParty/cmake_files.cmake | 1 + 6 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 cmake/3rdParty/FindOpenGLInterface.cmake create mode 100644 cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index d46c67fafb..b90902a948 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -68,12 +68,6 @@ ly_add_target( ) if (PAL_TRAIT_BUILD_HOST_TOOLS) - - find_package(OpenGL QUIET REQUIRED) - # Imported targets (like OpenGL::GL) are scoped to a directory. Add a - # a global scope - add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) - target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) ly_add_target( NAME EMotionFX.Editor.Static STATIC diff --git a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake index 821e7d1f25..95df062a93 100644 --- a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake +++ b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake @@ -13,10 +13,4 @@ # based on the active platform # NOTE: functions in cmake are global, therefore adding functions to this file # is being avoided to prevent overriding functions declared in other targets platfrom -# specific cmake files - -target_compile_definitions(3rdParty::OpenGLInterface - INTERFACE - # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. - GL_SILENCE_DEPRECATION -) \ No newline at end of file +# specific cmake files \ No newline at end of file diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake new file mode 100644 index 0000000000..7b537d1378 --- /dev/null +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -0,0 +1,21 @@ +# +# 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. +# + +find_package(OpenGL QUIET REQUIRED) +# Imported targets (like OpenGL::GL) are scoped to a directory. Add a +# a global scope +add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) +target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) + +set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +if(EXISTS ${pal_file}) + include(${pal_file}) +endif() \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake new file mode 100644 index 0000000000..c9a52f4b1b --- /dev/null +++ b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake @@ -0,0 +1,16 @@ +# +# 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. +# + +target_compile_definitions(3rdParty::OpenGLInterface + INTERFACE + # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. + GL_SILENCE_DEPRECATION +) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake index f786f80cf7..0e3cc53262 100644 --- a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake +++ b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake @@ -15,6 +15,7 @@ set(FILES Clang_mac.cmake DirectXShaderCompiler_mac.cmake FbxSdk_mac.cmake + OpenGLInterface_mac.cmake OpenSSL_mac.cmake Wwise_mac.cmake ) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index 3fe15bc0ce..46b612df42 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -18,6 +18,7 @@ set(FILES Finddyad.cmake FindFbxSdk.cmake Findlibav.cmake + FindOpenGLInterface.cmake FindOpenSSL.cmake FindRadTelemetry.cmake FindVkValidation.cmake From cc7b4fc251ac22e65d5bf86cf3e1c2804cf8f347 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 13:06:27 -0500 Subject: [PATCH 065/122] Updated all materials, did some mesh cleaning adding source file as well. --- .../ArtSource/objects/sponza_cleanup.mb | 3 ++ .../Sponza/Assets/objects/sponza.fbx | 4 +- .../Assets/objects/sponza_mat_arch.material | 15 ++++++ .../objects/sponza_mat_background.material | 22 +++++++- .../Assets/objects/sponza_mat_bricks.material | 27 ++++++++-- .../objects/sponza_mat_ceiling.material | 50 ++++++++++++++++--- .../Assets/objects/sponza_mat_chain.material | 13 ++++- .../objects/sponza_mat_columna.material | 22 +++++++- .../objects/sponza_mat_columnb.material | 22 +++++++- .../objects/sponza_mat_columnc.material | 22 +++++++- .../objects/sponza_mat_curtainblue.material | 19 +++++++ .../objects/sponza_mat_curtaingreen.material | 16 ++++++ .../objects/sponza_mat_curtainred.material | 21 ++++++++ .../objects/sponza_mat_details.material | 14 +++++- .../objects/sponza_mat_fabricblue.material | 16 ++++++ .../objects/sponza_mat_fabricgreen.material | 16 ++++++ .../objects/sponza_mat_fabricred.material | 16 ++++++ .../objects/sponza_mat_flagpole.material | 19 ++++++- .../Assets/objects/sponza_mat_floor.material | 22 +++++++- .../Assets/objects/sponza_mat_leaf.material | 39 ++++++++++++++- .../Assets/objects/sponza_mat_lion.material | 23 ++++++++- .../Assets/objects/sponza_mat_roof.material | 17 +++++-- .../Assets/objects/sponza_mat_vase.material | 19 ++++++- .../objects/sponza_mat_vasehanging.material | 16 +++++- .../objects/sponza_mat_vaseplant.material | 32 +++++++++++- .../objects/sponza_mat_vaseround.material | 26 +++++++++- 26 files changed, 499 insertions(+), 32 deletions(-) create mode 100644 Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb diff --git a/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb b/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb new file mode 100644 index 0000000000..882496f2b0 --- /dev/null +++ b/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d3c18d76f00688d15c54736ef3d8c953df08baf46a796fa71627de18bdb3c0f +size 22804332 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx index 80cb76941e..9061666968 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cbfc4d0a6722726070468da4368df7c76be67e8d067a7e3130fd29cdcdd5c6b -size 7613840 +oid sha256:35a880abc018520d4b30d21a64f7a14fca74d936593320d5afd03ddf25771bf3 +size 9176416 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material index 8f5edb6968..da72f8a430 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/arch_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/arch_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.885053813457489, + 0.801281750202179, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/arch_1k_metallic.png" }, diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material index 5ba48a758e..5a195fd0b6 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/background_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/background_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/background_1k_normal.jpg", + "roughness": 0.4000000059604645 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8911573886871338, + 0.7894102334976196, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/background_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.03099999949336052, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material index c32beebd5c..d2089b5537 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/bricks_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/bricks_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/bricks_1k_normal.jpg", + "roughness": 0.5 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9703211784362793, + 0.9703211784362793, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/bricks_1k_metallic.png" }, @@ -23,11 +44,9 @@ "factor": 1.0 }, "parallax": { - "algorithm": "POM", - "enable": true, + "algorithm": "ContactRefinement", "factor": 0.03500000014901161, - "pdo": true, - "quality": "High", + "quality": "Medium", "textureMap": "Textures/bricks_1k_height.png" }, "roughness": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material index cbccd8ed88..40e476305d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material @@ -4,17 +4,55 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/ceiling_1k_ao.png" + }, "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], + "textureBlendMode": "Lerp", "textureMap": "Textures/ceiling_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "influenceMap": "Textures/ceiling_1k_ao.png", + "normalMap": "Textures/ceiling_1k_normal.png", + "roughness": 0.30000001192092898 + }, + "emissive": { + "color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.7591058015823364, + 0.43776607513427737, + 1.0 + ] + }, + "normal": { + "textureMap": "Textures/ceiling_1k_normal.png" + }, "opacity": { "factor": 1.0 + }, + "parallax": { + "algorithm": "ContactRefinement", + "factor": 0.019999999552965165, + "pdo": true, + "quality": "Medium", + "textureMap": "Textures/ceiling_1k_height.png" + }, + "roughness": { + "textureMap": "Textures/ceiling_1k_roughness.png" } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material index cdb28a8a6f..4e39112383 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material @@ -13,6 +13,17 @@ ], "textureMap": "Textures/chain_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.4891279339790344, + 0.7931944727897644, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/chain_alpha.png" }, @@ -21,7 +32,7 @@ }, "opacity": { "alphaSource": "Split", - "factor": 1.0, + "factor": 0.30000001192092898, "mode": "Cutout", "textureMap": "Textures/chain_alpha.png" }, diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material index 1889e33313..6c89c94021 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnA_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnA_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnA_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8964369893074036, + 0.8264744281768799, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnA_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.017000000923871995, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material index 095afc0ab1..0be26ba553 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnB_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnB_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnB_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9015335440635681, + 0.8348516225814819, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnB_1k_metallic.png" }, @@ -23,7 +44,6 @@ "factor": 1.0 }, "parallax": { - "enable": true, "factor": 0.020999999716877939, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material index e78cb485cc..2f1512fa4a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnC_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnC_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnC_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.9050736427307129, + 0.9050736427307129, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnC_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.014000000432133675, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material index 62942faa87..e68bc7a41a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/curtainBlue_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.06195162981748581, + 0.2056153267621994, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/curtain_normal.jpg" }, "opacity": { @@ -24,6 +40,9 @@ }, "roughness": { "textureMap": "Textures/curtain_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material index 3284cfa837..85a5ef9775 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/curtainGreen_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 1.0, + 0.029526207596063615, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/curtain_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material index d07cf6d172..086f34727c 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/curtainRed_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.023315785452723504, + 0.048538949340581897, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, @@ -24,6 +39,12 @@ }, "roughness": { "textureMap": "Textures/curtain_roughness.png" + }, + "uv": { + "center": [ + 16.0, + 0.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material index fc5f5761d8..18bd2a307b 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/details_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,15 @@ ], "textureMap": "Textures/details_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/details_1k_normal.png", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, "metallic": { "textureMap": "Textures/details_1k_metallic.png" }, @@ -24,7 +37,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.02500000037252903, "pdo": true, "textureMap": "Textures/details_1k_height.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material index 3a555c0824..fb0490f9a9 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricBlue_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 0.15049973130226136, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material index 6a95d0d275..c6074bf894 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricGreen_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 1.0, + 0.15378041565418244, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material index 2558c86819..4215d8dde5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricRed_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.08197146654129029, + 0.10267795622348786, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material index c13baae474..cbba302103 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/flagpole_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/flagpole_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.6520485281944275, + 0.7122911214828491, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/flagpole_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.014000000432133675, "pdo": true, "quality": "High", @@ -32,6 +46,9 @@ }, "roughness": { "textureMap": "Textures/flagpole_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material index cb4affe1cf..2c2abe3931 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/floor_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/floor_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "influenceMap": "Textures/floor_1k_ao.png", + "normalMap": "Textures/floor_1k_normal.png", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9404135346412659, + 0.8688944578170776, + 1.0 + ] + }, "normal": { "textureMap": "Textures/floor_1k_normal.png" }, @@ -21,7 +42,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.012000000104308129, "pdo": true, "textureMap": "Textures/floor_1k_height.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material index bb226d14cb..4508a68f3f 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material @@ -13,6 +13,23 @@ ], "textureMap": "Textures/thorn_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.05000000074505806, + "normalMap": "Textures/thorn_normal.jpg", + "roughness": 0.10000000149011612 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.46506446599960329, + 1.0, + 0.3944609761238098, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/thorn_metallic.png" }, @@ -20,7 +37,8 @@ "textureMap": "Textures/thorn_normal.jpg" }, "opacity": { - "factor": 0.5699999928474426, + "doubleSided": true, + "factor": 0.20000000298023225, "mode": "Cutout" }, "parallax": { @@ -28,6 +46,25 @@ }, "roughness": { "textureMap": "Textures/thorn_roughness.png" + }, + "subsurfaceScattering": { + "enableSubsurfaceScattering": true, + "quality": 1.0, + "scatterColor": [ + 0.28143739700317385, + 1.0, + 0.13000686466693879, + 1.0 + ], + "scatterDistance": 1.0, + "thickness": 0.10000000149011612, + "transmissionMode": "ThinObject", + "transmissionTint": [ + 0.07225146889686585, + 0.16981765627861024, + 0.04444953054189682, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material index 4b47e1b7a1..55f44b2f63 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/lion_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/lion_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.7364919781684876, + 0.3672388792037964, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/lion_1k_metallic.png" }, @@ -23,14 +38,18 @@ "factor": 1.0 }, "parallax": { - "algorithm": "POM", + "algorithm": "ContactRefinement", "enable": true, - "factor": 0.023000000044703485, + "factor": 0.009999999776482582, "pdo": true, + "quality": "Ultra", "textureMap": "Textures/lion_1k_height.png" }, "roughness": { "textureMap": "Textures/lion_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material index 3b245b251f..a64486309d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/roof_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -11,24 +15,27 @@ 0.800000011920929, 1.0 ], + "textureBlendMode": "Lerp", "textureMap": "Textures/roof_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, "metallic": { - "factor": 0.009999999776482582, "useTexture": false }, "normal": { + "factor": 0.5, + "flipY": true, "textureMap": "Textures/roof_1k_normal.jpg" }, "opacity": { "factor": 1.0 }, "parallax": { - "algorithm": "POM", - "enable": true, + "algorithm": "ContactRefinement", "factor": 0.019999999552965165, - "pdo": true, - "quality": "High", + "quality": "Medium", "textureMap": "Textures/roof_1k_height.png" }, "roughness": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material index e471de4ab9..867943642e 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vase_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/vase_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8713664412498474, + 0.6021667718887329, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/vase_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.027000000700354577, "pdo": true, "quality": "High", @@ -32,6 +46,9 @@ }, "roughness": { "textureMap": "Textures/vase_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material index 6bb8a205d1..9e96fb983d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vaseHanging_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/vaseHanging_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.765606164932251, + 1.0, + 0.7052567601203919, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/vaseHanging_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.04600000008940697, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material index 0fe458b4ac..c5bfe5c6b4 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material @@ -13,9 +13,39 @@ ], "textureMap": "Textures/vasePlant_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.6788738965988159, + 1.0, + 0.026138704270124437, + 1.0 + ] + }, "opacity": { - "factor": 0.8399999737739563, + "doubleSided": true, + "factor": 0.28999999165534975, "mode": "Cutout" + }, + "subsurfaceScattering": { + "enableSubsurfaceScattering": true, + "quality": 1.0, + "scatterColor": [ + 0.07421988248825073, + 0.10223544389009476, + 0.0, + 1.0 + ], + "subsurfaceScatterFactor": 0.0, + "transmissionMode": "ThinObject", + "transmissionTint": [ + 0.33716335892677309, + 0.4620737135410309, + 0.0, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material index d2ef595c0d..ebb4e537f5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vaseRound_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,24 @@ ], "textureMap": "Textures/vaseRound_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "influenceMap": "Textures/vaseRound_1k_ao.png", + "normalMap": "Textures/vaseRound_1k_normal.jpg", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.5939116477966309, + 0.29176774621009829, + 1.0 + ] + }, "normal": { "textureMap": "Textures/vaseRound_1k_normal.jpg" }, @@ -21,7 +43,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.019999999552965165, "pdo": true, "quality": "High", @@ -29,6 +50,9 @@ }, "roughness": { "textureMap": "Textures/vaseRound_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file From a9345646f8bf188841551ce649f89f2b22cdfe78 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 13:08:13 -0500 Subject: [PATCH 066/122] fixing a hardcoded path typo that someone submitted on accident. --- .../DccScriptingInterface/azpy/config_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py index 483e14a8ec..0b75ea4330 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py @@ -158,10 +158,10 @@ def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()): """Builds and adds local site dir libs based on py version""" from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor - _DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages" - # _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath, - # sys.version_info[0], - # sys.version_info[1]) + #_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages" + _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath, + sys.version_info[0], + sys.version_info[1]) if os.path.exists(_DCCSI_PYTHON_LIB_PATH): _LOGGER.debug('Performed site.addsitedir({})'.format(_DCCSI_PYTHON_LIB_PATH)) From 80f8c0f68b3e8b511fa7fe106adc20e23c3180eb Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Thu, 15 Apr 2021 13:21:24 -0500 Subject: [PATCH 067/122] behavior context class SceneGraph::NodeIndex -> "NodeIndex" --- .../Gem/PythonTests/CMakeLists.txt | 25 ++++++++++++++++--- .../SceneCore/Containers/SceneGraph.cpp | 4 +-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index ea9c365978..056c7982a6 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -117,12 +117,30 @@ endif() #endif() ## Editor Python Bindings ## +#if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) +# ly_add_pytest( +# NAME AutomatedTesting::EditorPythonBindings +# TEST_SUITE sandbox +# TEST_SERIAL +# PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings +# TIMEOUT 3600 +# RUNTIME_DEPENDENCIES +# Legacy::Editor +# Legacy::CryRenderNULL +# AZ::AssetProcessor +# AutomatedTesting.Assets +# Gem::EditorPythonBindings.Editor +# COMPONENT TestTools +# ) +#endif() + +## Python Asset Builder ## if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_pytest( - NAME AutomatedTesting::EditorPythonBindings - TEST_SUITE sandbox + NAME AutomatedTesting::PythonAssetBuilder + TEST_SUITE periodic TEST_SERIAL - PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings + PATH ${CMAKE_CURRENT_LIST_DIR}/PythonAssetBuilder TIMEOUT 3600 RUNTIME_DEPENDENCIES Legacy::Editor @@ -130,6 +148,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AssetProcessor AutomatedTesting.Assets Gem::EditorPythonBindings.Editor + Gem::PythonAssetBuilder.Editor COMPONENT TestTools ) endif() diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp b/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp index 934b0154c9..87c265481f 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp @@ -43,7 +43,7 @@ namespace AZ AZ::BehaviorContext* behaviorContext = azrtti_cast(context); if (behaviorContext) { - behaviorContext->Class() + behaviorContext->Class("NodeIndex") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") ->Constructor<>() @@ -57,7 +57,7 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString) ; - behaviorContext->Class() + behaviorContext->Class("SceneGraphName") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") ->Constructor() From 48e53ac66b55ea8089e57f72589b58d004cb8bf6 Mon Sep 17 00:00:00 2001 From: guthadam Date: Thu, 15 Apr 2021 13:50:29 -0500 Subject: [PATCH 068/122] Correctingtypo --- .../Code/Source/Material/EditorMaterialComponentInspector.cpp | 2 +- .../Source/Material/EditorMaterialModelUvNameMapInspector.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index cbc3222694..38e41a74b4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -535,7 +535,7 @@ namespace AZ inspector->Populate(); inspector->SetOverrides(propertyOverrideMap); - // Create the menu botton + // Create the menu button QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp index d05b618f53..1c6e338ee9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp @@ -289,7 +289,7 @@ namespace AZ MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog); inspector->Populate(); - // Create the menu botton + // Create the menu button QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); From dbae71c5119705ced5b358b32ead5cb2b79d6b8c Mon Sep 17 00:00:00 2001 From: spham Date: Thu, 15 Apr 2021 11:57:23 -0700 Subject: [PATCH 069/122] Fixes for android nightly unit tests - Fix broken test launcher caused by change in unit test module registry format - Fix test runner script's ENGINE_ROOT (re-parenting) path caused by move of file to different folder - Adding step to always perform an android sdk update to latest creating and launching android virtual device (AVD) --- cmake/Tools/common.py | 9 ++++++--- .../Android/run_test_on_android_simulator.py | 13 ++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cmake/Tools/common.py b/cmake/Tools/common.py index 1f53c37c49..563408f942 100755 --- a/cmake/Tools/common.py +++ b/cmake/Tools/common.py @@ -628,8 +628,8 @@ def get_test_module_registry(build_dir_path): test_module_items = unit_test_json['Amazon'] for _, test_module_item in test_module_items.items(): - module_file = test_module_item['Modules'] - dep_modules.append(module_file) + module_files = test_module_item['Modules'] + dep_modules.extend(module_files) except FileNotFoundError: raise LmbrCmdError(f"Unit test registry not found ('{str(unit_test_module_path)}')") @@ -659,7 +659,10 @@ def get_validated_test_modules(test_modules, build_dir_path): for test_target_check in test_modules: if test_target_check not in all_test_modules: raise LmbrCmdError(f"Invalid test module {test_target_check}") - validated_test_modules.append(test_target_check) + if isinstance(test_target_check, list): + validated_test_modules.extend(test_target_check) + else: + validated_test_modules.append(test_target_check) else: validated_test_modules = all_test_modules diff --git a/scripts/build/Platform/Android/run_test_on_android_simulator.py b/scripts/build/Platform/Android/run_test_on_android_simulator.py index e81db00537..bdbe1c6b44 100644 --- a/scripts/build/Platform/Android/run_test_on_android_simulator.py +++ b/scripts/build/Platform/Android/run_test_on_android_simulator.py @@ -20,7 +20,7 @@ import logging CURRENT_PATH = pathlib.Path(os.path.dirname(__file__)).absolute() -ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent.parent.parent +ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent class AndroidEmuError(Exception): @@ -194,6 +194,14 @@ class AndroidEmulatorManager(object): return installed_packages, available_packages, available_updates + def update_installed_sdks(self): + """ + Run an SDK Manager update to make sure the SDKs are all up-to-date + """ + logging.info(f"Updating android SDK...") + self.sdk_manager_cmd.run(['--update']) + + def install_system_package_if_necessary(self): """ Make sure that we have the correct system image installed, and install if not @@ -503,6 +511,9 @@ def process_unit_test_on_simulator(base_android_sdk_path, build_path, build_conf manager = AndroidEmulatorManager(base_android_sdk_path=base_android_sdk_path, force_avd_creation=True) + # Make sure that the android SDK is up to date + manager.update_installed_sdks() + # First Install or overwrite the unit test emulator manager.install_unit_test_avd() From 020d7801bb625b8b7211dfb62bc45129b7cf7533 Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Thu, 15 Apr 2021 14:28:57 -0500 Subject: [PATCH 070/122] Make sure Recent Files list is correctly enabled/disabled when the list changes (#73) Make sure Recent Files list is correctly enabled/disabled when the recent files list changes --- .../AssetEditor/AssetEditorWidget.cpp | 20 ++++++++++++++++++- .../AssetEditor/AssetEditorWidget.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp index 603c7a8023..706d8243e2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp @@ -256,6 +256,8 @@ namespace AzToolsFramework m_userSettings = AZ::UserSettings::CreateFind(k_assetEditorWidgetSettings, AZ::UserSettings::CT_LOCAL); + UpdateRecentFileListState(); + QObject::connect(m_recentFileMenu, &QMenu::aboutToShow, this, &AssetEditorWidget::PopulateRecentMenu); } @@ -952,7 +954,8 @@ namespace AzToolsFramework void AssetEditorWidget::AddRecentPath(const AZStd::string& recentPath) { - m_userSettings->AddRecentPath(recentPath); + m_userSettings->AddRecentPath(recentPath); + UpdateRecentFileListState(); } void AssetEditorWidget::PopulateRecentMenu() @@ -989,6 +992,21 @@ namespace AzToolsFramework m_saveAsAssetAction->setEnabled(true); } + void AssetEditorWidget::UpdateRecentFileListState() + { + if (m_recentFileMenu) + { + if (!m_userSettings || m_userSettings->m_recentPaths.empty()) + { + m_recentFileMenu->setEnabled(false); + } + else + { + m_recentFileMenu->setEnabled(true); + } + } + } + } // namespace AssetEditor } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h index b27d69dba5..4379fc27ed 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h @@ -122,6 +122,8 @@ namespace AzToolsFramework void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; + void UpdateRecentFileListState(); + private: void DirtyAsset(); From a9516c6498b6b92e8e18b02b638e6d98154806d4 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 15:04:36 -0500 Subject: [PATCH 071/122] updated the ref to dccsi env that changed --- Gems/AtomContent/Sponza/Project_Env.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomContent/Sponza/Project_Env.bat b/Gems/AtomContent/Sponza/Project_Env.bat index ae21e6ebc4..46d4663c34 100644 --- a/Gems/AtomContent/Sponza/Project_Env.bat +++ b/Gems/AtomContent/Sponza/Project_Env.bat @@ -44,7 +44,7 @@ CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH% set LY_DEV=%CD% echo LY_DEV = %LY_DEV% -CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat +CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat rem :: Constant Vars (Global) rem SET LYPY_GDEBUG=0 From 66517b22e04d250a1e0e6a287800e686d4431e54 Mon Sep 17 00:00:00 2001 From: spham Date: Thu, 15 Apr 2021 13:06:27 -0700 Subject: [PATCH 072/122] Updating how to calculate the ENGINE_ROOT path based on the CURRENT_PATH value --- .../build/Platform/Android/run_test_on_android_simulator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build/Platform/Android/run_test_on_android_simulator.py b/scripts/build/Platform/Android/run_test_on_android_simulator.py index bdbe1c6b44..1fc2e19636 100644 --- a/scripts/build/Platform/Android/run_test_on_android_simulator.py +++ b/scripts/build/Platform/Android/run_test_on_android_simulator.py @@ -20,7 +20,8 @@ import logging CURRENT_PATH = pathlib.Path(os.path.dirname(__file__)).absolute() -ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent +# The engine root is based on the location of this file (/scripts/build/Platform/Android). Walk up to calculate the engine root +ENGINE_ROOT = CURRENT_PATH.parents[3] class AndroidEmuError(Exception): From ef30f49bf9cc6152dc6a2afc82c4625fff3627fd Mon Sep 17 00:00:00 2001 From: qingtao Date: Thu, 15 Apr 2021 13:29:29 -0700 Subject: [PATCH 073/122] Fixed a linux compile issue. --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index c00533f740..eb0e295129 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -725,7 +725,7 @@ namespace AZ ImGui::BeginTooltip(); ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); - ImGui::Text("Duration in ticks: %u", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks()); ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); ImGui::EndTooltip(); } From abf26eede19f53876e7aa8d511a147cc1c3ac7eb Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 14:00:40 -0700 Subject: [PATCH 074/122] Bump REsourcePoolBuilder as the bufferBindFlags were updated --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 7f617f4c6c..812198668d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 1; + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 7902eafd7d0c34b618cd1aa83b06aa7c87a49409 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 15:20:55 -0700 Subject: [PATCH 075/122] Add empty pal files for platforms other than Mac --- cmake/3rdParty/FindOpenGLInterface.cmake | 4 +--- .../Platform/Android/OpenGLInterface_android.cmake | 10 ++++++++++ .../Platform/Android/cmake_android_files.cmake | 1 + .../Platform/Linux/OpenGLInterface_linux.cmake | 10 ++++++++++ cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake | 1 + .../Platform/Windows/OpenGLInterface_windows.cmake | 10 ++++++++++ .../Platform/Windows/cmake_windows_files.cmake | 1 + cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake | 10 ++++++++++ cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake | 1 + 9 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake create mode 100644 cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake create mode 100644 cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake create mode 100644 cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake index 7b537d1378..99bf19c4d7 100644 --- a/cmake/3rdParty/FindOpenGLInterface.cmake +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -16,6 +16,4 @@ add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -if(EXISTS ${pal_file}) - include(${pal_file}) -endif() \ No newline at end of file +include(${pal_file}) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake @@ -0,0 +1,10 @@ +# +# 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. +# diff --git a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake index 07e453f862..93d1f3386b 100644 --- a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake +++ b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake @@ -12,6 +12,7 @@ set(FILES BuiltInPackages_android.cmake civetweb_android.cmake + OpenGLInterface_android.cmake VkValidation_android.cmake Wwise_android.cmake ) diff --git a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake @@ -0,0 +1,10 @@ +# +# 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. +# diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index 2b1ba4d0e5..cce929b909 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -16,6 +16,7 @@ set(FILES Clang_linux.cmake dyad_linux.cmake FbxSdk_linux.cmake + OpenGLInterface_linux.cmake OpenSSL_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake @@ -0,0 +1,10 @@ +# +# 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. +# diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 2c7890fcc4..675ae7f695 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -18,6 +18,7 @@ set(FILES dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake + OpenGLInterface_windows.cmake OpenSSL_windows.cmake Wwise_windows.cmake ) diff --git a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake @@ -0,0 +1,10 @@ +# +# 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. +# diff --git a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake index e32a9f75bb..242e1e91b0 100644 --- a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake +++ b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake @@ -11,6 +11,7 @@ set(FILES BuiltInPackages_ios.cmake + OpenGLInterface_ios.cmake OpenSSL_ios.cmake RadTelemetry_ios.cmake Wwise_ios.cmake From f76322d13d5916d7e38079050f234faa29036f2e Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 15:59:30 -0700 Subject: [PATCH 076/122] Remove Android/iOS pal files since OpenGL is only needed by host tools. --- .../Platform/Android/OpenGLInterface_android.cmake | 10 ---------- .../Platform/Android/cmake_android_files.cmake | 1 - cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake | 10 ---------- cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake | 1 - 4 files changed, 22 deletions(-) delete mode 100644 cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake delete mode 100644 cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake diff --git a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake index 93d1f3386b..07e453f862 100644 --- a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake +++ b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages_android.cmake civetweb_android.cmake - OpenGLInterface_android.cmake VkValidation_android.cmake Wwise_android.cmake ) diff --git a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake index 242e1e91b0..e32a9f75bb 100644 --- a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake +++ b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_ios.cmake - OpenGLInterface_ios.cmake OpenSSL_ios.cmake RadTelemetry_ios.cmake Wwise_ios.cmake From 61c24084e883a43d1a6f583899d22b5d680c550e Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 16:13:22 -0700 Subject: [PATCH 077/122] Enable Null RHI for AutomatedTesting --- .../Gem/Code/Platform/Windows/runtime_dependencies.cmake | 1 + .../Gem/Code/Platform/Windows/tool_dependencies.cmake | 2 ++ .../Template/Code/Platform/Mac/mac_runtime_dependencies.cmake | 1 + .../Template/Code/Platform/Mac/mac_tool_dependencies.cmake | 1 + .../Code/Platform/Windows/windows_runtime_dependencies.cmake | 1 + .../Code/Platform/Windows/windows_tool_dependencies.cmake | 2 ++ 6 files changed, 8 insertions(+) diff --git a/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake index 617816dcd0..0a1541bcfc 100644 --- a/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake @@ -12,4 +12,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Private Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private ) \ No newline at end of file diff --git a/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake index d13d0fb180..ddd3bfa6a7 100644 --- a/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake @@ -15,5 +15,7 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Private Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders Gem::Atom_RHI_Metal.Builders ) \ No newline at end of file diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake index e49929c6e1..2821493346 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake @@ -11,4 +11,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Null.Private ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake index eea4bb1dce..adf5485ed4 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake @@ -14,4 +14,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Metal.Builders Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Builders ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake index c5e1b4bc2e..514a61aa57 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake @@ -12,4 +12,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Private Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake index 304f97d590..b7f4b82126 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake @@ -14,4 +14,6 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Private Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders ) From 8074e0fb186aea840feaa9ebed561c08eadb7ffe Mon Sep 17 00:00:00 2001 From: karlberg Date: Thu, 15 Apr 2021 17:56:08 -0700 Subject: [PATCH 078/122] Remove formal template parameter name to resolve shadowed variable warning on clang --- .../AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h index a91f42b3a0..3d064b5ecc 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h @@ -115,7 +115,7 @@ namespace AzNetworking ContainerType m_container; - template + template friend class FixedSizeVectorBitset; }; } From d3520ddcf13413cbedcbe25634ec03ae38cb997b Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 15 Apr 2021 17:59:09 -0700 Subject: [PATCH 079/122] Adding "copy name" and "copy path" to Material Editor --- .../Source/Window/MaterialBrowserInteractions.cpp | 15 +++++++++++++++ .../Source/Window/MaterialBrowserInteractions.h | 1 + 2 files changed, 16 insertions(+) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp index c4601baff2..b0412c001c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -61,6 +62,8 @@ namespace MaterialEditor m_caller = nullptr; }); + AddGenericContextMenuActions(caller, menu, entry); + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { const auto source = azalias_cast(entry); @@ -84,6 +87,18 @@ namespace MaterialEditor } } + void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetName().c_str()); + }); + menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetFullPath().c_str()); + }); + } + void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) { menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h index 07e2be2d59..2806cee6d4 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h @@ -44,6 +44,7 @@ namespace MaterialEditor //! AssetBrowserInteractionNotificationBus::Handler overrides... void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) override; + void AddGenericContextMenuActions(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry); void AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); void AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); void AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); From 4edbf7890bfc15890a9b5b6b0f5c205c09568df6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 15 Apr 2021 19:01:15 -0700 Subject: [PATCH 080/122] Bringing fix that has not been migrated to github yet (fixes Windows release builds) --- AutomatedTesting/Gem/PythonTests/CMakeLists.txt | 1 + Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index ea9c365978..b7a5f85087 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -138,6 +138,7 @@ endif() if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_pytest( NAME AutomatedTesting::BlastTests + TEST_SUITE sandbox TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py TIMEOUT 3600 diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h index 29b2bfc4b5..44fa5b09e1 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h @@ -34,7 +34,6 @@ namespace AZ #if !defined(IMGUI_ENABLED) class DebugConsole {}; #else -#endif // defined(IMGUI_ENABLED) //////////////////////////////////////////////////////////////////////////////////////////////// //! A debug console used to enter debug console commands and display debug log messages. //! @@ -132,4 +131,5 @@ namespace AZ bool m_autoScroll = true; //!< Should we auto-scroll as new entries are added? bool m_forceScroll = false; //!< Do we need to force scroll after input entered? }; +#endif // defined(IMGUI_ENABLED) } // namespace AZ From bff55bd688024e9430e12dca0a6dd1f0250c1ed4 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 22:27:11 -0500 Subject: [PATCH 081/122] LYN-2726 Updated the Settings Registry Merge Utils logic to determine the project root and engine root to fix issues with running the Editor or AssetProcessor from within the project folder overriding the project_path with the engine root bootstrap.cfg project_path entry The order in which the project path is overridden as follows 1. The /bootstrap.cfg is first merged into the Settings Registry. Any '/Amazon/AzCore/Bootstrap/project_path' would be used if the following steps don't override that key. 2. Followed by general *.setreg/*.setregpatch files being merged into the Settings Registry which can override the '/Amazon/AzCore/Bootstrap/project_path' key 3. Next a project.json file searched upwards from the current executable directory to determine the project path 4. Finally if a command line parameter that overrides the project path is supplied it is used instead --- .../AzCore/Component/ComponentApplication.cpp | 27 +++- .../Settings/SettingsRegistryMergeUtils.cpp | 119 +++++++++++------ .../Settings/SettingsRegistryMergeUtils.h | 17 +++ .../ProjectManager/ProjectManager.cpp | 6 + .../API/ToolsApplicationAPI.h | 10 -- .../Application/ToolsApplication.cpp | 126 ------------------ .../Application/ToolsApplication.h | 6 - .../UI/PropertyEditor/PropertyAssetCtrl.cpp | 6 +- .../Editor/AssetEditor/AssetEditorWindow.cpp | 9 +- Code/Sandbox/Editor/PythonEditorFuncs.cpp | 7 +- Code/Sandbox/Editor/ToolBox.cpp | 7 +- 11 files changed, 136 insertions(+), 204 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index b8d3e12712..de97842cee 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -178,14 +178,16 @@ namespace AZ //! on an update to '/Amazon/AzCore/Bootstrap/project_path' key. struct UpdateProjectSettingsEventHandler { - UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry) + UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine) : m_registry{ registry } + , m_commandLine{ commandLine } { } void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type) { using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + // #1 Update the project settings when the project path is set const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; AZ::IO::FixedMaxPath newProjectPath; if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path) @@ -194,6 +196,7 @@ namespace AZ UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath)); } + // #2 Update the project specialization when the project name is set const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name"; FixedValueString newProjectName; if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path) @@ -201,6 +204,12 @@ namespace AZ { UpdateProjectSpecializationFromProjectName(newProjectName); } + + // #3 Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry + if (path == AZ::SettingsRegistryMergeUtils::CommandLineValueChangedKey) + { + UpdateCommandLine(); + } } //! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path @@ -233,10 +242,16 @@ namespace AZ AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry); } + void UpdateCommandLine() + { + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine); + } + private: AZ::IO::FixedMaxPath m_oldProjectPath; AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName; AZ::SettingsRegistryInterface& m_registry; + AZ::CommandLine& m_commandLine; }; void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app) @@ -415,6 +430,12 @@ namespace AZ // Add the Command Line arguments into the SettingsRegistry SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine); + // Add a notifier to update the project_settings when + // 1. The 'project_path' key changes + // 2. The project specialization when the 'project-name' key changes + // 3. The ComponentApplication command line when the command line is stored to the registry + m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry, m_commandLine }); + // Merge Command Line arguments constexpr bool executeRegDumpCommands = false; SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands); @@ -429,10 +450,6 @@ namespace AZ // for the application root. CalculateAppRoot(); - // Add a notifier to update the /Amazon/AzCore/Settings/Specializations - // when the 'project_path' property changes within the SettingsRegistry - m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry }); - // Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created. SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry); SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 392e95bf6e..f84ff354b2 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -132,23 +132,14 @@ namespace AZ::Internal AZ::IO::FixedMaxPath ScanUpRootLocator(AZStd::string_view rootFileToLocate) { - - AZStd::fixed_string executableDir; - if (AZ::Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity()) == Utils::ExecutablePathResult::Success) - { - // Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string - // stored within it - executableDir.resize_no_construct(AZStd::char_traits::length(executableDir.data())); - } - - AZ::IO::FixedMaxPath engineRootCandidate{ executableDir }; + AZ::IO::FixedMaxPath rootCandidate{ AZ::Utils::GetExecutableDirectory() }; bool rootPathVisited = false; do { - if (AZ::IO::SystemFile::Exists((engineRootCandidate / rootFileToLocate).c_str())) + if (AZ::IO::SystemFile::Exists((rootCandidate / rootFileToLocate).c_str())) { - return engineRootCandidate; + return rootCandidate; } // Note for posix filesystems the parent directory of '/' is '/' and for windows @@ -156,38 +147,69 @@ namespace AZ::Internal // Validate that the parent directory isn't itself, that would imply // that it is the filesystem root path - AZ::IO::PathView parentPath = engineRootCandidate.ParentPath(); - rootPathVisited = (engineRootCandidate == parentPath); + AZ::IO::PathView parentPath = rootCandidate.ParentPath(); + rootPathVisited = (rootCandidate == parentPath); // Recurse upwards one directory - engineRootCandidate = AZStd::move(parentPath); + rootCandidate = AZStd::move(parentPath); } while (!rootPathVisited); return {}; } + void InjectSettingToCommandLineFront(AZ::SettingsRegistryInterface& settingsRegistry, + AZStd::string_view path, AZStd::string_view value) + { + AZ::CommandLine commandLine; + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine); + AZ::CommandLine::ParamContainer paramContainer; + commandLine.Dump(paramContainer); + + auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")", + aznumeric_cast(path.size()), path.data(), aznumeric_cast(value.size()), value.data()); + paramContainer.emplace(paramContainer.begin(), AZStd::move(projectPathOverride)); + commandLine.Parse(paramContainer); + AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); + } } // namespace AZ::Internal namespace AZ::SettingsRegistryMergeUtils { + constexpr AZStd::string_view InternalScanUpEngineRootKey{ "/O3DE/Settings/Internal/engine_root_scan_up_path" }; + constexpr AZStd::string_view InternalScanUpProjectRootKey{ "/O3DE/Settings/Internal/project_root_scan_up_path" }; + AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry) { AZ::IO::FixedMaxPath engineRoot; - // This is the 'external' engine root key, as in passed from command-line or .setreg files. auto engineRootKey = SettingsRegistryInterface::FixedValueString::format("%s/engine_path", BootstrapSettingsRootKey); + + // Step 1 Run the scan upwards logic once to find the location of the engine.json if it exist + // Once this step is run the {InternalScanUpEngineRootKey} is set in the Settings Registry + // to have this scan logic only run once InternalScanUpEngineRootKey the supplied registry + if (settingsRegistry.GetType(InternalScanUpEngineRootKey) == SettingsRegistryInterface::Type::NoType) + { + // We can scan up from exe directory to find engine.json, use that for engine root if it exists. + engineRoot = Internal::ScanUpRootLocator("engine.json"); + // Set the {InternalScanUpEngineRootKey} to make sure this code path isn't called again for this settings registry + settingsRegistry.Set(InternalScanUpEngineRootKey, engineRoot.Native()); + if (!engineRoot.empty()) + { + settingsRegistry.Set(engineRootKey, engineRoot.Native()); + // Inject the engine root into the front of the command line settings + Internal::InjectSettingToCommandLineFront(settingsRegistry, engineRootKey, engineRoot.Native()); + return engineRoot; + } + } + + // Step 2 check if the engine_path key has been supplied if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty()) { return engineRoot; } - // We can scan up from exe directory to find engine.json, use that for engine root if it exists. - if (engineRoot = Internal::ScanUpRootLocator("engine.json"); !engineRoot.empty()) - { - settingsRegistry.Set(engineRootKey, engineRoot.c_str()); - return engineRoot; - } - + // Step 3 locate the project root and attempt to find the engine root using the registered engine + // for the project in the project.json file AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry); if (projectRoot.empty()) { @@ -207,16 +229,30 @@ namespace AZ::SettingsRegistryMergeUtils AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry) { AZ::IO::FixedMaxPath projectRoot; - // This is the 'external' project root key, as in passed from command-line or .setreg files. - auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey); - if (settingsRegistry.Get(projectRoot.Native(), projectRootKey)) + const auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey); + + // Step 1 Run the scan upwards logic once to find the location of the project.json if it exist + // Once this step is run the {InternalScanUpProjectRootKey} is set in the Settings Registry + // to have this scan logic only run once for the supplied registry + // SettingsRegistryInterface::GetType is used to check if a key is set + if (settingsRegistry.GetType(InternalScanUpProjectRootKey) == SettingsRegistryInterface::Type::NoType) { - return projectRoot; + projectRoot = Internal::ScanUpRootLocator("project.json"); + // Set the {InternalScanUpProjectRootKey} to make sure this code path isn't called again for this settings registry + settingsRegistry.Set(InternalScanUpProjectRootKey, projectRoot.Native()); + if (!projectRoot.empty()) + { + settingsRegistry.Set(projectRootKey, projectRoot.c_str()); + // Inject the project root into the front of the command line settings + Internal::InjectSettingToCommandLineFront(settingsRegistry, projectRootKey, projectRoot.Native()); + return projectRoot; + } } - if (projectRoot = Internal::ScanUpRootLocator("project.json"); !projectRoot.empty()) + // Step 2 Check the project-path key + // This is the project path root key, as in passed from command-line or .setreg files. + if (settingsRegistry.Get(projectRoot.Native(), projectRootKey)) { - settingsRegistry.Set(projectRootKey, projectRoot.c_str()); return projectRoot; } @@ -463,18 +499,6 @@ namespace AZ::SettingsRegistryMergeUtils void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry) { ConfigParserSettings parserSettings; - parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view - { - constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" }; - for (AZStd::string_view commentPrefix : commentPrefixes) - { - if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos) - { - return line.substr(0, commentOffset); - } - } - return line; - }; parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey; MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings); } @@ -807,6 +831,11 @@ namespace AZ::SettingsRegistryMergeUtils ++argumentIndex; commandLinePath.resize(commandLineRootSize); } + + // This key is used allow Notification Handlers to know when the command line has been updated within the + // registry. The value itself is meaningless. The JSON path of {CommandLineValueChangedKey} + // being passed to the Notification Event Handler indicates that the command line has be updated + registry.Set(CommandLineValueChangedKey, true); } bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine) @@ -823,10 +852,16 @@ namespace AZ::SettingsRegistryMergeUtils } else if (valueName == "Value" && !value.empty()) { - m_arguments.push_back(value); + // Make sure value types are in quotes in case they start with a command option prefix + m_arguments.push_back(QuoteArgument(value)); } } + AZStd::string QuoteArgument(AZStd::string_view arg) + { + return !arg.empty() ? AZStd::string::format(R"("%.*s")", aznumeric_cast(arg.size()), arg.data()) : AZStd::string{ arg }; + } + // The first parameter is skipped by the ComamndLine::Parse function so initialize // the container with one empty element AZ::CommandLine::ParamContainer m_arguments{ 1 }; diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index dad6c36d0f..10b3c2f18b 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -57,6 +57,9 @@ namespace AZ::SettingsRegistryMergeUtils //! Root key for where command line are stored at within the settings registry inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine"; + //! Key set to trigger a notification that the CommandLine has been stored within the settings registry + //! The value of the key has no meaning. Notification Handlers only need to check if the key was supplied + inline static constexpr char CommandLineValueChangedKey[] = "/Amazon/AzCore/Runtime/CommandLineChanged"; //! Root key where raw project settings (project.json) file is merged to settings registry inline static constexpr char ProjectSettingsRootKey[] = "/Amazon/Project/Settings"; @@ -74,6 +77,20 @@ namespace AZ::SettingsRegistryMergeUtils //! If it's still not found, attempt to find the project (by similar means) then reconcile the //! engine root by inspecting project.json and the engine manifest file. AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry); + + //! The algorithm that is used to find the project root is as follows + //! 1. The first time this function is it performs a upward scan for a project.json file from + //! the executable directory and if found stores that path to an internal key. + //! In the same step it injects the path into the front of list of command line parameters + //! using the --regset="{BootstrapSettingsRootKey}/project_path=" value + //! 2. Next the "{BootstrapSettingsRootKey}/project_path" is checked to see if it has a project path set + //! + //! The order in which the project path settings are overridden proceeds in the following order + //! 1. project_path set in the /bootstrap.cfg file + //! 2. project_path set in a *.setreg/*.setregpatch file + //! 3. project_path found by scanning upwards from the executable directory to the project.json path + //! 4. project_path set on the Command line via either --regset="{BootstrapSettingsRootKey}/project_path=" + //! or --project_path= AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry); //! Query the specializations that will be used when loading the Settings Registry. diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 5acf4e75d1..7e968ffcd8 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -42,8 +42,14 @@ namespace AzFramework::ProjectManager AZ::CommandLine commandLine; commandLine.Parse(argc, argv); AZ::SettingsRegistryImpl settingsRegistry; + // Store the Command line to the Setting Registry + + AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); + // Retrieve Command Line from Settings Registry, it may have been updated by the call to FindEngineRoot() + // in MergeSettingstoRegistry_ConfigFile + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(settingsRegistry, commandLine, false); engineRootPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(settingsRegistry); projectRootPath = AZ::SettingsRegistryMergeUtils::FindProjectRoot(settingsRegistry); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index 0c631cf09e..f12ab71936 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -578,16 +578,6 @@ namespace AzToolsFramework */ virtual bool IsEditorInIsolationMode() = 0; - /*! - * Get the engine root path that the current tool is running under. - */ - virtual const char* GetEngineRootPath() const = 0; - - /** - * Get the version of the engine the current tools application is running under - */ - virtual const char* GetEngineVersion() const = 0; - /** * Creates and adds a new entity to the tools application from components which match at least one of the requiredTags * The tag matching occurs on AZ::Edit::SystemComponentTags attribute from the reflected class data in the serialization context diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 352048f5f0..22c1390828 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -224,112 +224,6 @@ namespace AzToolsFramework } // Internal -#define AZ_MAX_ENGINE_VERSION_LEN 64 - // Private Implementation class to manage the engine root and version - // Note: We are not using any AzCore classes because the ToolsApplication - // initialization happens early on, before the Allocators get instantiated, - // so we are using Qt privately instead - class ToolsApplication::EngineConfigImpl - { - private: - friend class ToolsApplication; - - typedef QMap EngineJsonMap; - - EngineConfigImpl(const char* logWindow, const char* fileName) - : m_logWindow(logWindow) - , m_fileName(fileName) - { - m_engineRoot[0] = '\0'; - m_engineVersion[0] = '\0'; - } - - char m_engineRoot[AZ_MAX_PATH_LEN]; - char m_engineVersion[AZ_MAX_ENGINE_VERSION_LEN]; - EngineJsonMap m_engineConfigMap; - const char* m_logWindow; - const char* m_fileName; - - - // Read an engine configuration into a map of key/value pairs - bool ReadEngineConfigIntoMap(QString engineJsonPath, EngineJsonMap& engineJsonMap) - { - QFile engineJsonFile(engineJsonPath); - if (!engineJsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { - AZ_Warning(m_logWindow, false, "Unable to open file '%s' in the current root directory", engineJsonPath.toUtf8().data()); - return false; - } - - QByteArray engineJsonData = engineJsonFile.readAll(); - engineJsonFile.close(); - QJsonDocument engineJsonDoc(QJsonDocument::fromJson(engineJsonData)); - if (engineJsonDoc.isNull()) - { - AZ_Warning(m_logWindow, false, "Unable to read file '%s' in the current root directory", engineJsonPath.toUtf8().data()); - return false; - } - - QJsonObject engineJsonRoot = engineJsonDoc.object(); - for (const QString& configKey : engineJsonRoot.keys()) - { - QJsonValue configValue = engineJsonRoot[configKey]; - if (configValue.isString() || configValue.isDouble()) - { - // Only map strings and numbers, ignore every other type - engineJsonMap[configKey] = configValue.toString(); - } - else - { - AZ_Warning(m_logWindow, false, "Ignoring key '%s' from '%s', unsupported type.", configKey.toUtf8().data(), engineJsonPath.toUtf8().data()); - } - } - return true; - } - - // Initialize the engine config object based on the current - bool Initialize(const char* currentEngineRoot) - { - // Start with the app root as the engine root (legacy), but check to see if the engine root - // is external to the app root - azstrncpy(m_engineRoot, AZ_ARRAY_SIZE(m_engineRoot), currentEngineRoot, strlen(currentEngineRoot) + 1); - - // From the appRoot, check and see if we can read any external engine reference in engine.json - QString engineJsonFileName = QString(m_fileName); - QString engineJsonFilePath = QDir(currentEngineRoot).absoluteFilePath(engineJsonFileName); - - // From the appRoot, check and see if we can read any external engine reference in engine.json - if (!QFile::exists(engineJsonFilePath)) - { - AZ_Warning(m_logWindow, false, "Unable to find '%s' in the current app root directory.", m_fileName); - return false; - } - if (!ReadEngineConfigIntoMap(engineJsonFilePath, m_engineConfigMap)) - { - AZ_Warning(m_logWindow, false, "Defaulting root engine path to '%s'", currentEngineRoot); - return false; - } - - // Read in the local engine version value - auto localEngineVersionValue = m_engineConfigMap.find(QString(AzToolsFramework::Internal::s_engineConfigEngineVersionKey)); - QString localEngineVersion(localEngineVersionValue.value()); - azstrncpy(m_engineVersion, AZ_ARRAY_SIZE(m_engineVersion), localEngineVersion.toUtf8().data(), localEngineVersion.length() + 1); - - return true; - } - - const char* GetEngineRoot() const - { - return m_engineRoot; - } - - const char* GetEngineVersion() const - { - return m_engineVersion; - } - }; - - ToolsApplication::ToolsApplication(int* argc, char*** argv) : AzFramework::Application(argc, argv) , m_selectionBounds(AZ::Aabb()) @@ -339,7 +233,6 @@ namespace AzToolsFramework , m_isInIsolationMode(false) { ToolsApplicationRequests::Bus::Handler::BusConnect(); - m_engineConfigImpl.reset(new ToolsApplication::EngineConfigImpl(AzToolsFramework::Internal::s_startupLogWindow, AzToolsFramework::Internal::s_engineConfigFileName)); m_undoCache.RegisterToUndoCacheInterface(); } @@ -391,7 +284,6 @@ namespace AzToolsFramework void ToolsApplication::Start(const Descriptor& descriptor, const StartupParameters& startupParameters/* = StartupParameters()*/) { Application::Start(descriptor, startupParameters); - InitializeEngineConfig(); m_editorEntityManager.Start(); @@ -399,14 +291,6 @@ namespace AzToolsFramework AZ_Assert(m_editorEntityAPI, "ToolsApplication - Could not retrieve instance of EditorEntityAPI"); } - void ToolsApplication::InitializeEngineConfig() - { - if (!m_engineConfigImpl->Initialize(GetEngineRoot())) - { - AZ_Warning(AzToolsFramework::Internal::s_startupLogWindow, false, "Defaulting engine root path to '%s'", GetEngineRoot()); - } - } - void ToolsApplication::StartCommon(AZ::Entity* systemEntity) { Application::StartCommon(systemEntity); @@ -1832,16 +1716,6 @@ namespace AzToolsFramework return m_isInIsolationMode; } - const char* ToolsApplication::GetEngineRootPath() const - { - return m_engineConfigImpl->GetEngineRoot(); - } - - const char* ToolsApplication::GetEngineVersion() const - { - return m_engineConfigImpl->GetEngineVersion(); - } - void ToolsApplication::CreateAndAddEntityFromComponentTags(const AZStd::vector& requiredTags, const char* entityName) { if (!entityName || !entityName[0]) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index ef9f190309..0f038422ce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -150,8 +150,6 @@ namespace AzToolsFramework void EnterEditorIsolationMode() override; void ExitEditorIsolationMode() override; bool IsEditorInIsolationMode() override; - const char* GetEngineRootPath() const override; - const char* GetEngineVersion() const override; void CreateAndAddEntityFromComponentTags(const AZStd::vector& requiredTags, const char* entityName) override; @@ -174,7 +172,6 @@ namespace AzToolsFramework void CreateUndosForDirtyEntities(); void ConsistencyCheckUndoCache(); - void InitializeEngineConfig(); AZ::Aabb m_selectionBounds; EntityIdList m_selectedEntities; EntityIdList m_highlightedEntities; @@ -186,9 +183,6 @@ namespace AzToolsFramework bool m_isInIsolationMode; EntityIdSet m_isolatedEntityIdSet; - class EngineConfigImpl; - AZStd::unique_ptr m_engineConfigImpl; - EditorEntityAPI* m_editorEntityAPI = nullptr; EditorEntityManager m_editorEntityManager; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index bc27ffa5e1..261645e79a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -38,6 +38,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -1212,9 +1213,8 @@ namespace AzToolsFramework if (!QFile::exists(path)) { - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); path = engineDir.absoluteFilePath(iconPath.c_str()); } diff --git a/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp b/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp index 4645019261..53e2884943 100644 --- a/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp +++ b/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp @@ -20,6 +20,7 @@ // AzCore #include #include +#include // AzToolsFramework #include @@ -104,13 +105,9 @@ void AssetEditorWindow::SaveAssetAs(const AZStd::string_view assetPath) return; } - const char* engineRoot; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); + auto absoluteAssetPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / assetPath; - AZStd::string absoluteAssetPath; - AzFramework::StringFunc::Path::Join(engineRoot, assetPath.data(), absoluteAssetPath); - - if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath)) + if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath.Native())) { AZ_Warning("Asset Editor", false, "File was not saved correctly via SaveAssetAs."); } diff --git a/Code/Sandbox/Editor/PythonEditorFuncs.cpp b/Code/Sandbox/Editor/PythonEditorFuncs.cpp index 5c74a950c2..f5de22387c 100644 --- a/Code/Sandbox/Editor/PythonEditorFuncs.cpp +++ b/Code/Sandbox/Editor/PythonEditorFuncs.cpp @@ -19,6 +19,8 @@ #include #include +#include + // AzToolsFramework #include #include @@ -293,9 +295,8 @@ namespace // If not found try editor folder if (!CFileUtil::FileExists(path)) { - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); QString scriptFolder = engineDir.absoluteFilePath("Editor/Scripts/"); Path::ConvertBackSlashToSlash(scriptFolder); diff --git a/Code/Sandbox/Editor/ToolBox.cpp b/Code/Sandbox/Editor/ToolBox.cpp index def7329e83..46c01ce864 100644 --- a/Code/Sandbox/Editor/ToolBox.cpp +++ b/Code/Sandbox/Editor/ToolBox.cpp @@ -18,6 +18,8 @@ #include "ToolBox.h" +#include + // AzToolsFramework #include #include @@ -419,9 +421,8 @@ void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolb } } - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); string enginePath = PathUtil::AddSlash(engineDir.absolutePath().toUtf8().data()); From ee3f157fb8620e340f921a8b581b0273a2339c78 Mon Sep 17 00:00:00 2001 From: karlberg Date: Thu, 15 Apr 2021 20:41:08 -0700 Subject: [PATCH 082/122] Fix memory leak in multiplayer unit test --- Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp index 13adc6d774..c18c2ee5e3 100644 --- a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp +++ b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp @@ -97,6 +97,10 @@ namespace UnitTest m_mpComponent->OnConnect(&connMock2); EXPECT_EQ(m_connectionAcquiredCount, 25); + + // Clean up connection data + m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local); + m_mpComponent->OnDisconnect(&connMock2, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local); } } From 89a935cd29b4daf0f77d4f637fbc85fa46ae07fc Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:44:01 -0700 Subject: [PATCH 083/122] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 812198668d..6a94a46b93 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 2; //ATOM-15196 + builderDescriptor.m_version = 3; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 05359187c4a2d4aca2d15e59ffff771eaee8588d Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:45:53 -0700 Subject: [PATCH 084/122] Test update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 6a94a46b93..812198668d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 3; //ATOM-15196 + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From d0435b448959e69a38b7c914954ca40f75c6c1c8 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:46:48 -0700 Subject: [PATCH 085/122] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 812198668d..6a94a46b93 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 2; //ATOM-15196 + builderDescriptor.m_version = 3; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From ca86068d8338a9484eccb08a8925a4b166fa3b32 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:55:54 -0700 Subject: [PATCH 086/122] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 6a94a46b93..92c30c28b1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 3; //ATOM-15196 + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 1363a5b76ca15fd8dd276fc8c347ce3031b14b01 Mon Sep 17 00:00:00 2001 From: greerdv Date: Fri, 16 Apr 2021 16:52:30 +0100 Subject: [PATCH 087/122] fixing bugs with failing to disconnect from non-uniform scale event handlers in multiple places --- .../Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp | 1 + Gems/PhysX/Code/Source/EditorColliderComponent.cpp | 2 ++ Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp | 1 + Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 1 + Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp | 1 + 5 files changed, 6 insertions(+) diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp index 0ea6be5e4d..3f36840e3d 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp @@ -65,6 +65,7 @@ namespace LmbrCentral ShapeComponentNotificationsBus::Handler::BusDisconnect(); PolygonPrismShapeComponentNotificationBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); DestroyManipulators(); } diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 4b72eb32ad..c470c05c58 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -391,6 +391,8 @@ namespace PhysX Physics::WorldBodyRequestBus::Handler::BusDisconnect(); m_colliderDebugDraw.Disconnect(); AZ::Data::AssetBus::MultiHandler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); + EditorColliderComponentRequestBus::Handler::BusDisconnect(); AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect(); LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); ColliderShapeRequestBus::Handler::BusDisconnect(); diff --git a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp index 1dd25ced32..b4b730538d 100644 --- a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp @@ -277,6 +277,7 @@ namespace PhysX force.Deactivate(); } + m_nonUniformScaleChangedHandler.Disconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); EditorComponentBase::Deactivate(); } diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index d5ce38d389..5445f7fc69 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -273,6 +273,7 @@ namespace PhysX m_debugDisplayDataChangeHandler.Disconnect(); Physics::WorldBodyRequestBus::Handler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); m_sceneStartSimHandler.Disconnect(); Physics::ColliderComponentEventBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); diff --git a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp index a1b8516150..639a079c02 100644 --- a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp @@ -666,6 +666,7 @@ namespace PhysX Physics::WorldBodyRequestBus::Handler::BusDisconnect(); m_colliderDebugDraw.Disconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); PhysX::ColliderShapeRequestBus::Handler::BusDisconnect(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); From f552fc7ccd97bc8ba7cc1841c4c4f5af5122332e Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 16 Apr 2021 17:30:06 +0100 Subject: [PATCH 088/122] Fix for ReadMesh error reporting --- .../Code/Include/WhiteBox/WhiteBoxToolApi.h | 22 +++++++++++++++---- .../Source/Asset/WhiteBoxMeshAssetHandler.cpp | 7 ++++-- .../Code/Source/Core/WhiteBoxToolApi.cpp | 12 +++++----- .../Code/Source/EditorWhiteBoxComponent.cpp | 14 ++++++------ Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp | 3 ++- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h index 5b8d384774..8e74c09f52 100644 --- a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h +++ b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h @@ -729,15 +729,29 @@ namespace WhiteBox /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization + //! The result of attempting to deserialize a white box mesh from a white box mesh stream. + enum class ReadResult + { + Full, //!< The white box mesh stream was full and was read into white box mesh (it is now initialized). + Empty, //!< The white box mesh stream was empty so no white box mesh was loaded. + Error //!< An error occurred while trying to deserialize white box mesh stream. + }; + //! Take an input stream of bytes and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note A white box mesh must have been created first. - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); //! Take an input stream and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note The input stream must not skip white space characters (std::noskipws must be set on the stream). - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); //! Take a white box mesh and write it out to a stream of bytes. //! @return Will return false if any error was encountered during serialization, true otherwise. diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index 7aa12777e0..3ed22a3d1b 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -118,12 +118,15 @@ namespace WhiteBox stream->Read(size, whiteBoxData.data()); auto whiteBoxMesh = WhiteBox::Api::CreateWhiteBoxMesh(); - const bool success = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + const auto result = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + // if result is not 'Full', then whiteBoxMeshAsset could be empty which is most likely an error + // as no data was loaded from the asset, or it was not correctly read in stream->Read(..) + const auto success = result == Api::ReadResult::Full; if (success) { whiteBoxMeshAsset->SetMesh(AZStd::move(whiteBoxMesh)); - whiteBoxMeshAsset->SetWhiteBoxData(whiteBoxData); + whiteBoxMeshAsset->SetWhiteBoxData(AZStd::move(whiteBoxData)); } return success ? AZ::Data::AssetHandler::LoadResult::LoadComplete diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 03f2545ae1..5803f066ae 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3403,13 +3403,13 @@ namespace WhiteBox return false; } - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); if (input.empty()) { - return false; + return ReadResult::Empty; } std::string inputStr; @@ -3423,19 +3423,19 @@ namespace WhiteBox return ReadMesh(whiteBox, whiteBoxStream); } - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) { const auto skipws = input.flags() & std::ios_base::skipws; AZ_Assert(skipws == 0, "Input stream must not skip white space characters"); if (skipws != 0) { - return false; + return ReadResult::Error; } AZStd::lock_guard lg(g_omSerializationLock); OpenMesh::IO::Options options{OpenMesh::IO::Options::FaceTexCoord | OpenMesh::IO::Options::FaceNormal}; - return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options); + return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options) ? ReadResult::Full : ReadResult::Error; } WhiteBoxMeshPtr CloneMesh(const WhiteBoxMesh& whiteBox) @@ -3449,7 +3449,7 @@ namespace WhiteBox } WhiteBoxMeshPtr newMesh = CreateWhiteBoxMesh(); - if (!ReadMesh(*newMesh, clonedData)) + if (ReadMesh(*newMesh, clonedData) != ReadResult::Full) { return nullptr; } diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp index 61012b8577..e88b4ce686 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp @@ -348,14 +348,14 @@ namespace WhiteBox else { // attempt to load the mesh - if (Api::ReadMesh(*m_whiteBox, m_whiteBoxData)) + const auto result = Api::ReadMesh(*m_whiteBox, m_whiteBoxData); + AZ_Error("EditorWhiteBoxComponent", result != WhiteBox::Api::ReadResult::Error, "Error deserializing white box mesh stream"); + + // if the read was successful but the byte stream is empty + // (there was nothing to load), create a default mesh + if (result == Api::ReadResult::Empty) { - // if the read was successful but the byte stream is empty - // (there was nothing to load), create a default mesh - if (m_whiteBoxData.empty()) - { - Api::InitializeAsUnitCube(*m_whiteBox); - } + Api::InitializeAsUnitCube(*m_whiteBox); } } } diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp index 1d55539720..1135a915ec 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp @@ -470,6 +470,7 @@ namespace UnitTest TEST_F(WhiteBoxTestFixture, MeshNotDeserializedWithSkipWhiteSpaceStream) { namespace Api = WhiteBox::Api; + using testing::Eq; Api::InitializeAsUnitCube(*m_whiteBox); AZStd::vector serializedWhiteBox; @@ -485,7 +486,7 @@ namespace UnitTest // note: std::stringstream will default to skip white space characters AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_FALSE(Api::ReadMesh(*m_whiteBox, whiteBoxStream)); + EXPECT_THAT(Api::ReadMesh(*m_whiteBox, whiteBoxStream), Eq(Api::ReadResult::Error)); AZ_TEST_STOP_TRACE_SUPPRESSION(1); } From 8e34d784e60f0e9489bec5335fa6171af5e3cad5 Mon Sep 17 00:00:00 2001 From: qingtao Date: Fri, 16 Apr 2021 09:47:03 -0700 Subject: [PATCH 089/122] ATOM-15252 [Atom 0.8.5] Track View capture crashes when scene contains certain postfx The crash was because the "BlendColorGradingLutImageAttachmentId" attachment got imported to attachment database twice. This fix avoids import this attachment twice. It also avoid crash but only report a warning if an imported attachment wasn't used in any scope. Enable both RHI and RPI validation (no visiable performance impact observed. --- .../PostProcessing/BlendColorGradingLutsPass.cpp | 9 +++++++-- Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp | 12 ++++++++++++ Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp index 206e58d5e6..e0ff253301 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp @@ -131,8 +131,13 @@ namespace AZ AZ_Assert(m_blendedLut.m_lutImage != nullptr, "BlendColorGradingLutsPass unable to acquire LUT image"); AZ::RHI::AttachmentId imageAttachmentId = AZ::RHI::AttachmentId("BlendColorGradingLutImageAttachmentId"); - [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage); - AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import compute buffer with error %d", result); + + // import this attachment if it wasn't imported + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(imageAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage); + AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import BlendColorGradingLutImageAttachmentId with error %d", result); + } RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = imageAttachmentId; diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp index 4d35411e09..21eb634159 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp @@ -16,6 +16,6 @@ namespace AZ { namespace RHI { - bool Validation::s_isEnabled = BuildOptions::IsDebugBuild; + bool Validation::s_isEnabled = BuildOptions::IsDebugBuild || BuildOptions::IsProfileBuild; } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp index 1ae8a4ae96..7fc1db179a 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp @@ -404,6 +404,12 @@ namespace AZ Buffer& buffer = static_cast(*bufferFrameAttachment.GetBuffer()); RHI::BufferScopeAttachment* scopeAttachment = bufferFrameAttachment.GetFirstScopeAttachment(); + if (scopeAttachment == nullptr) + { + AZ_WarningOnce("RHI", false, "Imported BufferFrameAttachment isn't used in any Scope"); + return; + } + D3D12_RESOURCE_TRANSITION_BARRIER transition; transition.pResource = buffer.GetMemoryView().GetMemory(); transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; @@ -471,6 +477,12 @@ namespace AZ Image& image = static_cast(*imageFrameAttachment.GetImage()); RHI::ImageScopeAttachment* scopeAttachment = imageFrameAttachment.GetFirstScopeAttachment(); + if (scopeAttachment == nullptr) + { + AZ_WarningOnce("RHI", false, "Imported ImageFrameAttachment isn't used in any Scope"); + return; + } + D3D12_RESOURCE_TRANSITION_BARRIER transition; transition.pResource = image.GetMemoryView().GetMemory(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp index 7012a7cf88..8addb16a23 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp @@ -16,6 +16,6 @@ namespace AZ { namespace RPI { - bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild; + bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild || RHI::BuildOptions::IsProfileBuild; } } From bc9b2b4c2ee28ccd11fc4de120eadc4d3056f3cd Mon Sep 17 00:00:00 2001 From: qingtao Date: Fri, 16 Apr 2021 11:05:03 -0700 Subject: [PATCH 090/122] Fixed Mac compile issue. Set default refresh type to realtime (due to a known issue with OncePerSecond with ASV) --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h | 2 +- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h index 6520844edd..ce6915699b 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h @@ -249,7 +249,7 @@ namespace AZ bool m_showTimeline = false; // Controls how often the timestamp data is refreshed - RefreshType m_refreshType = RefreshType::OncePerSecond; + RefreshType m_refreshType = RefreshType::Realtime; AZStd::sys_time_t m_lastUpdateTimeMicroSecond; }; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index eb0e295129..fa9395dffc 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -16,6 +16,8 @@ #include #include +#include + namespace AZ { namespace Render @@ -725,7 +727,7 @@ namespace AZ ImGui::BeginTooltip(); ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); - ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in ticks: %" PRIu64, passEntry->m_timestampResult.GetDurationInTicks()); ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); ImGui::EndTooltip(); } From f0cf27b8d35ba6f9ec3aa3d22aaa50fcda8cc9bf Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 13:58:57 -0500 Subject: [PATCH 091/122] adding the testing files for testing for python asset building and scripting the scene_api gets a small update for mesh_group_add_advanced_coordinate_system(self, --- .../Gem/Editor/Scripts/__init__.py | 10 ++ .../Gem/Editor/Scripts/bootstrap.py | 13 ++ .../PythonAssetBuilder/AssetBuilder_test.py | 57 +++++++++ .../AssetBuilder_test_case.py | 52 ++++++++ .../PythonAssetBuilder/__init__.py | 10 ++ .../PythonAssetBuilder/bootstrap_tests.py | 17 +++ .../export_chunks_builder.py | 88 +++++++++++++ .../PythonAssetBuilder/geom_group.fbx | 3 + .../geom_group.fbx.assetinfo | 9 ++ .../PythonAssetBuilder/mock_asset_builder.py | 121 ++++++++++++++++++ .../PythonAssetBuilder/test_asset.mock | 1 + .../Editor/Scripts/scene_api/scene_data.py | 15 ++- 12 files changed, 391 insertions(+), 5 deletions(-) create mode 100644 AutomatedTesting/Gem/Editor/Scripts/__init__.py create mode 100644 AutomatedTesting/Gem/Editor/Scripts/bootstrap.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock diff --git a/AutomatedTesting/Gem/Editor/Scripts/__init__.py b/AutomatedTesting/Gem/Editor/Scripts/__init__.py new file mode 100644 index 0000000000..79f8fa4422 --- /dev/null +++ b/AutomatedTesting/Gem/Editor/Scripts/__init__.py @@ -0,0 +1,10 @@ +""" +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. +""" diff --git a/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py b/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py new file mode 100644 index 0000000000..e41f9c1767 --- /dev/null +++ b/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py @@ -0,0 +1,13 @@ +""" +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. +""" +import sys, os +sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../PythonTests') +from PythonAssetBuilder import bootstrap_tests diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py new file mode 100644 index 0000000000..e914182542 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -0,0 +1,57 @@ +""" +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. +""" +# +# This launches the AssetProcessor and Editor then attempts to find the expected +# assets created by a Python Asset Builder and the output of a scene pipeline script +# +import sys +import os +import pytest +import logging +pytest.importorskip('ly_test_tools') + +import ly_test_tools.environment.file_system as file_system +import ly_test_tools.log.log_monitor +import ly_test_tools.environment.waiter as waiter + +@pytest.mark.SUITE_sandbox +@pytest.mark.parametrize('launcher_platform', ['windows_editor']) +@pytest.mark.parametrize('project', ['AutomatedTesting']) +@pytest.mark.parametrize('level', ['auto_test']) +class TestPythonAssetProcessing(object): + def test_DetectPythonCreatedAsset(self, request, editor, level, launcher_platform): + unexpected_lines = [] + expected_lines = [ + 'Mock asset exists', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found' + ] + timeout = 180 + halt_on_unexpected = False + test_directory = os.path.join(os.path.dirname(__file__)) + testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py') + editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) + + with editor.start(): + editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log') + log_monitor = ly_test_tools.log.log_monitor.LogMonitor(editor, editorlog_file) + waiter.wait_for( + lambda: editor.is_alive(), + timeout, + exc=("Log file '{}' was never opened by another process.".format(editorlog_file)), + interval=1) + log_monitor.monitor_log_for_lines(expected_lines, unexpected_lines, halt_on_unexpected, timeout) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py new file mode 100644 index 0000000000..608c2d224d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -0,0 +1,52 @@ +""" +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. +""" +import azlmbr.bus +import azlmbr.asset +import azlmbr.editor +import azlmbr.math +import azlmbr.legacy.general + +def raise_and_stop(msg): + print (msg) + azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') + +# These tests are meant to check that the test_asset.mock source asset turned into +# a test_asset.mock_asset product asset via the Python asset builder system +mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0) +mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset' +assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False) +if (assetId.is_valid() is False): + raise_and_stop(f'Mock AssetId is not valid!') + +if (assetId.to_string().endswith(':54c06b89') is False): + raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!') + +print ('Mock asset exists') + +# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets +def test_azmodel_product(generatedModelAssetPath, expectedSubId): + azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0) + assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False) + assetIdString = assetId.to_string() + if (assetIdString.endswith(':' + expectedSubId) is False): + raise_and_stop(f'Asset has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath})!') + else: + print(f'Expected subId for asset ({generatedModelAssetPath}) found') + +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel', '10d16e68') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel', '10a71973') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_positive.azmodel', '10130556') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_negative.azmodel', '1065724d') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_positive.azmodel', '1024be55') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_negative.azmodel', '1052c94e') + +azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py new file mode 100644 index 0000000000..6ed3dc4bda --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py @@ -0,0 +1,10 @@ +""" +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. +""" \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py new file mode 100644 index 0000000000..9e7b738a4d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py @@ -0,0 +1,17 @@ +""" +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. +""" +import os +import sys +try: + sys.path.append(os.path.dirname(os.path.abspath(__file__))) + import mock_asset_builder +except: + print ('skipping asset builder testing via mock_asset_builder') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py new file mode 100644 index 0000000000..ad68a486b1 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py @@ -0,0 +1,88 @@ +""" +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. +""" +import uuid, os +import azlmbr.scene as sceneApi +import azlmbr.scene.graph +from scene_api import scene_data as sceneData + +def get_mesh_node_names(sceneGraph): + meshDataList = [] + node = sceneGraph.get_root() + children = [] + + while node.IsValid(): + # store children to process after siblings + if sceneGraph.has_node_child(node): + children.append(sceneGraph.get_node_child(node)) + + # store any node that has mesh data content + nodeContent = sceneGraph.get_node_content(node) + if nodeContent is not None and nodeContent.CastWithTypeName('MeshData'): + if sceneGraph.is_node_end_point(node) is False: + meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node))) + + # advance to next node + if sceneGraph.has_node_sibling(node): + node = sceneGraph.get_node_sibling(node) + elif children: + node = children.pop() + else: + node = azlmbr.scene.graph.NodeIndex() + + return meshDataList + +def update_manifest(scene): + graph = sceneData.SceneGraph(scene.graph) + meshNameList = get_mesh_node_names(graph) + sceneManifest = sceneData.SceneManifest() + sourceFilenameOnly = os.path.basename(scene.sourceFilename) + sourceFilenameOnly = sourceFilenameOnly.replace('.','_') + + for activeMeshIndex in range(len(meshNameList)): + chunkName = meshNameList[activeMeshIndex] + chunkPath = chunkName.get_path() + meshGroupName = '{}_{}'.format(sourceFilenameOnly, chunkName.get_name()) + meshGroup = sceneManifest.add_mesh_group(meshGroupName) + meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, sourceFilenameOnly + chunkPath)) + '}' + sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by scene manifest') + sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup, None, None, None, 1.0) + + # create selection node list + pathSet = set() + for meshIndex in range(len(meshNameList)): + targetPath = meshNameList[meshIndex].get_path() + if (activeMeshIndex == meshIndex): + sceneManifest.mesh_group_select_node(meshGroup, targetPath) + else: + if targetPath not in pathSet: + pathSet.update(targetPath) + sceneManifest.mesh_group_unselect_node(meshGroup, targetPath) + + return sceneManifest.export() + +mySceneJobHandler = None + +def on_update_manifest(args): + scene = args[0] + result = update_manifest(scene) + global mySceneJobHandler + mySceneJobHandler.disconnect() + mySceneJobHandler = None + return result + +def main(): + global mySceneJobHandler + mySceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler() + mySceneJobHandler.connect() + mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest) + +if __name__ == "__main__": + main() diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx new file mode 100644 index 0000000000..8945a5505a --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66d38948309ef273adf74b63eaa38f8fc2e2bdfbab3933d2ee082ce6a8cb108e +size 30496 diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo new file mode 100644 index 0000000000..707c6f3705 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo @@ -0,0 +1,9 @@ +{ + "values": + [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py" + } + ] +} diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py new file mode 100644 index 0000000000..00a656abd0 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -0,0 +1,121 @@ +""" +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. +""" +import azlmbr.asset +import azlmbr.asset.builder +import azlmbr.bus +import azlmbr.math +import os, traceback, binascii, sys + +jobKeyName = 'Mock Asset' + +def log_exception_traceback(): + exc_type, exc_value, exc_tb = sys.exc_info() + data = traceback.format_exception(exc_type, exc_value, exc_tb) + print(str(data)) + +# creates a single job to compile for each platform +def create_jobs(request): + # create job descriptor for each platform + jobDescriptorList = [] + for platformInfo in request.enabledPlatforms: + jobDesc = azlmbr.asset.builder.JobDescriptor() + jobDesc.jobKey = jobKeyName + jobDesc.set_platform_identifier(platformInfo.identifier) + jobDescriptorList.append(jobDesc) + + response = azlmbr.asset.builder.CreateJobsResponse() + response.result = azlmbr.asset.builder.CreateJobsResponse_ResultSuccess + response.createJobOutputs = jobDescriptorList + return response + +def on_create_jobs(args): + try: + request = args[0] + return create_jobs(request) + except: + log_exception_traceback() + # returing back a default CreateJobsResponse() records an asset error + return azlmbr.asset.builder.CreateJobsResponse() + +def process_file(request): + # prepare output folder + basePath, _ = os.path.split(request.sourceFile) + outputPath = os.path.join(request.tempDirPath, basePath) + os.makedirs(outputPath, exist_ok=True) + + # write out a mock file + basePath, sourceFile = os.path.split(request.sourceFile) + mockFilename = os.path.splitext(sourceFile)[0] + '.mock_asset' + mockFilename = os.path.join(basePath, mockFilename) + mockFilename = mockFilename.replace('\\', '/').lower() + tempFilename = os.path.join(request.tempDirPath, mockFilename) + + # write out a tempFilename like a JSON or something? + fileOutput = open(tempFilename, "w") + fileOutput.write('{}') + fileOutput.close() + + # generate a product asset file entry + subId = binascii.crc32(mockFilename.encode()) + mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0) + product = azlmbr.asset.builder.JobProduct(mockFilename, mockAssetType, subId) + product.dependenciesHandled = True + productOutputs = [] + productOutputs.append(product) + + # fill out response object + response = azlmbr.asset.builder.ProcessJobResponse() + response.outputProducts = productOutputs + response.resultCode = azlmbr.asset.builder.ProcessJobResponse_Success + response.dependenciesHandled = True + return response + +# using the incoming 'request' find the type of job via 'jobKey' to determine what to do +def on_process_job(args): + try: + request = args[0] + if (request.jobDescription.jobKey.startswith(jobKeyName)): + return process_file(request) + except: + log_exception_traceback() + # returning back an empty ProcessJobResponse() will record an error + return azlmbr.asset.builder.ProcessJobResponse() + +# register asset builder +def register_asset_builder(busId): + assetPattern = azlmbr.asset.builder.AssetBuilderPattern() + assetPattern.pattern = '*.mock' + assetPattern.type = azlmbr.asset.builder.AssetBuilderPattern_Wildcard + + builderDescriptor = azlmbr.asset.builder.AssetBuilderDesc() + builderDescriptor.name = "Mock Builder" + builderDescriptor.patterns = [assetPattern] + builderDescriptor.busId = busId + builderDescriptor.version = 1 + + outcome = azlmbr.asset.builder.PythonAssetBuilderRequestBus(azlmbr.bus.Broadcast, 'RegisterAssetBuilder', builderDescriptor) + if outcome.IsSuccess(): + # created the asset builder to hook into the notification bus + handler = azlmbr.asset.builder.PythonBuilderNotificationBusHandler() + handler.connect(busId) + handler.add_callback('OnCreateJobsRequest', on_create_jobs) + handler.add_callback('OnProcessJobRequest', on_process_job) + return handler + +# create the asset builder handler +busIdString = '{CF5C74C1-9ED4-5851-95B1-0B15090DBEC7}' +busId = azlmbr.math.Uuid_CreateString(busIdString, 0) +handler = None +try: + handler = register_asset_builder(busId) +except: + handler = None + log_exception_traceback() diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock new file mode 100644 index 0000000000..6d6a52e643 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock @@ -0,0 +1 @@ +mock data \ No newline at end of file diff --git a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py index 7db3daa276..4583262b25 100755 --- a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py +++ b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py @@ -114,12 +114,17 @@ class SceneManifest(): def mesh_group_unselect_node(self, meshGroup, nodeName): meshGroup['nodeSelectionList']['unselectedNodes'].append(nodeName) - def mesh_group_set_origin(self, meshGroup, originNodeName, x, y, z, scale): + def mesh_group_add_advanced_coordinate_system(self, meshGroup, originNodeName, translation, rotation, scale): originRule = {} - originRule['$type'] = 'OriginRule' - originRule['originNodeName'] = 'World' if originNodeName is None else originNodeName - originRule['translation'] = [x, y, z] - originRule['scale'] = scale + originRule['$type'] = 'CoordinateSystemRule' + originRule['useAdvancedData'] = True + originRule['originNodeName'] = '' if originNodeName is None else originNodeName + if translation is not None: + originRule['translation'] = translation + if rotation is not None: + originRule['rotation'] = rotation + if scale != 1.0: + originRule['scale'] = scale meshGroup['rules']['rules'].append(originRule) def mesh_group_add_comment(self, meshGroup, comment): From 10faddb113333a77221ff3df8be4b619fe318332 Mon Sep 17 00:00:00 2001 From: alexpete Date: Fri, 16 Apr 2021 12:05:11 -0700 Subject: [PATCH 092/122] Integrating github/staging through commit ef88e6e --- CMakeLists.txt | 4 - .../Common/PerInstanceConstantBufferPool.cpp | 4 + .../CryEngine/RenderDll/Common/RenderMesh.cpp | 1 + Code/Framework/AzCore/AzCore/Math/Vector2.cpp | 4 +- .../Entity/EntityDebugDisplayBus.h | 2 - .../AzFramework/Font/FontInterface.h | 85 + .../AzFramework/Viewport/ScreenGeometry.h | 13 + .../AzFramework/Viewport/ViewportScreen.cpp | 27 +- .../AzFramework/Viewport/ViewportScreen.h | 5 + .../AzFramework/azframework_files.cmake | 1 + .../EditorTransformComponentSelection.cpp | 45 +- .../Editor/Objects/DisplayContextShared.inl | 22 - .../SandboxIntegration.cpp | 20 - .../SandboxIntegration.h | 2 - ...enticationNotificationBusBehaviorHandler.h | 69 +- .../AuthenticationProviderManager.h | 22 +- .../AuthenticationProviderScriptCanvasBus.h | 103 + .../AuthenticationProviderTypes.h | 8 + ...horizationNotificationBusBehaviorHandler.h | 11 +- ...ManagementNotificationBusBehaviorHandler.h | 49 +- .../AuthenticationProviderBus.h | 10 +- .../Authentication/AuthenticationTokens.h | 15 +- .../Authorization/ClientAuthAWSCredentials.h | 36 +- .../AWSCognitoUserManagementBus.h | 5 +- .../Source/AWSClientAuthSystemComponent.cpp | 44 +- .../AWSCognitoAuthenticationProvider.cpp | 2 +- .../AuthenticationProviderManager.cpp | 87 +- .../Authentication/AuthenticationTokens.cpp | 26 + .../AWSCognitoAuthorizationController.cpp | 6 +- .../AWSCognitoUserManagementController.cpp | 2 +- .../AuthenticationProviderManagerMock.h | 55 + ...tionProviderManagerScriptCanvasBusTest.cpp | 261 ++ .../AuthenticationProviderManagerTest.cpp | 48 +- .../Code/awsclientauth_files.cmake | 1 + .../Code/awsclientauth_test_files.cmake | 2 + .../cdk/auth/cognito_identity_pool_role.py | 3 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.cpp | 10 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.h | 2 +- .../Atom/RPI.Public/AuxGeom/AuxGeomDraw.h | 2 +- .../AtomDebugDisplayViewportInterface.cpp | 2301 ++++++++++------- .../AtomDebugDisplayViewportInterface.h | 55 +- .../AtomLyIntegration/AtomFont/AtomFont.h | 37 +- .../AtomLyIntegration/AtomFont/FFont.h | 58 +- .../AtomFont/Code/Source/AtomFont.cpp | 78 +- .../AtomFont/Code/Source/FFont.cpp | 268 +- .../CoreLights/AreaLightComponentConfig.h | 3 + .../CoreLights/AreaLightComponentConfig.cpp | 5 + .../AreaLightComponentController.cpp | 9 + .../Source/CoreLights/DiskLightDelegate.cpp | 46 +- .../CoreLights/EditorAreaLightComponent.cpp | 57 +- .../Source/CoreLights/LightDelegateBase.h | 5 + .../Source/CoreLights/LightDelegateBase.inl | 6 + .../CoreLights/LightDelegateInterface.h | 3 + .../CoreLights/SimpleSpotLightDelegate.cpp | 35 +- .../CoreLights/SimpleSpotLightDelegate.h | 4 +- .../AtomShim_RenderAuxGeom.cpp | 4 +- cmake/FindTarget.cmake.in | 45 + cmake/Findo3de.cmake | 25 +- cmake/Findo3de.cmake.in | 36 + cmake/Platform/Common/Install_common.cmake | 11 +- 60 files changed, 2959 insertions(+), 1246 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/Font/FontInterface.h create mode 100644 Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h create mode 100644 Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h create mode 100644 Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp create mode 100644 cmake/FindTarget.cmake.in create mode 100644 cmake/Findo3de.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index c09cfc9588..6da92f9c2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,15 +23,11 @@ endif() include(cmake/Version.cmake) -set(INSTALLED_ENGINE TRUE) - if(NOT PROJECT_NAME) project(O3DE LANGUAGES C CXX VERSION ${LY_VERSION_STRING} ) - - set(INSTALLED_ENGINE FALSE) endif() include(cmake/Initialize.cmake) diff --git a/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp b/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp index 7fa69f6026..f2475c0b48 100644 --- a/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp +++ b/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp @@ -274,6 +274,10 @@ void PerInstanceConstantBufferPool::SetConstantBuffer(SRendItem* renderItem) deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex); deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex); #else + AZ::u32 itemIndex = directId % SPI_NUM_INSTS_PER_CB; + AZ::u32 first[1] = {itemIndex * static_cast(sizeof(HLSL_PerInstanceConstantBuffer))}; + AZ::u32 count[1] = {static_cast(sizeof(HLSL_PerInstanceConstantBuffer))}; + deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]); deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]); #endif diff --git a/Code/CryEngine/RenderDll/Common/RenderMesh.cpp b/Code/CryEngine/RenderDll/Common/RenderMesh.cpp index 10bbfbf0e6..357731fc6d 100644 --- a/Code/CryEngine/RenderDll/Common/RenderMesh.cpp +++ b/Code/CryEngine/RenderDll/Common/RenderMesh.cpp @@ -755,6 +755,7 @@ lSysUpdate: buffer_handle_t nVB = ~0u; # if BUFFER_ENABLE_DIRECT_ACCESS && !defined(NULL_RENDERER) nVB = MS->m_nID; + int nFrame = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nFillThreadID].m_nFrameUpdateID; if ((nVB != ~0u && (MS->m_nFrameCreate != nFrame || MS->m_nElements != m_nVerts)) || !CRenderer::CV_r_buffer_enable_lockless_updates) # endif goto lSysCreate; diff --git a/Code/Framework/AzCore/AzCore/Math/Vector2.cpp b/Code/Framework/AzCore/AzCore/Math/Vector2.cpp index bc5f6ecdad..c2a3a934b0 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector2.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Vector2.cpp @@ -167,14 +167,14 @@ namespace AZ } } - AZ_MATH_INLINE Vector2::Vector2(const Vector3& source) + Vector2::Vector2(const Vector3& source) : m_x(source.GetX()) , m_y(source.GetY()) { } - AZ_MATH_INLINE Vector2::Vector2(const Vector4& source) + Vector2::Vector2(const Vector4& source) : m_x(source.GetX()) , m_y(source.GetY()) { diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h index a5d3e657f5..f84f0276e1 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h @@ -105,8 +105,6 @@ namespace AzFramework virtual bool SetDrawInFrontMode(bool bOn) { (void)bOn; return false; } virtual AZ::u32 GetState() { return 0; } virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; } - virtual AZ::u32 SetStateFlag(AZ::u32 state) { (void)state; return 0; } - virtual AZ::u32 ClearStateFlag(AZ::u32 state) { (void)state; return 0; } virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; } virtual void PopMatrix() {} diff --git a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h new file mode 100644 index 0000000000..7c5bcce6d6 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h @@ -0,0 +1,85 @@ +/* +* 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 +#include +#include + +namespace AzFramework +{ + using FontId = uint32_t; + static constexpr FontId InvalidFontId = 0xffffffffu; + + enum class TextHorizontalAlignment : uint16_t + { + Left, + Right, + Center + }; + + enum class TextVerticalAlignment : uint16_t + { + Top, + Bottom, + Center, + }; + + //! Standard parameters for drawing text on screen + struct TextDrawParameters + { + ViewportId m_drawViewportId = InvalidViewportId; //! Viewport to draw into + AZ::Vector3 m_position; //! world space position for 3d draws, screen space x,y,depth for 2d. + AZ::Color m_color = AZ::Colors::White; //! Color to draw the text + AZ::Vector2 m_scale = AZ::Vector2(1.0f); //! font scale + TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //! Horizontal text alignment + TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //! Vertical text alignment + bool m_monospace = false; //! disable character proportional spacing + bool m_depthTest = false; //! Test character against the depth buffer + bool m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + bool m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + bool m_multiline = true; //! text respects ascii newline characters + }; + + class FontDrawInterface + { + public: + AZ_RTTI(FontDrawInterface, "{545A7C14-CB3E-4A5B-B435-13EA606708EE}"); + + FontDrawInterface() = default; + virtual ~FontDrawInterface() = default; + + virtual void DrawScreenAlignedText2d( + const TextDrawParameters& params, + const AZStd::string_view& string) = 0; + virtual void DrawScreenAlignedText3d( + const TextDrawParameters& params, + const AZStd::string_view& string) = 0; + }; + + class FontQueryInterface + { + public: + AZ_RTTI(FontQueryInterface, "{4BDD8520-EBC1-4680-B25E-421BDF31750F}"); + + FontQueryInterface() = default; + virtual ~FontQueryInterface() = default; + + FontId GetFontId(const AZStd::string_view& fontName) const {return FontId(AZ::Crc32(fontName));} + virtual FontDrawInterface* GetFontDrawInterface(FontId) const = 0; + virtual FontDrawInterface* GetDefaultFontDrawInterface() const = 0; + + }; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h index 1b570ebb8e..d3ae4e16f3 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h @@ -14,6 +14,7 @@ #include #include +#include #include namespace AZ @@ -133,6 +134,18 @@ namespace AzFramework return !operator==(lhs, rhs); } + inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize) + { + return ScreenPoint( + aznumeric_caster(std::round(screenNDC.GetX() * viewportSize.GetX())), + aznumeric_caster(std::round((1.0f - screenNDC.GetY()) * viewportSize.GetY()))); + } + + inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize) + { + return AZ::Vector2(aznumeric_cast(screenPoint.m_x), viewportSize.GetY() - aznumeric_cast(screenPoint.m_y)) / viewportSize; + } + //! Return an AZ::Vector2 from a ScreenPoint. inline AZ::Vector2 Vector2FromScreenPoint(const ScreenPoint& screenPoint) { diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp index 3ca16897ba..5d2d02a398 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp @@ -101,20 +101,25 @@ namespace AzFramework cameraState.m_nearClip, cameraState.m_farClip); } - ScreenPoint WorldToScreen( - const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection, - const AZ::Vector2& viewportSize) + AZ::Vector3 WorldToScreenNDC( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection) { // transform the world space position to clip space const auto clipSpacePosition = cameraProjection * cameraView * AZ::Vector3ToVector4(worldPosition, 1.0f); // transform the clip space position to ndc space (perspective divide) const auto ndcPosition = clipSpacePosition / clipSpacePosition.GetW(); // transform ndc space from <-1,1> to <0, 1> range - const auto ndcNormalizedPosition = (AZ::Vector4ToVector2(ndcPosition) + AZ::Vector2::CreateOne()) * 0.5f; + return (AZ::Vector4ToVector3(ndcPosition) + AZ::Vector3::CreateOne()) * 0.5f; + } + + + ScreenPoint WorldToScreen( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection, + const AZ::Vector2& viewportSize) + { + const auto ndcNormalizedPosition = WorldToScreenNDC(worldPosition, cameraView, cameraProjection); // scale ndc position by screen dimensions to return screen position - return ScreenPoint( - aznumeric_caster(std::round(ndcNormalizedPosition.GetX() * viewportSize.GetX())), - aznumeric_caster(std::round(viewportSize.GetY() - (ndcNormalizedPosition.GetY() * viewportSize.GetY())))); + return ScreenPointFromNDC(ndcNormalizedPosition, viewportSize); } ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState) @@ -127,12 +132,8 @@ namespace AzFramework const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize) { - const auto screenHeight = viewportSize.GetY(); - const auto flippedScreenPosition = - AZ::Vector2(aznumeric_caster(screenPosition.m_x), aznumeric_caster(screenHeight - screenPosition.m_y)); - - // convert screen space coordinates to <-1,1> range - const auto ndcPosition = (flippedScreenPosition / viewportSize) * 2.0f - AZ::Vector2::CreateOne(); + // convert screen space coordinates from <0, 1> to <-1,1> range + const auto ndcPosition = NDCFromScreenPoint(screenPosition, viewportSize) * 2.0f - AZ::Vector2::CreateOne(); // transform ndc space position to clip space const auto clipSpacePosition = inverseCameraProjection * Vector2ToVector4(ndcPosition, -1.0f, 1.0f); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h index 582e051bbb..a2c650465f 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h @@ -28,6 +28,11 @@ namespace AzFramework struct ScreenPoint; struct ViewportInfo; + //! Projects a position in world space to screen space normalized device coordinates for the given camera. + AZ::Vector3 WorldToScreenNDC( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection); + + //! Projects a position in world space to screen space for the given camera. ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState); diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index b37c1b259f..cde2afb930 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -145,6 +145,7 @@ set(FILES Components/NonUniformScaleComponent.cpp FileFunc/FileFunc.h FileFunc/FileFunc.cpp + Font/FontInterface.h Gem/GemInfo.cpp Gem/GemInfo.h StringFunc/StringFunc.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 83632708d9..433602e6d8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -53,7 +53,7 @@ namespace AzToolsFramework float, cl_viewportGizmoAxisLabelOffset, 1.15f, nullptr, AZ::ConsoleFunctorFlags::Null, "The offset of the label for the viewport axis gizmo"); AZ_CVAR( - float, cl_viewportGizmoAxisLabelSize, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, + float, cl_viewportGizmoAxisLabelSize, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The size of each label for the viewport axis gizmo"); AZ_CVAR( AZ::Vector2, cl_viewportGizmoAxisScreenPosition, AZ::Vector2(0.045f, 0.9f), nullptr, @@ -3434,19 +3434,22 @@ namespace AzToolsFramework const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState); // screen space offset to move the 2d gizmo around - const AZ::Vector3 screenPosition = - (AZ::Vector2ToVector3(cl_viewportGizmoAxisScreenPosition) - AZ::Vector3(0.5f, 0.5f, 0.0f)) * - AZ::Vector2ToVector3(gizmoCameraState.m_viewportSize); + const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f); // map from a position in world space (relative to the the gizmo camera near the origin) to a position in // screen space const auto calculateGizmoAxis = - [&cameraView, &cameraProjection, &gizmoCameraState, &screenPosition] - (const AZ::Vector3& position) + [&cameraView, &cameraProjection, &screenOffset] + (const AZ::Vector3& axis) { - return AZ::Vector2ToVector3(AzFramework::Vector2FromScreenPoint( - AzFramework::WorldToScreen( - position, cameraView, cameraProjection, gizmoCameraState.m_viewportSize))) + screenPosition; + auto result = AZ::Vector2( + AzFramework::WorldToScreenNDC( + axis, + cameraView, + cameraProjection) + ); + result.SetY(1.0f - result.GetY()); + return result + screenOffset; }; // get all important axis positions in screen space @@ -3456,31 +3459,31 @@ namespace AzToolsFramework const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength); const auto gizmoEndAxisZ = calculateGizmoAxis(-AZ::Vector3::CreateAxisZ() * lineLength); - const AZ::Vector3 gizmoAxisX = gizmoEndAxisX - gizmoStart; - const AZ::Vector3 gizmoAxisY = gizmoEndAxisY - gizmoStart; - const AZ::Vector3 gizmoAxisZ = gizmoEndAxisZ - gizmoStart; + const AZ::Vector2 gizmoAxisX = gizmoEndAxisX - gizmoStart; + const AZ::Vector2 gizmoAxisY = gizmoEndAxisY - gizmoStart; + const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart; // draw the axes of the gizmo debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth); debugDisplay.SetColor(AZ::Colors::Red); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisX); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f); debugDisplay.SetColor(AZ::Colors::Lime); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisY); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisY, 1.0f); debugDisplay.SetColor(AZ::Colors::Blue); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisZ); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f); debugDisplay.SetLineWidth(1.0f); const float labelOffset = cl_viewportGizmoAxisLabelOffset; - const auto labelOffsetX = gizmoStart + gizmoAxisX * labelOffset; - const auto labelOffsetY = gizmoStart + gizmoAxisY * labelOffset; - const auto labelOffsetZ = gizmoStart + gizmoAxisZ * labelOffset; + const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize; + const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize; + const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize; // draw the label of of each axis for the gizmo const float labelSize = cl_viewportGizmoAxisLabelSize; debugDisplay.SetColor(AZ::Colors::White); - debugDisplay.Draw2dTextLabel(labelOffsetX.GetX(), labelOffsetX.GetY(), labelSize, "X", true); - debugDisplay.Draw2dTextLabel(labelOffsetY.GetX(), labelOffsetY.GetY(), labelSize, "Y", true); - debugDisplay.Draw2dTextLabel(labelOffsetZ.GetX(), labelOffsetZ.GetY(), labelSize, "Z", true); + debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true); + debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true); + debugDisplay.Draw2dTextLabel(labelZScreenPosition.GetX(), labelZScreenPosition.GetY(), labelSize, "Z", true); } void EditorTransformComponentSelection::DisplayViewportSelection2d( diff --git a/Code/Sandbox/Editor/Objects/DisplayContextShared.inl b/Code/Sandbox/Editor/Objects/DisplayContextShared.inl index a4baf1fe89..dd5c248357 100644 --- a/Code/Sandbox/Editor/Objects/DisplayContextShared.inl +++ b/Code/Sandbox/Editor/Objects/DisplayContextShared.inl @@ -1245,28 +1245,6 @@ uint32 DisplayContext::SetState(uint32 state) return old; } -//! Set a new render state flags. -//! @param returns previous render state. -uint32 DisplayContext::SetStateFlag(uint32 state) -{ - uint32 old = m_renderState; - m_renderState |= state; - m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags; - pRenderAuxGeom->SetRenderFlags(m_renderState); - return old; -} - -//! Clear specified flags in render state. -//! @param returns previous render state. -uint32 DisplayContext::ClearStateFlag(uint32 state) -{ - uint32 old = m_renderState; - m_renderState &= ~state; - m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags; - pRenderAuxGeom->SetRenderFlags(m_renderState); - return old; -} - ////////////////////////////////////////////////////////////////////////// void DisplayContext::DepthTestOff() { diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index e5311dbea9..d9e3d9bb8c 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -2777,26 +2777,6 @@ AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state) return 0; } -AZ::u32 SandboxIntegrationManager::SetStateFlag(AZ::u32 state) -{ - if (m_dc) - { - return m_dc->SetStateFlag(state); - } - - return 0; -} - -AZ::u32 SandboxIntegrationManager::ClearStateFlag(AZ::u32 state) -{ - if (m_dc) - { - return m_dc->ClearStateFlag(state); - } - - return 0; -} - void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm) { if (m_dc) diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index e35fb5087a..36767605b2 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -268,8 +268,6 @@ private: bool SetDrawInFrontMode(bool bOn) override; AZ::u32 GetState() override; AZ::u32 SetState(AZ::u32 state) override; - AZ::u32 SetStateFlag(AZ::u32 state) override; - AZ::u32 ClearStateFlag(AZ::u32 state) override; void PushMatrix(const AZ::Transform& tm) override; void PopMatrix() override; diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h index c5e3c46cd4..c44327a5f2 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include namespace AWSClientAuth { @@ -28,74 +29,104 @@ namespace AWSClientAuth OnPasswordGrantMultiFactorConfirmSignInSuccess, OnPasswordGrantMultiFactorConfirmSignInFail, OnDeviceCodeGrantSignInSuccess, OnDeviceCodeGrantSignInFail, OnDeviceCodeGrantConfirmSignInSuccess, OnDeviceCodeGrantConfirmSignInFail, - OnRefreshTokensSuccess, OnRefreshTokensFail, - OnSignOut + OnRefreshTokensSuccess, OnRefreshTokensFail ); void OnPasswordGrantSingleFactorSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken); + }); } void OnPasswordGrantSingleFactorSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantSingleFactorSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantSingleFactorSignInFail, error); + }); } void OnPasswordGrantMultiFactorSignInSuccess() override { - Call(FN_OnPasswordGrantMultiFactorSignInSuccess); + AZ::TickBus::QueueFunction([this]() + { + Call(FN_OnPasswordGrantMultiFactorSignInSuccess); + }); } void OnPasswordGrantMultiFactorSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantMultiFactorSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantMultiFactorSignInFail, error); + }); } void OnPasswordGrantMultiFactorConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken); + }); } void OnPasswordGrantMultiFactorConfirmSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error); + }); } void OnDeviceCodeGrantSignInSuccess( const AZStd::string& userCode, const AZStd::string& verificationUrl, const int codeExpiresInSeconds) override { - Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds); + AZ::TickBus::QueueFunction([userCode, verificationUrl, codeExpiresInSeconds, this]() + { + Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds); + }); } void OnDeviceCodeGrantSignInFail(const AZStd::string& error) override { - Call(FN_OnDeviceCodeGrantSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnDeviceCodeGrantSignInFail, error); + }); } void OnDeviceCodeGrantConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken); + }); } void OnDeviceCodeGrantConfirmSignInFail(const AZStd::string& error) override { - Call(FN_OnDeviceCodeGrantConfirmSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnDeviceCodeGrantConfirmSignInFail, error); + }); } void OnRefreshTokensSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnRefreshTokensSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnRefreshTokensSuccess, authenticationToken); + }); } void OnRefreshTokensFail(const AZStd::string& error) override { - Call(FN_OnRefreshTokensFail, error); - } - - void OnSignOut(const ProviderNameEnum& provideName) override - { - Call(FN_OnSignOut, provideName); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnRefreshTokensFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h index a9a2f2ad6e..a09a96ba5c 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,8 @@ namespace AWSClientAuth { //! Manages various authentication provider implementations and implements AuthenticationProvider Request bus. class AuthenticationProviderManager - : AuthenticationProviderRequestBus::Handler + : public AuthenticationProviderRequestBus::Handler + , public AuthenticationProviderScriptCanvasRequestBus::Handler { public: AZ_RTTI(AuthenticationProviderManager, "{45813BA5-9A46-4A2A-A923-C79CFBA0E63D}", IAuthenticationProviderRequests); @@ -43,6 +45,22 @@ namespace AWSClientAuth bool IsSignedIn(const ProviderNameEnum& providerName) override; bool SignOut(const ProviderNameEnum& providerName) override; AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override; + + // AuthenticationProviderScriptCanvasRequest interface + bool Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) override; + void PasswordGrantSingleFactorSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override; + void PasswordGrantMultiFactorSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override; + void PasswordGrantMultiFactorConfirmSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override; + void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) override; + void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) override; + void RefreshTokensAsync(const AZStd::string& providerName) override; + void GetTokensWithRefreshAsync(const AZStd::string& providerName) override; + bool IsSignedIn(const AZStd::string& providerName) override; + bool SignOut(const AZStd::string& providerName) override; + AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) override; virtual AZStd::unique_ptr CreateAuthenticationProviderObject(const ProviderNameEnum& providerName); AZStd::map> m_authenticationProvidersMap; @@ -50,9 +68,9 @@ namespace AWSClientAuth private: bool IsProviderInitialized(const ProviderNameEnum& providerName); void ResetProviders(); + ProviderNameEnum GetProviderNameEnum(AZStd::string name); AZStd::shared_ptr m_settingsRegistry; - }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h new file mode 100644 index 0000000000..9ce508b497 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h @@ -0,0 +1,103 @@ +/* +* 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 AWSClientAuth +{ + //! Abstract class for authentication provider script canvas requests. + //! Private class to allow provide names to be string type instead of an enum as behavior context does not work well with enum's. + class IAuthenticationProviderScriptCanvasRequests + { + public: + AZ_TYPE_INFO(IAuthenticationProviderRequests, "{A8FD915F-9FF2-4BA3-8AA0-8CF7A94A323B}"); + + //! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers + //! @param providerNames List of provider names to instantiate and initialize for Authentication. + //! @param settingsRegistryPath Path for the settings registry file to use to configure providers. + //! @return bool True: if all providers initialized successfully. False: If any provider fails initialization. + virtual bool Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) = 0; + + //! Checks if user is signed in. + //! If access tokens are available and not expired. + //! @param providerName Provider to check signed in for + //! @return bool True if valid access token available, else False + virtual bool IsSignedIn(const AZStd::string& providerName) = 0; + + //! Get cached tokens from last last successful sign-in for the provider. + //! @param providerName Provider to get authentication tokens + //! @return AuthenticationTokens tokens from successful authentication. + virtual AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) = 0; + + // Below methods have corresponding notifications for success and failures. + + //! Call sign in endpoint for provider password grant flow. + //! @param providerName Provider to call sign in. + //! @param username Username to use to for sign in. + //! @param password Password to use to for sign in. + virtual void PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0; + + //! Call sign in endpoint for provider password grant multi factor authentication flow. + //! @param providerName Provider to call MFA sign in. + //! @param username Username to use for MFA sign in. + //! @param password Password to use for MFA sign in. + virtual void PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0; + + //! Call confirm endpoint for provider password grant multi factor authentication flow . + //! @param providerName Provider to call MFA confirm sign in. + //! @param username Username to use for MFA confirm. + //! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm. + virtual void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0; + + //! Call code-pair endpoint for provider device grant flow. + //! @param providerName Provider to call device sign in. + virtual void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) = 0; + + //! Call tokens endpoint for provider device grant flow. + //! @param providerName Provider to call device confirm sign in. + virtual void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) = 0; + + //! Call refresh endpoint for provider refresh grant flow. + //! @param providerName Provider to call refresh tokens. + virtual void RefreshTokensAsync(const AZStd::string& providerName) = 0; + + //! Call refresh token if token not valid. If token valid, fires corresponding event. + //! @param providerName Provider to get access token for. + //! events: OnRefreshTokensSuccess, OnRefreshTokensFail + virtual void GetTokensWithRefreshAsync(const AZStd::string& providerName) = 0; + + //! Signs user out. + //! Clears all cached tokens. + //! @param providerName Provider to sign out. + //! @return bool True: Successfully sign out. + virtual bool SignOut(const AZStd::string& providerName) = 0; + + ////////////////////////////////////////////////////////////////////////// + }; + + //! Authentication Request bus for different supported providers. + class AuthenticationProviderScriptCanvasRequests + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + using MutexType = AZ::NullMutex; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + using AuthenticationProviderScriptCanvasRequestBus = AZ::EBus; + +} // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h index 1e10e66307..8bd31d6aeb 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h @@ -15,6 +15,14 @@ namespace AWSClientAuth { + constexpr char ProvideNameEnumStringNone[] = "None"; + constexpr char ProvideNameEnumStringAWSCognitoIDP[] = "AWSCognitoIDP"; + constexpr char ProvideNameEnumStringLoginWithAmazon[] = "LoginWithAmazon"; + constexpr char ProvideNameEnumStringGoogle[] = "Google"; + constexpr char ProvideNameEnumStringApple[] = "Apple"; + constexpr char ProvideNameEnumStringFacebook[] = "Facebook"; + constexpr char ProvideNameEnumStringTwitch[] = "Twitch"; + //! Holds Login with Amazon provider serialized settings class LWAProviderSetting { diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h index f690445c26..e26896fa06 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include namespace AWSClientAuth @@ -28,12 +29,18 @@ namespace AWSClientAuth void OnRequestAWSCredentialsSuccess(const ClientAuthAWSCredentials& awsCredentials) override { - Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials); + AZ::TickBus::QueueFunction([awsCredentials, this]() + { + Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials); + }); } void OnRequestAWSCredentialsFail(const AZStd::string& error) override { - Call(FN_OnRequestAWSCredentialsFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnRequestAWSCredentialsFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h index 06f2ae6e58..f5c2ca7ed1 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include namespace AWSClientAuth { @@ -32,62 +33,86 @@ namespace AWSClientAuth void OnEmailSignUpSuccess(const AZStd::string& uuid) override { - Call(FN_OnEmailSignUpSuccess, uuid); + AZ::TickBus::QueueFunction([uuid, this]() { + Call(FN_OnEmailSignUpSuccess, uuid); + }); } void OnEmailSignUpFail(const AZStd::string& error) override { - Call(FN_OnEmailSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnEmailSignUpFail, error); + }); } void OnPhoneSignUpSuccess(const AZStd::string& uuid) override { - Call(FN_OnPhoneSignUpSuccess, uuid); + AZ::TickBus::QueueFunction([uuid, this]() { + Call(FN_OnPhoneSignUpSuccess, uuid); + }); } void OnPhoneSignUpFail(const AZStd::string& error) override { - Call(FN_OnPhoneSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnPhoneSignUpFail, error); + }); } void OnConfirmSignUpSuccess() override { - Call(FN_OnConfirmSignUpSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnConfirmSignUpSuccess); + }); } void OnConfirmSignUpFail(const AZStd::string& error) override { - Call(FN_OnConfirmSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnConfirmSignUpFail, error); + }); } void OnForgotPasswordSuccess() override { - Call(FN_OnForgotPasswordSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnForgotPasswordSuccess); + }); } void OnForgotPasswordFail(const AZStd::string& error) override { - Call(FN_OnForgotPasswordFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnForgotPasswordFail, error); + }); } void OnConfirmForgotPasswordSuccess() override { - Call(FN_OnConfirmForgotPasswordSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnConfirmForgotPasswordSuccess); + }); } void OnConfirmForgotPasswordFail(const AZStd::string& error) override { - Call(FN_OnConfirmForgotPasswordFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnConfirmForgotPasswordFail, error); + }); } void OnEnableMFASuccess() override { - Call(FN_OnEnableMFASuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnEnableMFASuccess); + }); } void OnEnableMFAFail(const AZStd::string& error) override { - Call(FN_OnEnableMFAFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnEnableMFAFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h index 693adf1e65..9e822849bc 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h @@ -16,7 +16,7 @@ namespace AWSClientAuth { - //@ Abstract class for authentication provider requests. + //! Abstract class for authentication provider requests. class IAuthenticationProviderRequests { public: @@ -35,32 +35,40 @@ namespace AWSClientAuth virtual bool IsSignedIn(const ProviderNameEnum& providerName) = 0; //! Get cached tokens from last last successful sign-in for the provider. + //! @param providerName Provider to get authentication tokens. + //! @return AuthenticationTokens tokens from successful authentication. virtual AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) = 0; // Below methods have corresponding notifications for success and failures. //! Call sign in endpoint for provider password grant flow. + //! @param providerName Provider to call sign in. //! @param username Username to use to for sign in. //! @param password Password to use to for sign in. virtual void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0; //! Call sign in endpoint for provider password grant multi factor authentication flow. + //! @param providerName Provider to call MFA sign in. //! @param username Username to use for MFA sign in. //! @param password Password to use for MFA sign in. virtual void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0; //! Call confirm endpoint for provider password grant multi factor authentication flow . + //! @param providerName Provider to call MFA confirm sign in. //! @param username Username to use for MFA confirm. //! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm. virtual void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0; //! Call code-pair endpoint for provider device grant flow. + //! @param providerName Provider to call device sign in. virtual void DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName) = 0; //! Call tokens endpoint for provider device grant flow. + //! @param providerName Provider to call device confirm sign in. virtual void DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName) = 0; //! Call refresh endpoint for provider refresh grant flow. + //! @param providerName Provider to call refresh tokens. virtual void RefreshTokensAsync(const ProviderNameEnum& providerName) = 0; //! Call refresh token if token not valid. If token valid, fires corresponding event. diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h index 80138efd1b..3bb781f262 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h @@ -11,20 +11,15 @@ */ #pragma once +#include #include #include +#include +#include namespace AWSClientAuth { - enum class ProviderNameEnum - { - None, - AWSCognitoIDP, - LoginWithAmazon, - Google, - Apple, - Facebook - }; + AZ_ENUM_CLASS(ProviderNameEnum, None, AWSCognitoIDP, LoginWithAmazon, Twitch, Google, Apple, Facebook); //! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController. class AuthenticationTokens @@ -55,6 +50,8 @@ namespace AWSClientAuth //! @return Expiration time in seconds. int GetTokensExpireTimeSeconds() const; + static void Reflect(AZ::ReflectContext* context); + private: int m_tokensExpireTimeSeconds = 0; AZStd::string m_accessToken; diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h b/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h index 71a5703efd..2daac42a49 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include #include @@ -24,6 +24,14 @@ namespace AWSClientAuth { public: AZ_TYPE_INFO(ClientAuthAWSCredentials, "{02FB32C4-B94E-4084-9049-3DF32F87BD76}"); + ClientAuthAWSCredentials() = default; + ClientAuthAWSCredentials(const ClientAuthAWSCredentials& other) + : m_accessKeyId(other.m_accessKeyId) + , m_secretKey(other.m_secretKey) + , m_sessionToken(other.m_sessionToken) + + { + } ClientAuthAWSCredentials(const AZStd::string& accessKeyId, const AZStd::string& secretKey, const AZStd::string& sessionToken) { @@ -50,6 +58,32 @@ namespace AWSClientAuth return m_sessionToken; } + static void Reflect(AZ::ReflectContext* context) + { + auto serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId) + ->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey) + ->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken); + } + + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth") + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Constructor() + ->Constructor() + ->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId)) + ->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey)) + ->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken)); + } + } + private: AZStd::string m_accessKeyId; AZStd::string m_secretKey; diff --git a/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h b/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h index 89ddf0a999..aff68db365 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h +++ b/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h @@ -22,11 +22,12 @@ namespace AWSClientAuth public: AZ_TYPE_INFO(IAWSCognitoUserManagementRequests, "{A4C90F21-7056-4827-8C6B-401E6945697D}"); - //! Initialize Cognito User pool. + //! Initialize Cognito User pool using settings from resource mappings. //! @param settingsRegistryPath settingsRegistryPath Path for the settings registry file to use. virtual bool Initialize() = 0; // Requests interface + //! Cognito user pool email sign up start. //! @param username User name to use for sign up. //! @param password Password to use for sign up. @@ -59,7 +60,7 @@ namespace AWSClientAuth virtual void EnableMFAAsync(const AZStd::string& accessToken) = 0; }; - //! Manages various authentication provider implementations and implements AuthenticationProvider Request bus. + //! Implements AWS Cognito user pool user management requests. class AWSCognitoUserManagementRequests : public AZ::EBusTraits { diff --git a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp index 20efa354cc..008d56da0b 100644 --- a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp +++ b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp @@ -22,6 +22,11 @@ #include #include +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}"); +} + namespace AWSClientAuth { constexpr char SerializeComponentName[] = "AWSClientAuth"; @@ -44,20 +49,35 @@ namespace AWSClientAuth AWSClientAuth::GoogleProviderSetting::Reflect(*serialize); } + AWSClientAuth::AuthenticationTokens::Reflect(context); + AWSClientAuth::ClientAuthAWSCredentials::Reflect(context); + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("AuthenticationProviderRequestBus") + behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None") + ->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP") + ->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon") + ->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google"); + + behaviorContext->EBus("AuthenticationProviderRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) - ->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize) - ->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn) - ->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens) + ->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize) + ->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn) + ->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens) ->Event( - "PasswordGrantSingleFactorSignInAsync", &AuthenticationProviderRequestBus::Events::PasswordGrantSingleFactorSignInAsync) - ->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantSignInAsync) - ->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantConfirmSignInAsync) - ->Event("RefreshTokensAsync", &AuthenticationProviderRequestBus::Events::RefreshTokensAsync) - ->Event("GetTokensWithRefreshAsync", &AuthenticationProviderRequestBus::Events::GetTokensWithRefreshAsync) - ->Event("SignOut", &AuthenticationProviderRequestBus::Events::SignOut); + "PasswordGrantSingleFactorSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantSingleFactorSignInAsync) + ->Event( + "PasswordGrantMultiFactorSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorSignInAsync) + ->Event( + "PasswordGrantMultiFactorConfirmSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorConfirmSignInAsync) + ->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantSignInAsync) + ->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantConfirmSignInAsync) + ->Event("RefreshTokensAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::RefreshTokensAsync) + ->Event("GetTokensWithRefreshAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::GetTokensWithRefreshAsync) + ->Event("SignOut", &AuthenticationProviderScriptCanvasRequestBus::Events::SignOut); behaviorContext->EBus("AWSCognitoAuthorizationRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) @@ -77,11 +97,15 @@ namespace AWSClientAuth ->Event("ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync) ->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync); + behaviorContext->EBus("AuthenticationProviderNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoUserManagementNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoAuthorizationNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); } } diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp index eca5ba22c2..74865c0044 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp @@ -40,7 +40,7 @@ namespace AWSClientAuth AZ_UNUSED(settingsRegistry); AWSCore::AWSResourceMappingRequestBus::BroadcastResult( m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey); - AZ_Warning("AWSCognitoAuthenticationProvider", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); + AZ_Warning("AWSCognitoAuthenticationProvider", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); return !m_cognitoAppClientId.empty(); } diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp index 76d7c45c71..f6e5efd106 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -25,12 +26,14 @@ namespace AWSClientAuth { AZ::Interface::Register(this); AuthenticationProviderRequestBus::Handler::BusConnect(); + AuthenticationProviderScriptCanvasRequestBus::Handler::BusConnect(); } AuthenticationProviderManager::~AuthenticationProviderManager() { ResetProviders(); m_settingsRegistry.reset(); + AuthenticationProviderScriptCanvasRequestBus::Handler::BusDisconnect(); AuthenticationProviderRequestBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); } @@ -38,12 +41,19 @@ namespace AWSClientAuth bool AuthenticationProviderManager::Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) { ResetProviders(); + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "File IO is not initialized."); + m_settingsRegistry.reset(); m_settingsRegistry = AZStd::make_shared(); - if (!m_settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch)) + AZStd::array resolvedPath{}; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(settingsRegistryPath.data(), resolvedPath.data(), resolvedPath.size()); + + + if (!m_settingsRegistry->MergeSettingsFile(resolvedPath.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch)) { - AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", settingsRegistryPath.c_str()); + AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", resolvedPath.data()); return false; } @@ -112,6 +122,7 @@ namespace AWSClientAuth { AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail , "Provider is not initialized"); + return; } AuthenticationTokens tokens = m_authenticationProvidersMap[providerName]->GetAuthenticationTokens(); @@ -181,5 +192,77 @@ namespace AWSClientAuth } } + ProviderNameEnum AuthenticationProviderManager::GetProviderNameEnum(AZStd::string name) + { + auto enumValue = ProviderNameEnumNamespace::FromStringToProviderNameEnum(name); + if (enumValue.has_value()) + { + return enumValue.value(); + } + AZ_Warning("AuthenticationProviderManager", true, "Incorrect string value for enum: %s", name.c_str()); + return ProviderNameEnum::None; + } + + bool AuthenticationProviderManager::Initialize( + const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) + { + AZStd::vector providerNamesEnum; + for (auto name : providerNames) + { + providerNamesEnum.push_back(GetProviderNameEnum(name)); + } + return Initialize(providerNamesEnum, settingsRegistryPath); + } + + void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) + { + PasswordGrantSingleFactorSignInAsync(GetProviderNameEnum(providerName), username, password); + } + + void AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) + { + PasswordGrantMultiFactorSignInAsync(GetProviderNameEnum(providerName), username, password); + } + + void AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) + { + PasswordGrantMultiFactorConfirmSignInAsync(GetProviderNameEnum(providerName), username, confirmationCode); + } + + void AuthenticationProviderManager::DeviceCodeGrantSignInAsync(const AZStd::string& providerName) + { + DeviceCodeGrantSignInAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) + { + DeviceCodeGrantConfirmSignInAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::RefreshTokensAsync(const AZStd::string& providerName) + { + RefreshTokensAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::GetTokensWithRefreshAsync(const AZStd::string& providerName) + { + GetTokensWithRefreshAsync(GetProviderNameEnum(providerName)); + } + + bool AuthenticationProviderManager::IsSignedIn(const AZStd::string& providerName) + { + return IsSignedIn(GetProviderNameEnum(providerName)); + } + + bool AuthenticationProviderManager::SignOut(const AZStd::string& providerName) + { + return SignOut(GetProviderNameEnum(providerName)); + } + + AuthenticationTokens AuthenticationProviderManager::GetAuthenticationTokens(const AZStd::string& providerName) + { + return GetAuthenticationTokens(GetProviderNameEnum(providerName)); + } + } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp index 9c078ad99c..737d6ae929 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp @@ -79,4 +79,30 @@ namespace AWSClientAuth { return m_tokensExpireTimeSeconds; } + + void AuthenticationTokens::Reflect(AZ::ReflectContext* context) + { + auto serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Field("AccessToken", &AuthenticationTokens::m_accessToken) + ->Field("OpenIdToken", &AuthenticationTokens::m_openIdToken) + ->Field("RefreshToken", &AuthenticationTokens::m_refreshToken); + } + + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth") + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Constructor() + ->Constructor() + ->Property("AccessToken", BehaviorValueGetter(&AuthenticationTokens::m_accessToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)) + ->Property("OpenIdToken", BehaviorValueGetter(&AuthenticationTokens::m_openIdToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)) + ->Property("RefreshToken", BehaviorValueGetter(&AuthenticationTokens::m_refreshToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)); + } + } } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp b/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp index 4c10d968fc..5e2c07bdbb 100644 --- a/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp @@ -71,15 +71,15 @@ namespace AWSClientAuth if (m_awsAccountId.empty() || m_cognitoIdentityPoolId.empty()) { - AZ_Warning("AWSCognitoUserManagementController", m_awsAccountId.empty(), "Missing AWS account id in resource mappings."); - AZ_Warning("AWSCognitoUserManagementController", m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings."); + AZ_Warning("AWSCognitoAuthorizationController", !m_awsAccountId.empty(), "Missing AWS account id not configured."); + AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings."); return false; } AZStd::string userPoolId; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( userPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoUserPoolIdResourceMappingKey); - AZ_Warning("AWSCognitoUserManagementController", userPoolId.empty(), "Missing Cognito USer pool id in resource mappings. Cognito IDP authenticated identities will no work."); + AZ_Warning("AWSCognitoAuthorizationController", !userPoolId.empty(), "Missing Cognito User pool id in resource mappings. Cognito IDP authenticated identities will no work."); AZStd::string defaultRegion; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( diff --git a/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp b/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp index 19d5d47d33..755b0e1f15 100644 --- a/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp +++ b/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp @@ -54,7 +54,7 @@ namespace AWSClientAuth AWSCore::AWSResourceMappingRequestBus::BroadcastResult( m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey); AZ_Warning( - "AWSCognitoUserManagementController", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); + "AWSCognitoUserManagementController", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); return !m_cognitoAppClientId.empty(); } diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h new file mode 100644 index 0000000000..e7b233c786 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h @@ -0,0 +1,55 @@ +/* +* 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 AWSClientAuthUnitTest +{ + class AuthenticationProviderManagerLocalMock + : public AWSClientAuth::AuthenticationProviderManager + { + public: + using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens; + using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync; + using AWSClientAuth::AuthenticationProviderManager::Initialize; + using AWSClientAuth::AuthenticationProviderManager::IsSignedIn; + using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync; + using AWSClientAuth::AuthenticationProviderManager::SignOut; + + AZStd::unique_ptr CreateAuthenticationProviderObjectMock( + const AWSClientAuth::ProviderNameEnum& providerName) + { + auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName); + providerObject.reset(); + return AZStd::make_unique>(); + } + + AuthenticationProviderManagerLocalMock() + { + ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)) + .WillByDefault(testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock)); + } + + MOCK_METHOD1( + CreateAuthenticationProviderObject, + AZStd::unique_ptr(const AWSClientAuth::ProviderNameEnum&)); + }; +} // namespace AWSClientAuthUnitTest diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp new file mode 100644 index 0000000000..7673840299 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp @@ -0,0 +1,261 @@ +/* +* 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 +#include +#include +#include +#include + + +class AuthenticationProviderManagerScriptCanvasTest + : public AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture +{ +protected: + void SetUp() override + { + AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp(); + + AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext); + AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext); + + m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg", + m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder); + CreateTestFile("authenticationProvider.setreg" + , R"({ + "AWS": + { + "LoginWithAmazon": + { + "AppClientId": "TestLWAClientId", + "GrantType": "device_code", + "Scope": "profile", + "ResponseType": "device_code", + "OAuthCodeURL": "https://api.amazon.com/auth/o2/create/codepair", + "OAuthTokensURL": "https://oauth2.googleapis.com/token" + }, + "Google": + { + "AppClientId": "TestGoogleClientId", + "ClientSecret": "123", + "GrantType": "urn:ietf:params:oauth:grant-type:device_code", + "Scope": "profile", + "OAuthCodeURL": "https://oauth2.googleapis.com/device/code", + "OAuthTokensURL": "https://oauth2.googleapis.com/token" + } + } + })"); + + m_mockController = AZStd::make_unique>(); + } + + void TearDown() override + { + m_mockController.reset(); + AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::TearDown(); + } + +public: + AZStd::unique_ptr> m_mockController; + AZStd::string m_settingspath; + AZStd::vector m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, + AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle}; +}; + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success) +{ + ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath)); + ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Fail_NonConfiguredProviderError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringApple, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock *lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock *lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 600); + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + AWSClientAuth::AuthenticationTokens tokens; + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60); + + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + m_mockController->GetAuthenticationTokens(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60); + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + m_mockController->IsSignedIn(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* googleProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get(); + + EXPECT_CALL(*googleProviderMock, SignOut()).Times(1); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnSignOut(testing::_)).Times(1); + m_mockController->SignOut(AWSClientAuth::ProvideNameEnumStringGoogle); + + googleProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, "")); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp index 9e7d189f5d..4b5bdfb841 100644 --- a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp @@ -10,8 +10,6 @@ * */ -#include -#include #include #include #include @@ -20,42 +18,7 @@ #include #include #include - -namespace AWSClientAuthUnitTest -{ - class AuthenticationProviderManagerLocalMock - : public AWSClientAuth::AuthenticationProviderManager - { - public: - using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap; - using AWSClientAuth::AuthenticationProviderManager::Initialize; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync; - using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync; - using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens; - using AWSClientAuth::AuthenticationProviderManager::SignOut; - using AWSClientAuth::AuthenticationProviderManager::IsSignedIn; - - AZStd::unique_ptr CreateAuthenticationProviderObjectMock(const AWSClientAuth::ProviderNameEnum& providerName) - { - auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName); - providerObject.reset(); - return AZStd::make_unique>(); - } - - AuthenticationProviderManagerLocalMock() - { - ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)).WillByDefault( - testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock)); - } - - MOCK_METHOD1(CreateAuthenticationProviderObject, AZStd::unique_ptr(const AWSClientAuth::ProviderNameEnum&)); - }; -} +#include class AuthenticationProviderManagerTest @@ -239,6 +202,15 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken cognitoProviderMock = nullptr; } +TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProviderNameEnum::AWSCognitoIDP); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + TEST_F(AuthenticationProviderManagerTest, GetTokens_Success) { m_mockController->Initialize(m_enabledProviderNames, m_settingspath); diff --git a/Gems/AWSClientAuth/Code/awsclientauth_files.cmake b/Gems/AWSClientAuth/Code/awsclientauth_files.cmake index 79da00076c..7e4734992f 100644 --- a/Gems/AWSClientAuth/Code/awsclientauth_files.cmake +++ b/Gems/AWSClientAuth/Code/awsclientauth_files.cmake @@ -20,6 +20,7 @@ set(FILES Include/Private/AWSClientAuthBus.h Include/Private/AWSClientAuthResourceMappingConstants.h Include/Private/Authentication/AuthenticationProviderTypes.h + Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h Include/Private/Authentication/AuthenticationProviderManager.h Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h diff --git a/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake b/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake index 6d3de7cc54..18aaa697dd 100644 --- a/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake +++ b/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake @@ -14,7 +14,9 @@ set(FILES Tests/AWSClientAuthGemTest.cpp Tests/AWSClientAuthSystemComponentTest.cpp + Tests/Authentication/AuthenticationProviderManagerMock.h Tests/Authentication/AuthenticationProviderManagerTest.cpp + Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp Tests/Authentication/AWSCognitoAuthenticationProviderTest.cpp Tests/Authentication/LWAAuthenticationProviderTest.cpp Tests/Authentication/GoogleAuthenticationProviderTest.cpp diff --git a/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py b/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py index 0ebef83eba..3a2e413617 100755 --- a/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py +++ b/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py @@ -56,8 +56,7 @@ class CognitoIdentityPoolRole: # basic permissions stack_statement = iam.PolicyStatement( actions=[ - 's3:Get*', - 's3:List*' + 's3:ListBuckets' ], effect=iam.Effect.ALLOW, resources=[ diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp index fd4b5b28d1..dc53498c8b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp @@ -289,7 +289,7 @@ namespace AZ void AuxGeomDrawQueue::DrawQuad( float width, float height, - const AZ::Transform& transform, + const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, @@ -302,8 +302,8 @@ namespace AZ return; } - Transform noScaleTransform = transform; - noScaleTransform.ExtractScale(); + AZ::Matrix3x4 noScaleTransform = transform; + AZ::Vector3 scale = noScaleTransform.ExtractScale(); ShapeBufferEntry shape; shape.m_shapeType = ShapeType_Quad; @@ -311,9 +311,9 @@ namespace AZ shape.m_depthWrite = ConvertRPIDepthWriteFlag(depthWrite); shape.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull); shape.m_color = color; - shape.m_rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + shape.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleTransform); shape.m_position = transform.GetTranslation(); - shape.m_scale = transform.GetScale() * Vector3(width, 1.0f, height); + shape.m_scale = scale * Vector3(width, 1.0f, height); shape.m_pointSize = m_pointSize; shape.m_viewProjOverrideIndex = viewProjOverrideIndex; diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h index b959173ed1..53220c031d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h @@ -62,7 +62,7 @@ namespace AZ void DrawTriangles(const AuxGeomDynamicIndexedDrawArguments& args, FaceCullMode faceCull = FaceCullMode::None) override; // Fixed shape draws - void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; + void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawSphere(const AZ::Vector3& center, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawDisk(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawCone(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, float height, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h index afba71a457..0e7f11e46e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h @@ -138,7 +138,7 @@ namespace AZ //! @param depthWrite If depth writing should be enabled //! @param faceCull Which (if any) facing triangles should be culled //! @param viewProjOverrideIndex Which view projection override entry to use, -1 if unused - virtual void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0; + virtual void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0; //! Draw a sphere. //! @param center The center of the sphere. diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index ec7aa17151..4cab7b8869 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -15,811 +15,1206 @@ #include #include #include +#include +#include #include #include #include -namespace AZ +#include + +namespace // unnamed namespace to hold copies of Cry AuxGeom state enum's, this is to avoid creating a dependency on IRenderAuxGeom.h { - namespace AtomBridge + // Notes: + // Don't change the xxxShift values, they need to match the values from legacy cry rendering + // This also applies to the individual flags in EAuxGeomPublicRenderflags_*! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + enum EAuxGeomPublicRenderflagBitMasks { + e_Mode2D3DShift = 31, + e_Mode2D3DMask = 0x1 << e_Mode2D3DShift, - //////////////////////////////////////////////////////////////////////// - SingleColorDynamicSizeLineHelper::SingleColorDynamicSizeLineHelper( - int estimatedNumLineSegments - ) + e_AlphaBlendingShift = 29, + e_AlphaBlendingMask = 0x3 << e_AlphaBlendingShift, + + e_DrawInFrontShift = 28, + e_DrawInFrontMask = 0x1 << e_DrawInFrontShift, + + e_FillModeShift = 26, + e_FillModeMask = 0x3 << e_FillModeShift, + + e_CullModeShift = 24, + e_CullModeMask = 0x3 << e_CullModeShift, + + e_DepthWriteShift = 23, + e_DepthWriteMask = 0x1 << e_DepthWriteShift, + + e_DepthTestShift = 22, + e_DepthTestMask = 0x1 << e_DepthTestShift, + + e_PublicParamsMask = e_Mode2D3DMask | e_AlphaBlendingMask | e_DrawInFrontMask | e_FillModeMask | + e_CullModeMask | e_DepthWriteMask | e_DepthTestMask + }; + + // Notes: + // e_Mode2D renders in normalized [0.. 1] screen space. + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_Mode2D3D + { + e_Mode3D = 0x0 << e_Mode2D3DShift, + e_Mode2D = 0x1 << e_Mode2D3DShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_AlphaBlendMode + { + e_AlphaNone = 0x0 << e_AlphaBlendingShift, + e_AlphaAdditive = 0x1 << e_AlphaBlendingShift, + e_AlphaBlended = 0x2 << e_AlphaBlendingShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DrawInFrontMode + { + e_DrawInFrontOff = 0x0 << e_DrawInFrontShift, + e_DrawInFrontOn = 0x1 << e_DrawInFrontShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_FillMode + { + e_FillModeSolid = 0x0 << e_FillModeShift, + e_FillModeWireframe = 0x1 << e_FillModeShift, + e_FillModePoint = 0x2 << e_FillModeShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_CullMode + { + e_CullModeNone = 0x0 << e_CullModeShift, + e_CullModeFront = 0x1 << e_CullModeShift, + e_CullModeBack = 0x2 << e_CullModeShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DepthWrite + { + e_DepthWriteOn = 0x0 << e_DepthWriteShift, + e_DepthWriteOff = 0x1 << e_DepthWriteShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DepthTest + { + e_DepthTestOn = 0x0 << e_DepthTestShift, + e_DepthTestOff = 0x1 << e_DepthTestShift, + }; +}; + +namespace AZ::AtomBridge +{ + + //////////////////////////////////////////////////////////////////////// + SingleColorDynamicSizeLineHelper::SingleColorDynamicSizeLineHelper( + int estimatedNumLineSegments + ) + { + m_points.reserve(estimatedNumLineSegments * 2); + } + + void SingleColorDynamicSizeLineHelper::AddLineSegment( + const AZ::Vector3& lineStart, + const AZ::Vector3& lineEnd + ) + { + m_points.push_back(lineStart); + m_points.push_back(lineEnd); + } + + void SingleColorDynamicSizeLineHelper::Draw( + AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, + const RenderState& rendState + ) const + { + if (auxGeomDrawPtr && !m_points.empty()) { - m_points.reserve(estimatedNumLineSegments * 2); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = rendState.m_viewProjOverrideIndex; + auxGeomDrawPtr->DrawLines( drawArgs ); } + } - void SingleColorDynamicSizeLineHelper::AddLineSegment( - const AZ::Vector3& lineStart, - const AZ::Vector3& lineEnd - ) + void SingleColorDynamicSizeLineHelper::Draw2d( + AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, + const RenderState& rendState + ) const + { + if (auxGeomDrawPtr && !m_points.empty()) { - m_points.push_back(lineStart); - m_points.push_back(lineEnd); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride(); + auxGeomDrawPtr->DrawLines( drawArgs ); } + } - void SingleColorDynamicSizeLineHelper::Draw( - AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, - const RenderState& rendState - ) const - { - if (auxGeomDrawPtr && !m_points.empty()) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = m_points.data(); - drawArgs.m_vertCount = aznumeric_cast(m_points.size()); - drawArgs.m_colors = &rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = rendState.m_lineWidth; - drawArgs.m_opacityType = rendState.m_opacityType; - drawArgs.m_depthTest = rendState.m_depthTest; - drawArgs.m_depthWrite = rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = rendState.m_viewProjOverrideIndex; - auxGeomDrawPtr->DrawLines( drawArgs ); - } - } + void SingleColorDynamicSizeLineHelper::Reset() + { + m_points.clear(); + } + //////////////////////////////////////////////////////////////////////// - void SingleColorDynamicSizeLineHelper::Reset() + // Partial implementation of the DebugDisplayRequestBus on Atom. + // Commented out function prototypes are waiting to be implemented. + // work tracked in [ATOM-3459] + AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr) + { + ResetRenderState(); + m_viewportId = viewportContextPtr->GetId(); + m_defaultInstance = false; + auto setupScene = [this](RPI::ScenePtr scene) { - m_points.clear(); - } - //////////////////////////////////////////////////////////////////////// + auto viewportContextManager = AZ::Interface::Get(); + AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId); + InitInternal(scene.get(), viewportContextPtr); + }; + setupScene(viewportContextPtr->GetRenderScene()); + m_sceneChangeHandler = AZ::RPI::ViewportContext::SceneChangedEvent::Handler(setupScene); + viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler); + } - // Partial implementation of the DebugDisplayRequestBus on Atom. - // Commented out function prototypes are waiting to be implemented. - // work tracked in [ATOM-3459] - AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr) - { - ResetRenderState(); - m_viewportId = viewportContextPtr->GetId(); - m_defaultInstance = false; - auto setupScene = [this](RPI::ScenePtr scene) - { - auto viewportContextManager = AZ::Interface::Get(); - AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId); - InitInternal(scene.get(), viewportContextPtr); - }; - setupScene(viewportContextPtr->GetRenderScene()); - m_sceneChangeHandler = AZ::RPI::ViewportContext::SceneChangedEvent::Handler(setupScene); - viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler); - } + AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress) + { + ResetRenderState(); + m_viewportId = defaultInstanceAddress; + m_defaultInstance = true; + RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); + InitInternal(scene, nullptr); + } - AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress) + void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) + { + AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + if (!scene) { - ResetRenderState(); - m_viewportId = defaultInstanceAddress; - m_defaultInstance = true; - RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - InitInternal(scene, nullptr); - } - - void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) - { - AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); - if (!scene) - { - m_auxGeomPtr = nullptr; - return; - } - auto auxGeomFP = scene->GetFeatureProcessor(); - if (!auxGeomFP) - { - m_auxGeomPtr = nullptr; - return; - } - if (m_defaultInstance) - { - m_auxGeomPtr = auxGeomFP->GetDrawQueue(); - } - else - { - m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get()); - } - AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId); - } - - AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface() - { - AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); - m_viewportId = AzFramework::InvalidViewportId; m_auxGeomPtr = nullptr; + return; + } + auto auxGeomFP = scene->GetFeatureProcessor(); + if (!auxGeomFP) + { + m_auxGeomPtr = nullptr; + return; + } + if (m_defaultInstance) + { + m_auxGeomPtr = auxGeomFP->GetDrawQueue(); + } + else + { + m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get()); + } + AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId); + } + + AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface() + { + AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + m_viewportId = AzFramework::InvalidViewportId; + m_auxGeomPtr = nullptr; + } + + void AtomDebugDisplayViewportInterface::ResetRenderState() + { + m_rendState = RenderState(); + for (int index = 0; index < RenderState::TransformStackSize; ++index) + { + m_rendState.m_transformStack[index] = AZ::Matrix3x4::Identity(); + } + } + + void AtomDebugDisplayViewportInterface::SetColor(float r, float g, float b, float a) + { + m_rendState.m_color = AZ::Color(r, g, b, a); + } + + void AtomDebugDisplayViewportInterface::SetColor(const AZ::Color& color) + { + m_rendState.m_color = color; + } + + void AtomDebugDisplayViewportInterface::SetColor(const AZ::Vector4& color) + { + m_rendState.m_color = AZ::Color(color); + } + + void AtomDebugDisplayViewportInterface::SetAlpha(float a) + { + m_rendState.m_color.SetA(a); + if (a < 1.0f) + { + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; + } + else + { + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; + } + } + + void AtomDebugDisplayViewportInterface::DrawQuad( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4) + { + if (m_auxGeomPtr) + { + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::Vector3 triangles[6]; + triangles[0] = wsPoints[0]; + triangles[1] = wsPoints[1]; + triangles[2] = wsPoints[2]; + triangles[3] = wsPoints[2]; + triangles[4] = wsPoints[3]; + triangles[5] = wsPoints[0]; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = triangles; + drawArgs.m_vertCount = 6; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawQuad(float width, float height) + { + if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f) + { + return; } - void AtomDebugDisplayViewportInterface::ResetRenderState() + m_auxGeomPtr->DrawQuad( + width, + height, + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + + void AtomDebugDisplayViewportInterface::DrawWireQuad( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4) + { + if (m_auxGeomPtr) { - m_rendState = RenderState(); - for (int index = 0; index < RenderState::TransformStackSize; ++index) + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = wsPoints; + drawArgs.m_vertCount = 4; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireQuad(float width, float height) + { + if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f) + { + return; + } + + m_auxGeomPtr->DrawQuad( + width, + height, + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + + void AtomDebugDisplayViewportInterface::DrawQuadGradient( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4, + const AZ::Vector4& firstColor, + const AZ::Vector4& secondColor) + { + if (m_auxGeomPtr) + { + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::Vector3 triangles[6]; + AZ::Color colors[6]; + triangles[0] = wsPoints[0]; colors[0] = firstColor; + triangles[1] = wsPoints[1]; colors[1] = firstColor; + triangles[2] = wsPoints[2]; colors[2] = secondColor; + triangles[3] = wsPoints[2]; colors[3] = secondColor; + triangles[4] = wsPoints[3]; colors[4] = secondColor; + triangles[5] = wsPoints[0]; colors[5] = firstColor; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = triangles; + drawArgs.m_vertCount = 6; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 6; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) + { + if (m_auxGeomPtr) + { + AZ::Vector3 verts[3] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 3; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) + { + if (m_auxGeomPtr) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = vertices.data(); + drawArgs.m_vertCount = aznumeric_cast(vertices.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawTrianglesIndexed( + const AZStd::vector& vertices, + const AZStd::vector& indices, + const AZ::Color& color) + { + if (m_auxGeomPtr) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicIndexedDrawArguments drawArgs; + drawArgs.m_verts = vertices.data(); + drawArgs.m_vertCount = aznumeric_cast(vertices.size()); + drawArgs.m_indices = indices.data(); + drawArgs.m_indexCount = aznumeric_cast(indices.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) + { + if (m_auxGeomPtr) + { + m_auxGeomPtr->DrawAabb( + AZ::Aabb::CreateFromMinMax(min, max), + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + } + } + + void AtomDebugDisplayViewportInterface::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) + { + if (m_auxGeomPtr) + { + m_auxGeomPtr->DrawAabb( + AZ::Aabb::CreateFromMinMax(min, max), + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + } + + void AtomDebugDisplayViewportInterface::DrawSolidOBB( + const AZ::Vector3& center, + const AZ::Vector3& axisX, + const AZ::Vector3& axisY, + const AZ::Vector3& axisZ, + const AZ::Vector3& halfExtents) + { + if (m_auxGeomPtr) + { + AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ)); + AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents); + m_auxGeomPtr->DrawObb( + obb, + AZ::Vector3::CreateZero(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + } + + void AtomDebugDisplayViewportInterface::DrawPoint(const AZ::Vector3& p, int nSize) + { + if (m_auxGeomPtr) + { + AZ::Vector3 wsPoint = ToWorldSpacePosition(p); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = &wsPoint; + drawArgs.m_vertCount = 1; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = aznumeric_cast(nSize); + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPoints(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) + { + if (m_auxGeomPtr) + { + AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) + { + if (m_auxGeomPtr) + { + AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; + AZ::Color colors[2] = {col1, col2}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 2; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawLines(const AZStd::vector& lines, const AZ::Color& color) + { + if (m_auxGeomPtr) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = lines.data(); + drawArgs.m_vertCount = aznumeric_cast(lines.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); + } + } + + void AtomDebugDisplayViewportInterface::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled) + { + if (m_auxGeomPtr) + { + AZStd::vector wsPoints(static_cast(numPoints)); + for (int index = 0; index < numPoints; ++index) { - m_rendState.m_transformStack[index] = AZ::Matrix3x4::Identity(); + wsPoints[index] = ToWorldSpacePosition(pnts[index]); } + AZ::RPI::AuxGeomDraw::PolylineEnd polylineEnd = cycled ? AZ::RPI::AuxGeomDraw::PolylineEnd::Closed : AZ::RPI::AuxGeomDraw::PolylineEnd::Open; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = wsPoints.data(); + drawArgs.m_vertCount = aznumeric_cast(numPoints); + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPolylines(drawArgs, polylineEnd); } + } - void AtomDebugDisplayViewportInterface::SetColor(float r, float g, float b, float a) + void AtomDebugDisplayViewportInterface::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) + { + if (m_auxGeomPtr) { - m_rendState.m_color = AZ::Color(r, g, b, a); + AZ::Vector3 points[4]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p1.GetY(), z); + points[2] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + points[3] = AZ::Vector3(p1.GetX(), p2.GetY(), z); + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 4; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed); } + } - void AtomDebugDisplayViewportInterface::SetColor(const AZ::Color& color) + void AtomDebugDisplayViewportInterface::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) + { + if (m_auxGeomPtr) { - m_rendState.m_color = color; + AZ::Vector3 points[2]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::SetColor(const AZ::Vector4& color) + void AtomDebugDisplayViewportInterface::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) + { + if (m_auxGeomPtr) { - m_rendState.m_color = AZ::Color(color); + AZ::Vector3 points[2]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + AZ::Color colors[2] = {firstColor, secondColor}; + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 2; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::SetAlpha(float a) + void AtomDebugDisplayViewportInterface::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) + { + if (m_auxGeomPtr) { - m_rendState.m_color.SetA(a); - if (a < 1.0f) + // Draw axis aligned arc + constexpr float angularStepDegrees = 10.0f; + constexpr float startAngleDegrees = 0.0f; + constexpr float sweepAngleDegrees = 360.0f; + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + AZ::Vector3 pos = AZ::Vector3(center.GetX(), center.GetY(), z); + CreateAxisAlignedArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + CircleAxis::CircleAxisZ + ); + lines.Draw2d(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawArc( + const AZ::Vector3& pos, + float radius, + float startAngleDegrees, + float sweepAngleDegrees, + float angularStepDegrees, + int referenceAxis) + { + if (m_auxGeomPtr) + { + // Draw axis aligned arc + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateAxisAlignedArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + static_cast(referenceAxis) + ); + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawArc( + const AZ::Vector3& pos, + float radius, + float startAngleDegrees, + float sweepAngleDegrees, + float angularStepDegrees, + const AZ::Vector3& fixedAxis) + { + if (m_auxGeomPtr) + { + // Draw arbitraty axis arc + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateArbitraryAxisArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + fixedAxis + ); + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis) + { + if (m_auxGeomPtr) + { + // Draw circle with default radius. + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateAxisAlignedArc( + lines, + step, + 0.0f, + maxAngle, + pos, + radiusV3, + static_cast(nUnchangedAxis)); + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis) + { + if (m_auxGeomPtr) + { + // Draw circle with single radius. + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. + + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldView = ToWorldSpacePosition(viewPos); + const AZ::Vector3 worldDir = worldView - worldPos; + + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, radiusV3, static_cast(nUnchangedAxis%CircleAxisMax), + [&worldPos, &worldDir](const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex) + { + AZ_UNUSED(lineEnd); + const float dot = (lineStart - worldPos).Dot(worldDir); + const bool facing = dot > 0.0f; + // if so skip every other line to produce a dotted effect + if (facing || segmentIndex % 2 == 0) + { + return true; + } + return false; + }); + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) + { + if (m_auxGeomPtr) + { + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); + m_auxGeomPtr->DrawCone( + worldPos, + worldDir, + radius, + height, + m_rendState.m_color, + drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) + { + if (m_auxGeomPtr) + { + const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); + const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); + m_auxGeomPtr->DrawCylinder( + worldCenter, + worldAxis, + radius, + height, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + } + } + + void AtomDebugDisplayViewportInterface::DrawSolidCylinder( + const AZ::Vector3& center, + const AZ::Vector3& axis, + float radius, + float height, + bool drawShaded) + { + if (m_auxGeomPtr) + { + const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); + const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); + m_auxGeomPtr->DrawCylinder( + worldCenter, + worldAxis, + radius, + height, + m_rendState.m_color, + drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireCapsule( + const AZ::Vector3& center, + const AZ::Vector3& axis, + float radius, + float heightStraightSection) + { + if (m_auxGeomPtr && radius > FLT_EPSILON && axis.GetLengthSq() > FLT_EPSILON) + { + AZ::Vector3 axisNormalized = axis.GetNormalizedEstimate(); + SingleColorStaticSizeLineHelper<(16+1) * 5> lines; // 360/22.5 = 16, 5 possible calls to CreateArbitraryAxisArc + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + float stepAngle = DegToRad(22.5f); + float Deg0 = DegToRad(0.0f); + + + // Draw cylinder part (or just a circle around the middle) + if (heightStraightSection > FLT_EPSILON) { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; + DrawWireCylinder(center, axis, radius, heightStraightSection); } else { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; - } - } - - void AtomDebugDisplayViewportInterface::DrawQuad( - const AZ::Vector3& p1, - const AZ::Vector3& p2, - const AZ::Vector3& p3, - const AZ::Vector3& p4) - { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; - AZ::Vector3 triangles[6]; - triangles[0] = wsPoints[0]; - triangles[1] = wsPoints[1]; - triangles[2] = wsPoints[2]; - triangles[3] = wsPoints[2]; - triangles[4] = wsPoints[3]; - triangles[5] = wsPoints[0]; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = triangles; - drawArgs.m_vertCount = 6; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } - } - - // void DrawQuad(float width, float height) override - // void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawWireQuad(float width, float height) override; - - void AtomDebugDisplayViewportInterface::DrawQuadGradient( - const AZ::Vector3& p1, - const AZ::Vector3& p2, - const AZ::Vector3& p3, - const AZ::Vector3& p4, - const AZ::Vector4& firstColor, - const AZ::Vector4& secondColor) - { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; - AZ::Vector3 triangles[6]; - AZ::Color colors[6]; - triangles[0] = wsPoints[0]; colors[0] = firstColor; - triangles[1] = wsPoints[1]; colors[1] = firstColor; - triangles[2] = wsPoints[2]; colors[2] = secondColor; - triangles[3] = wsPoints[2]; colors[3] = secondColor; - triangles[4] = wsPoints[3]; colors[4] = secondColor; - triangles[5] = wsPoints[0]; colors[5] = firstColor; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = triangles; - drawArgs.m_vertCount = 6; - drawArgs.m_colors = colors; - drawArgs.m_colorCount = 6; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) - { - if (m_auxGeomPtr) - { - AZ::Vector3 verts[3] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 3; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) - { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = vertices.data(); - drawArgs.m_vertCount = aznumeric_cast(vertices.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawTrianglesIndexed( - const AZStd::vector& vertices, - const AZStd::vector& indices, - const AZ::Color& color) - { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicIndexedDrawArguments drawArgs; - drawArgs.m_verts = vertices.data(); - drawArgs.m_vertCount = aznumeric_cast(vertices.size()); - drawArgs.m_indices = indices.data(); - drawArgs.m_indexCount = aznumeric_cast(indices.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) - { - if (m_auxGeomPtr) - { - m_auxGeomPtr->DrawAabb( - AZ::Aabb::CreateFromMinMax(min, max), - GetCurrentTransform(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex + float Deg360 = DegToRad(360.0f); + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg0, + Deg360, + center, + radiusV3, + axisNormalized ); } - } - void AtomDebugDisplayViewportInterface::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) - { - if (m_auxGeomPtr) - { - m_auxGeomPtr->DrawAabb( - AZ::Aabb::CreateFromMinMax(min, max), - GetCurrentTransform(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex); - } - } + float Deg90 = DegToRad(90.0f); + float Deg180 = DegToRad(180.0f); - void AtomDebugDisplayViewportInterface::DrawSolidOBB( - const AZ::Vector3& center, - const AZ::Vector3& axisX, - const AZ::Vector3& axisY, - const AZ::Vector3& axisZ, - const AZ::Vector3& halfExtents) - { - if (m_auxGeomPtr) - { - AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ)); - AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents); - m_auxGeomPtr->DrawObb( - obb, - AZ::Vector3::CreateZero(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex); - } - } + AZ::Vector3 ortho1Normalized, ortho2Normalized; + CalcBasisVectors(axisNormalized, ortho1Normalized, ortho2Normalized); + AZ::Vector3 centerToTopCircleCenter = axisNormalized * heightStraightSection * 0.5f; + AZ::Vector3 topCenter = center + centerToTopCircleCenter; + AZ::Vector3 bottomCenter = center - centerToTopCircleCenter; - void AtomDebugDisplayViewportInterface::DrawPoint(const AZ::Vector3& p, int nSize) - { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoint = ToWorldSpacePosition(p); - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = &wsPoint; - drawArgs.m_vertCount = 1; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = aznumeric_cast(nSize); - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawPoints(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) - { - if (m_auxGeomPtr) - { - AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) - { - if (m_auxGeomPtr) - { - AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; - AZ::Color colors[2] = {col1, col2}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = colors; - drawArgs.m_colorCount = 2; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawLines(const AZStd::vector& lines, const AZ::Color& color) - { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = lines.data(); - drawArgs.m_vertCount = aznumeric_cast(lines.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); - } - } - - void AtomDebugDisplayViewportInterface::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled) - { - if (m_auxGeomPtr) - { - AZStd::vector wsPoints(static_cast(numPoints)); - for (int index = 0; index < numPoints; ++index) - { - wsPoints[index] = ToWorldSpacePosition(pnts[index]); - } - AZ::RPI::AuxGeomDraw::PolylineEnd polylineEnd = cycled ? AZ::RPI::AuxGeomDraw::PolylineEnd::Closed : AZ::RPI::AuxGeomDraw::PolylineEnd::Open; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = wsPoints.data(); - drawArgs.m_vertCount = aznumeric_cast(numPoints); - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawPolylines(drawArgs, polylineEnd); - } - } - - // void AtomDebugDisplayViewportInterface::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void AtomDebugDisplayViewportInterface::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void AtomDebugDisplayViewportInterface::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; - // void AtomDebugDisplayViewportInterface::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; - - void AtomDebugDisplayViewportInterface::DrawArc( - const AZ::Vector3& pos, - float radius, - float startAngleDegrees, - float sweepAngleDegrees, - float angularStepDegrees, - int referenceAxis) - { - if (m_auxGeomPtr) - { - // Draw axis aligned arc - const float stepAngle = DegToRad(angularStepDegrees); - const float startAngle = DegToRad(startAngleDegrees); - const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; - SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateAxisAlignedArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, - radiusV3, - static_cast(referenceAxis) - ); - lines.Draw(m_auxGeomPtr, m_rendState); - } - } - - void AtomDebugDisplayViewportInterface::DrawArc( - const AZ::Vector3& pos, - float radius, - float startAngleDegrees, - float sweepAngleDegrees, - float angularStepDegrees, - const AZ::Vector3& fixedAxis) - { - if (m_auxGeomPtr) - { - // Draw arbitraty axis arc - const float stepAngle = DegToRad(angularStepDegrees); - const float startAngle = DegToRad(startAngleDegrees); - const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; - SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateArbitraryAxisArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, + // Draw top cap as two criss-crossing 180deg arcs + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg90, + Deg90 + Deg180, + topCenter, radiusV3, - fixedAxis + ortho1Normalized + ); + + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg180, + Deg180 + Deg180, + topCenter, + radiusV3, + ortho2Normalized + ); + + // Draw bottom cap + CreateArbitraryAxisArc( + lines, + stepAngle, + -Deg90, + -Deg90 + Deg180, + bottomCenter, + radiusV3, + ortho1Normalized + ); + + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg0, + Deg0 + Deg180, + bottomCenter, + radiusV3, + ortho2Normalized + ); + + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, float radius) + { + if (m_auxGeomPtr) + { + + m_auxGeomPtr->DrawSphere( + ToWorldSpacePosition(pos), + radius, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) + { + if (m_auxGeomPtr) + { + // This matches Cry behavior, the DrawWireSphere above may need modifying to use the same approach. + // Draw 3 axis aligned circles + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40*3> lines; // hard code to 40 lines * 3 circles until DegToRad is constexpr. + + // Z Axis + AZ::Vector3 axisRadius(radius.GetX(), radius.GetY(), 0.0f); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisZ); + + // X Axis + axisRadius = AZ::Vector3(0.0f, radius.GetY(), radius.GetZ()); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisX); + + // Y Axis + axisRadius = AZ::Vector3(radius.GetX(), 0.0f, radius.GetZ()); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisY); + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) + { + if (m_auxGeomPtr) + { + + // Draw 3 axis aligned circles + const float stepAngle = DegToRad(11.25f); + const float startAngle = DegToRad(0.0f); + const float stopAngle = DegToRad(360.0f) + startAngle; + SingleColorDynamicSizeLineHelper lines(2+static_cast(360.0f/11.25f)); // num disk segments + 1 for azis line + 1 for spare + const AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateArbitraryAxisArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + dir + ); + + lines.AddLineSegment(ToWorldSpacePosition(pos), ToWorldSpacePosition(pos + dir * (radius * 0.2f))); // 0.2f comes from Code\Sandbox\Editor\Objects\DisplayContextShared.inl DisplayContext::DrawWireDisk + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) + { + if (m_auxGeomPtr) + { + // get the max scaled radius in case the transform on the stack is scaled non-uniformly + const float transformedRadiusX = ToWorldSpaceVector(AZ::Vector3(radius, 0.0f, 0.0f)).GetLengthEstimate(); + const float transformedRadiusY = ToWorldSpaceVector(AZ::Vector3(0.0f, radius, 0.0f)).GetLengthEstimate(); + const float transformedRadiusZ = ToWorldSpaceVector(AZ::Vector3(0.0f, 0.0f, radius)).GetLengthEstimate(); + const float maxTransformedRadius = + AZ::GetMax(transformedRadiusX, AZ::GetMax(transformedRadiusY, transformedRadiusZ)); + + AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; + m_auxGeomPtr->DrawSphere( + ToWorldSpacePosition(pos), + maxTransformedRadius, + m_rendState.m_color, + drawStyle, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex ); - lines.Draw(m_auxGeomPtr, m_rendState); - } } - - void AtomDebugDisplayViewportInterface::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis) + } + + void AtomDebugDisplayViewportInterface::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw circle with default radius. - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateAxisAlignedArc( - lines, - step, - 0.0f, - maxAngle, - pos, - radiusV3, - static_cast(nUnchangedAxis)); - lines.Draw(m_auxGeomPtr, m_rendState); - } + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); + m_auxGeomPtr->DrawDisk( + worldPos, + worldDir, + radius, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis) + void AtomDebugDisplayViewportInterface::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale, bool dualEndedArrow) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) + float f2dScale = 1.0f; + float arrowLen = 0.4f * headScale; + float arrowRadius = 0.1f * headScale; + // if (flags & DISPLAY_2D) + // { + // f2dScale = 1.2f * ToWorldSpaceVector(Vec3(1, 0, 0)).GetLength(); + // } + AZ::Vector3 dir = trg - src; + dir = ToWorldSpaceVector(dir.GetNormalized()); + AZ::Vector3 verts[2] = {ToWorldSpacePosition(src), ToWorldSpacePosition(trg)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + if (!dualEndedArrow) { - // Draw circle with single radius. - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. - - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldView = ToWorldSpacePosition(viewPos); - const AZ::Vector3 worldDir = worldView - worldPos; - - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, radiusV3, static_cast(nUnchangedAxis%CircleAxisMax), - [&worldPos, &worldDir](const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex) - { - AZ_UNUSED(lineEnd); - const float dot = (lineStart - worldPos).Dot(worldDir); - const bool facing = dot > 0.0f; - // if so skip every other line to produce a dotted effect - if (facing || segmentIndex % 2 == 0) - { - return true; - } - return false; - }); - lines.Draw(m_auxGeomPtr, m_rendState); - } - } - - void AtomDebugDisplayViewportInterface::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) - { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); + verts[1] -= dir * arrowLen; + m_auxGeomPtr->DrawLines(drawArgs); m_auxGeomPtr->DrawCone( - worldPos, - worldDir, - radius, - height, - m_rendState.m_color, - drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) - { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); - const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); - m_auxGeomPtr->DrawCylinder( - worldCenter, - worldAxis, - radius, - height, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - } - - void AtomDebugDisplayViewportInterface::DrawSolidCylinder( - const AZ::Vector3& center, - const AZ::Vector3& axis, - float radius, - float height, - bool drawShaded) - { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); - const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); - m_auxGeomPtr->DrawCylinder( - worldCenter, - worldAxis, - radius, - height, - m_rendState.m_color, - drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireCapsule( - const AZ::Vector3& center, - const AZ::Vector3& axis, - float radius, - float heightStraightSection) - { - if (m_auxGeomPtr && radius > FLT_EPSILON && axis.GetLengthSq() > FLT_EPSILON) - { - AZ::Vector3 axisNormalized = axis.GetNormalizedEstimate(); - SingleColorStaticSizeLineHelper<(16+1) * 5> lines; // 360/22.5 = 16, 5 possible calls to CreateArbitraryAxisArc - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - float stepAngle = DegToRad(22.5f); - float Deg0 = DegToRad(0.0f); - - - // Draw cylinder part (or just a circle around the middle) - if (heightStraightSection > FLT_EPSILON) - { - DrawWireCylinder(center, axis, radius, heightStraightSection); - } - else - { - float Deg360 = DegToRad(360.0f); - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg0, - Deg360, - center, - radiusV3, - axisNormalized - ); - } - - float Deg90 = DegToRad(90.0f); - float Deg180 = DegToRad(180.0f); - - AZ::Vector3 ortho1Normalized, ortho2Normalized; - CalcBasisVectors(axisNormalized, ortho1Normalized, ortho2Normalized); - AZ::Vector3 centerToTopCircleCenter = axisNormalized * heightStraightSection * 0.5f; - AZ::Vector3 topCenter = center + centerToTopCircleCenter; - AZ::Vector3 bottomCenter = center - centerToTopCircleCenter; - - // Draw top cap as two criss-crossing 180deg arcs - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg90, - Deg90 + Deg180, - topCenter, - radiusV3, - ortho1Normalized - ); - - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg180, - Deg180 + Deg180, - topCenter, - radiusV3, - ortho2Normalized - ); - - // Draw bottom cap - CreateArbitraryAxisArc( - lines, - stepAngle, - -Deg90, - -Deg90 + Deg180, - bottomCenter, - radiusV3, - ortho1Normalized - ); - - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg0, - Deg0 + Deg180, - bottomCenter, - radiusV3, - ortho2Normalized - ); - - lines.Draw(m_auxGeomPtr, m_rendState); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, float radius) - { - if (m_auxGeomPtr) - { - - m_auxGeomPtr->DrawSphere( - ToWorldSpacePosition(pos), - radius, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) - { - if (m_auxGeomPtr) - { - // This matches Cry behavior, the DrawWireSphere above may need modifying to use the same approach. - // Draw 3 axis aligned circles - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40*3> lines; // hard code to 40 lines * 3 circles until DegToRad is constexpr. - - // Z Axis - AZ::Vector3 axisRadius(radius.GetX(), radius.GetY(), 0.0f); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisZ); - - // X Axis - axisRadius = AZ::Vector3(0.0f, radius.GetY(), radius.GetZ()); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisX); - - // Y Axis - axisRadius = AZ::Vector3(radius.GetX(), 0.0f, radius.GetZ()); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisY); - lines.Draw(m_auxGeomPtr, m_rendState); - } - } - - void AtomDebugDisplayViewportInterface::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) - { - if (m_auxGeomPtr) - { - - // Draw 3 axis aligned circles - const float stepAngle = DegToRad(11.25f); - const float startAngle = DegToRad(0.0f); - const float stopAngle = DegToRad(360.0f) + startAngle; - SingleColorDynamicSizeLineHelper lines(2+static_cast(360.0f/11.25f)); // num disk segments + 1 for azis line + 1 for spare - const AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateArbitraryAxisArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, - radiusV3, - dir - ); - - lines.AddLineSegment(ToWorldSpacePosition(pos), ToWorldSpacePosition(pos + dir * (radius * 0.2f))); // 0.2f comes from Code\Sandbox\Editor\Objects\DisplayContextShared.inl DisplayContext::DrawWireDisk - lines.Draw(m_auxGeomPtr, m_rendState); - } - } - - void AtomDebugDisplayViewportInterface::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) - { - if (m_auxGeomPtr) - { - // get the max scaled radius in case the transform on the stack is scaled non-uniformly - const float transformedRadiusX = ToWorldSpaceVector(AZ::Vector3(radius, 0.0f, 0.0f)).GetLengthEstimate(); - const float transformedRadiusY = ToWorldSpaceVector(AZ::Vector3(0.0f, radius, 0.0f)).GetLengthEstimate(); - const float transformedRadiusZ = ToWorldSpaceVector(AZ::Vector3(0.0f, 0.0f, radius)).GetLengthEstimate(); - const float maxTransformedRadius = - AZ::GetMax(transformedRadiusX, AZ::GetMax(transformedRadiusY, transformedRadiusZ)); - - AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; - m_auxGeomPtr->DrawSphere( - ToWorldSpacePosition(pos), - maxTransformedRadius, - m_rendState.m_color, - drawStyle, + verts[1], + dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, m_rendState.m_depthTest, m_rendState.m_depthWrite, m_rendState.m_faceCullMode, m_rendState.m_viewProjOverrideIndex ); } - } - - void AtomDebugDisplayViewportInterface::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) - { - if (m_auxGeomPtr) + else { - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); - m_auxGeomPtr->DrawDisk( - worldPos, - worldDir, - radius, + verts[0] += dir * arrowLen; + verts[1] -= dir * arrowLen; + m_auxGeomPtr->DrawLines(drawArgs); + m_auxGeomPtr->DrawCone( + verts[0], + -dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + m_auxGeomPtr->DrawCone( + verts[1], + dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, m_rendState.m_color, AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, m_rendState.m_depthTest, @@ -829,179 +1224,297 @@ namespace AZ ); } } + } - void AtomDebugDisplayViewportInterface::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale, bool dualEndedArrow) + void AtomDebugDisplayViewportInterface::DrawTextLabel( + const AZ::Vector3& pos, + float size, + const char* text, + const bool center, + int srcOffsetX [[maybe_unused]], + int srcOffsetY [[maybe_unused]]) + { + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + if (!fontDrawInterface || !text || size == 0.0f) { - if (m_auxGeomPtr) + return; + } + // if 2d draw need to project pos to screen first + AzFramework::TextDrawParameters params; + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works + params.m_position = pos; + params.m_color = m_rendState.m_color; + params.m_scale = AZ::Vector2(size); + params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment + params.m_monospace = false; //! disable character proportional spacing + params.m_depthTest = false; //! Test character against the depth buffer + params.m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + params.m_multiline = true; //! text respects ascii newline characters + + fontDrawInterface->DrawScreenAlignedText3d(params, text); + } + + void AtomDebugDisplayViewportInterface::Draw2dTextLabel( + float x, + float y, + float size, + const char* text, + bool center) + { + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + if (!fontDrawInterface || !text || size == 0.0f) + { + return; + } + // if 2d draw need to project pos to screen first + AzFramework::TextDrawParameters params; + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works + params.m_position = AZ::Vector3(x, y, 1.0f); + params.m_color = m_rendState.m_color; + params.m_scale = AZ::Vector2(size); + params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment + params.m_monospace = false; //! disable character proportional spacing + params.m_depthTest = false; //! Test character against the depth buffer + params.m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + params.m_multiline = true; //! text respects ascii newline characters + + fontDrawInterface->DrawScreenAlignedText2d(params, text); + } + + void AtomDebugDisplayViewportInterface::DrawTextOn2DBox( + const AZ::Vector3& pos [[maybe_unused]], + const char* text [[maybe_unused]], + float textScale [[maybe_unused]], + const AZ::Vector4& TextColor [[maybe_unused]], + const AZ::Vector4& TextBackColor [[maybe_unused]]) + { + AZ_Assert(false, "Unexpected use of legacy api, please file a feature request with the rendering team to get this implemented!"); + } + // unhandledled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; + // void AtomDebugDisplayViewportInterface::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; + + void AtomDebugDisplayViewportInterface::SetLineWidth(float width) + { + AZ_Assert(width >= 0.0f && width <= 255.0f, "Width (%f) exceeds allowable range [0 - 255]", width); + m_rendState.m_lineWidth = static_cast(width); + } + + bool AtomDebugDisplayViewportInterface::IsVisible(const AZ::Aabb& bounds) + { + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + const AZ::Matrix4x4& worldToClip = viewportContext->GetDefaultView()->GetWorldToClipMatrix(); + AZ::Frustum frustum = AZ::Frustum::CreateFromMatrixColumnMajor(worldToClip, Frustum::ReverseDepth::True); + return frustum.IntersectAabb(bounds) != AZ::IntersectResult::Exterior; + } + // int AtomDebugDisplayViewportInterface::SetFillMode(int nFillMode) override; + float AtomDebugDisplayViewportInterface::GetLineWidth() + { + return m_rendState.m_lineWidth; + } + + float AtomDebugDisplayViewportInterface::GetAspectRatio() + { + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + auto windowSize = viewportContext->GetViewportSize(); + return aznumeric_cast(windowSize.m_width)/aznumeric_cast(windowSize.m_height); + } + + void AtomDebugDisplayViewportInterface::DepthTestOff() + { + m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::Off; + } + + void AtomDebugDisplayViewportInterface::DepthTestOn() + { + m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::On; + } + + void AtomDebugDisplayViewportInterface::DepthWriteOff() + { + m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::Off; + } + + void AtomDebugDisplayViewportInterface::DepthWriteOn() + { + m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; + } + + void AtomDebugDisplayViewportInterface::CullOff() + { + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::None; + } + + void AtomDebugDisplayViewportInterface::CullOn() + { + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; + } + + bool AtomDebugDisplayViewportInterface::SetDrawInFrontMode(bool on) + { + AZ_UNUSED(on); + return false; + } + + AZ::u32 AtomDebugDisplayViewportInterface::GetState() + { + return ConvertRenderStateToCry(); + } + + AZ::u32 AtomDebugDisplayViewportInterface::SetState(AZ::u32 state) + { + uint32_t currentState = ConvertRenderStateToCry(); + uint32_t changedState = (state & e_PublicParamsMask) ^ currentState; + + if (changedState & e_Mode2D3DMask) + { + // this is the only way to turn on 2d Mode under Atom + if (state & e_Mode2D) { - float f2dScale = 1.0f; - float arrowLen = 0.4f * headScale; - float arrowRadius = 0.1f * headScale; - // if (flags & DISPLAY_2D) - // { - // f2dScale = 1.2f * ToWorldSpaceVector(Vec3(1, 0, 0)).GetLength(); - // } - AZ::Vector3 dir = trg - src; - dir = ToWorldSpaceVector(dir.GetNormalized()); - AZ::Vector3 verts[2] = {ToWorldSpacePosition(src), ToWorldSpacePosition(trg)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - if (!dualEndedArrow) - { - verts[1] -= dir * arrowLen; - m_auxGeomPtr->DrawLines(drawArgs); - m_auxGeomPtr->DrawCone( - verts[1], - dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - else - { - verts[0] += dir * arrowLen; - verts[1] -= dir * arrowLen; - m_auxGeomPtr->DrawLines(drawArgs); - m_auxGeomPtr->DrawCone( - verts[0], - -dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - m_auxGeomPtr->DrawCone( - verts[1], - dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + AZ_Assert((currentState & e_DrawInFrontOn) == 0 && (changedState & e_DrawInFrontOn) == 0, "Atom doesnt support Draw In Front and 2d at the same time"); + m_rendState.m_viewProjOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_rendState.m_2dMode = true; + } + else // switch back to mode 3d + { + m_rendState.m_viewProjOverrideIndex = -1; + m_rendState.m_2dMode = false; } } - // void AtomDebugDisplayViewportInterface::DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; - // void AtomDebugDisplayViewportInterface::Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; - // void AtomDebugDisplayViewportInterface::DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; - // unhandledled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; - // void AtomDebugDisplayViewportInterface::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; - - void AtomDebugDisplayViewportInterface::SetLineWidth(float width) + if (changedState & e_AlphaBlendingMask) { - AZ_Assert(width >= 0.0f && width <= 255.0f, "Width (%f) exceeds allowable range [0 - 255]", width); - m_rendState.m_lineWidth = static_cast(width); - } - - // bool AtomDebugDisplayViewportInterface::IsVisible(const AZ::Aabb& bounds) override; - // int AtomDebugDisplayViewportInterface::SetFillMode(int nFillMode) override; - float AtomDebugDisplayViewportInterface::GetLineWidth() - { - return m_rendState.m_lineWidth; - } - - float AtomDebugDisplayViewportInterface::GetAspectRatio() - { - auto viewContextManager = AZ::Interface::Get(); - AZ::RPI::ViewportContextPtr viewportContext; - if (m_defaultInstance) + switch (state&e_AlphaBlendingMask) { - viewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); + case e_AlphaNone: + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; + break; + case e_AlphaAdditive: + [[fallthrough]]; // Additive not currently supported in Atom AuxGeom implementation + case e_AlphaBlended: + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; + break; + } + } + + if (changedState & e_DrawInFrontMask) + { + AZ_Assert( // either state is turning DrawInFront off or Mode 2D has to be off + (state & e_DrawInFrontOn) == 0 || + ((currentState & e_Mode2D) == 0 && (changedState & e_Mode2D) == 0), + "Atom doesnt support Draw In Front and 2d at the same time"); + SetDrawInFrontMode(changedState & e_DrawInFrontOn); + } + + if (changedState & e_CullModeMask) + { + switch (state & e_CullModeMask) + { + case e_CullModeNone: + CullOff(); + break; + case e_CullModeFront: + // Currently no other way to set front face culling in DebugDisplayRequestBus + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Front; + break; + case e_CullModeBack: + CullOn(); + break; + } + } + + if (changedState & e_DepthWriteMask) + { + if (state & e_DepthWriteOff) + { + DepthWriteOff(); } else { - viewportContext = viewContextManager->GetViewportContextById(m_viewportId); + DepthWriteOn(); } - auto windowSize = viewportContext->GetViewportSize(); - return aznumeric_cast(windowSize.m_width)/aznumeric_cast(windowSize.m_height); } - void AtomDebugDisplayViewportInterface::DepthTestOff() + if (changedState & e_DepthTestMask) { - m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::Off; - } - - void AtomDebugDisplayViewportInterface::DepthTestOn() - { - m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::On; - } - - void AtomDebugDisplayViewportInterface::DepthWriteOff() - { - m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::Off; - } - - void AtomDebugDisplayViewportInterface::DepthWriteOn() - { - m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; - } - - void AtomDebugDisplayViewportInterface::CullOff() - { - m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::None; - } - - void AtomDebugDisplayViewportInterface::CullOn() - { - m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; - } - - bool AtomDebugDisplayViewportInterface::SetDrawInFrontMode(bool on) - { - AZ_UNUSED(on); - return false; - } - - // AZ::u32 AtomDebugDisplayViewportInterface::GetState() override; - // AZ::u32 AtomDebugDisplayViewportInterface::SetState(AZ::u32 state) override; - // AZ::u32 AtomDebugDisplayViewportInterface::SetStateFlag(AZ::u32 state) override; - // AZ::u32 AtomDebugDisplayViewportInterface::ClearStateFlag(AZ::u32 state) override; - - void AtomDebugDisplayViewportInterface::PushMatrix(const AZ::Transform& tm) - { - AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size"); - if (m_rendState.m_currentTransform < RenderState::TransformStackSize) + if (state & e_DepthTestOff) { - m_rendState.m_currentTransform++; - m_rendState.m_transformStack[m_rendState.m_currentTransform] = m_rendState.m_transformStack[m_rendState.m_currentTransform - 1] * AZ::Matrix3x4::CreateFromTransform(tm); + DepthTestOff(); } - } - - void AtomDebugDisplayViewportInterface::PopMatrix() - { - AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack"); - if (m_rendState.m_currentTransform > 0) + else { - m_rendState.m_currentTransform--; + DepthTestOn(); } } - const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const + return currentState; + } + + void AtomDebugDisplayViewportInterface::PushMatrix(const AZ::Transform& tm) + { + AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size"); + if (m_rendState.m_currentTransform < RenderState::TransformStackSize) { - return m_rendState.m_transformStack[m_rendState.m_currentTransform]; + m_rendState.m_currentTransform++; + m_rendState.m_transformStack[m_rendState.m_currentTransform] = m_rendState.m_transformStack[m_rendState.m_currentTransform - 1] * AZ::Matrix3x4::CreateFromTransform(tm); } } + + void AtomDebugDisplayViewportInterface::PopMatrix() + { + AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack"); + if (m_rendState.m_currentTransform > 0) + { + m_rendState.m_currentTransform--; + } + } + + const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const + { + return m_rendState.m_transformStack[m_rendState.m_currentTransform]; + } + + AZ::RPI::ViewportContextPtr AtomDebugDisplayViewportInterface::GetViewportContext() const + { + auto viewContextManager = AZ::Interface::Get(); + if (m_defaultInstance) + { + return viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); + } + else + { + return viewContextManager->GetViewportContextById(m_viewportId); + } + } + + uint32_t AtomDebugDisplayViewportInterface::ConvertRenderStateToCry() const + { + uint32_t result = 0; + + result |= m_rendState.m_2dMode ? e_Mode2D : e_Mode3D; + result |= m_rendState.m_opacityType == AZ::RPI::AuxGeomDraw::OpacityType::Opaque ? e_AlphaNone : e_AlphaBlended; + result |= m_rendState.m_drawInFront ? e_DrawInFrontOn : e_DrawInFrontOff; + result |= m_rendState.m_depthTest == AZ::RPI::AuxGeomDraw::DepthTest::On ? e_DepthTestOn : e_DepthTestOff; + result |= m_rendState.m_depthWrite == AZ::RPI::AuxGeomDraw::DepthWrite::On ? e_DepthWriteOn : e_DepthWriteOff; + switch (m_rendState.m_faceCullMode) + { + case AZ::RPI::AuxGeomDraw::FaceCullMode::None: + result |= e_CullModeNone; + break; + case AZ::RPI::AuxGeomDraw::FaceCullMode::Front: + result |= e_CullModeFront; + break; + case AZ::RPI::AuxGeomDraw::FaceCullMode::Back: + result |= e_CullModeBack; + break; + default: + AZ_Assert(false, "Trying to convert an unknown culling mode to cry!"); + break; + } + + return result; + } } diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h index 48091ea8d8..021d816ca4 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h @@ -42,6 +42,10 @@ namespace AZ::AtomBridge AZ::RPI::AuxGeomDraw::DepthWrite m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; AZ::RPI::AuxGeomDraw::FaceCullMode m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; int32_t m_viewProjOverrideIndex = -1; // will be used to implement SetDrawInFrontMode & 2D mode + + // separate tracking for Cry only state + bool m_drawInFront = false; + bool m_2dMode = false; }; //! Utility class to collect line segments when the number of segments is known at compile time. @@ -77,6 +81,24 @@ namespace AZ::AtomBridge } } + void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const + { + if (auxGeomDrawPtr && !m_points.empty()) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride(); + auxGeomDrawPtr->DrawLines( drawArgs ); + } + } + void Reset() { m_points.clear(); @@ -91,6 +113,7 @@ namespace AZ::AtomBridge SingleColorDynamicSizeLineHelper(int estimatedNumLineSegments); void AddLineSegment(const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd); void Draw(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const; + void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const; void Reset(); AZStd::vector m_points; @@ -119,9 +142,9 @@ namespace AZ::AtomBridge void SetColor(const AZ::Vector4& color) override; void SetAlpha(float a) override; void DrawQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawQuad(float width, float height) overr - // void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawWireQuad(float width, float height) override; + void DrawQuad(float width, float height) override; + void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; + void DrawWireQuad(float width, float height) override; void DrawQuadGradient(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; void DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) override; void DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) override; @@ -134,10 +157,10 @@ namespace AZ::AtomBridge void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) override; void DrawLines(const AZStd::vector& lines, const AZ::Color& color) override; void DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled = true) override; - // void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; - // void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; + void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; + void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; + void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; + void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2) override; void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) override; void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) override; @@ -152,13 +175,13 @@ namespace AZ::AtomBridge void DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) override; void DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) override; void DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale = 1.0f, bool dualEndedArrow = false) override; - // void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; - // void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; - // void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; + void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; + void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; + void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; // unhandled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; // void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; void SetLineWidth(float width) override; - // bool IsVisible(const AZ::Aabb& bounds) override; + bool IsVisible(const AZ::Aabb& bounds) override; // int SetFillMode(int nFillMode) override; float GetLineWidth() override; float GetAspectRatio() override; @@ -169,10 +192,8 @@ namespace AZ::AtomBridge void CullOff() override; void CullOn() override; bool SetDrawInFrontMode(bool on) override; - // AZ::u32 GetState() override; - // AZ::u32 SetState(AZ::u32 state) override; - // AZ::u32 SetStateFlag(AZ::u32 state) override; - // AZ::u32 ClearStateFlag(AZ::u32 state) override; + AZ::u32 GetState() override; + AZ::u32 SetState(AZ::u32 state) override; void PushMatrix(const AZ::Transform& tm) override; void PopMatrix() override; @@ -226,6 +247,10 @@ namespace AZ::AtomBridge void InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr); + AZ::RPI::ViewportContextPtr GetViewportContext() const; + + uint32_t ConvertRenderStateToCry() const; + RenderState m_rendState; AZ::RPI::AuxGeomDrawPtr m_auxGeomPtr; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index b1feaf1d87..2969e35a51 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -20,8 +20,14 @@ #include #include #include +#include #include +#include +#include + +#include + namespace AZ { class FFont; @@ -33,6 +39,8 @@ namespace AZ //! and manages their loading & saving together. class AtomFont : public ICryFont + , public AzFramework::FontQueryInterface + , public AzFramework::SceneSystemNotificationBus::Handler { friend class FFont; @@ -79,16 +87,31 @@ namespace AZ void ReloadAllFonts() override; ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // FontQueryInterface implementation + AzFramework::FontDrawInterface* GetFontDrawInterface(AzFramework::FontId fontId) const override; + AzFramework::FontDrawInterface* GetDefaultFontDrawInterface() const override; + + // SceneSystemNotificationBus handlers + void SceneAboutToBeRemoved(AzFramework::Scene& scene) override; + + + // Atom DynamicDraw interface management + AZ::RHI::Ptr GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene); + + public: void UnregisterFont(const char* fontName); private: - typedef std::map FontMap; - typedef FontMap::iterator FontMapItor; - typedef FontMap::const_iterator FontMapConstItor; + using FontMap = std::unordered_map; + using FontMapItor = FontMap::iterator; + using FontMapConstItor = FontMap::const_iterator; - typedef AZStd::map> FontFamilyMap; - typedef AZStd::map FontFamilyReverseLookupMap; + using FontFamilyMap = AZStd::unordered_map>; + using FontFamilyReverseLookupMap = AZStd::unordered_map; + + using SceneToDynamicDrawMap = AZStd::unordered_map>; private: //! Convenience method for loading fonts @@ -119,9 +142,13 @@ namespace AZ FontFamilyReverseLookupMap m_fontFamilyReverseLookup; // m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled) + SceneToDynamicDrawMap m_sceneToDynamicDrawMap; + AZStd::shared_mutex m_sceneToDynamicDrawMutex; }; } #endif diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 4f87334b46..96f5e09fc3 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,8 @@ namespace AZ void operator () (const AZStd::intrusive_refcount* ptr) const; }; + using TextDrawContext = STextDrawContext; + //! FFont is the implementation of IFFont used to draw text with a particular font (e.g. Consolas Italic) //! FFont manages creation of a gpu texture to cache the font and generates draw commands that use that texture. //! FFont's are managed by AtomFont as either individual font instances or a font family @@ -64,12 +67,12 @@ namespace AZ class FFont : public IFFont , public AZStd::intrusive_refcount + , public AzFramework::FontDrawInterface , private AZ::Render::Bootstrap::NotificationBus::Handler { using ref_count = AZStd::intrusive_refcount; friend FontDeleter; public: - using TextDrawContext = STextDrawContext; //! Determines how characters of different sizes should be handled during render. enum class SizeBehavior { @@ -201,6 +204,14 @@ namespace AZ uint32_t GetFontTextureVersion() override; ///////////////////////////////////////////////////////////////////////////////////////////////////// + // AzFramework::FontDrawInterface implementation + void DrawScreenAlignedText2d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) override; + + void DrawScreenAlignedText3d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) override; public: FFont(AtomFont* atomFont, const char* fontName); @@ -220,8 +231,18 @@ namespace AZ bool InitCache(); void Prepare(const char* str, bool updateTexture, const AtomFont::GlyphSize& glyphSize = AtomFont::defaultGlyphSize); - void DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); - Vec2 GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); + void DrawStringUInternal( + const RHI::Viewport& viewport, + RPI::ViewportContext* viewportContext, + float x, + float y, + float z, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx); + Vec2 GetTextSizeUInternal(const RHI::Viewport& viewport, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); + Vec2 GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const; + float GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const; // returns true if add operation was successful, false otherwise using AddFunction = AZStd::function; @@ -229,6 +250,7 @@ namespace AZ //! This function is used by both DrawStringUInternal and WriteTextQuadsToBuffers //! To do this is takes a function pointer that implement the appropriate AddQuad behavior int CreateQuadsForText( + const RHI::Viewport& viewport, float x, float y, float z, @@ -247,16 +269,16 @@ namespace AZ float rcpCellWidth; }; - TextScaleInfoInternal CalculateScaleInternal(const TextDrawContext& ctx) const; + TextScaleInfoInternal CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const; Vec2 GetRestoredFontSize(const TextDrawContext& ctx) const; bool UpdateTexture(); - void ScaleCoord(float& x, float& y) const; + void ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const; - void InitWindowContext(); - void InitViewportContext(); + void InitDefaultWindowContext(); + void InitDefaultViewportContext(); void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override; @@ -272,8 +294,8 @@ namespace AZ size_t m_fontBufferSize = 0; unsigned char* m_fontBuffer = nullptr; - AZStd::shared_ptr m_windowContext; - AZStd::shared_ptr m_viewportContext; + AZStd::shared_ptr m_defaultWindowContext; + AZStd::shared_ptr m_defaultViewportContext; AZ::Data::Instance m_fontStreamingImage; AZ::RHI::Ptr m_fontImage; @@ -296,8 +318,6 @@ namespace AZ FontShaderData m_fontShaderData; - AZ::RHI::Ptr m_dynamicDraw; - bool m_monospacedFont = false; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType) float m_sizeRatio = IFFontConstants::defaultSizeRatio; @@ -325,25 +345,25 @@ namespace AZ } } -inline void AZ::FFont::InitWindowContext() +inline void AZ::FFont::InitDefaultWindowContext() { - if (!m_windowContext) + if (!m_defaultWindowContext) { // font is created before window & viewport in the editor so need to do late init // TODO need to deal with multiple windows, such as the editor - AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext); - AZ_Assert(m_windowContext, "Unable to get the main window context"); + AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_defaultWindowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext); + AZ_Assert(m_defaultWindowContext, "Unable to get the main window context"); } } -inline void AZ::FFont::InitViewportContext() +inline void AZ::FFont::InitDefaultViewportContext() { - if (!m_viewportContext) + if (!m_defaultViewportContext) { // font is created before window & viewport in the editor so need to do late init auto viewContextManager = AZ::Interface::Get(); - m_viewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); - AZ_Assert(m_viewportContext, "Unable to get the viewport context"); + m_defaultViewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); + AZ_Assert(m_defaultViewportContext, "Unable to get the viewport context"); } } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp index 0a081d01f1..636583fe98 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp @@ -28,8 +28,12 @@ #include #include +#include +#include #include +#include +#include // Static member definitions const AZ::AtomFont::GlyphSize AZ::AtomFont::defaultGlyphSize = AZ::AtomFont::GlyphSize(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY); @@ -348,10 +352,14 @@ AZ::AtomFont::AtomFont(ISystem* system) REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL, "Reload all fonts"); #endif + AZ::Interface::Register(this); } AZ::AtomFont::~AtomFont() { + AZ::Interface::Unregister(this); + m_defaultFontDrawInterface = nullptr; + // Persist fonts for application lifetime to prevent unnecessary work m_persistedFontFamilies.clear(); @@ -372,24 +380,41 @@ IFFont* AZ::AtomFont::NewFont(const char* fontName) { string name = fontName; name.MakeLower(); + AzFramework::FontId fontId = GetFontId(name.c_str()); - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str())); + FontMapItor it = m_fonts.find(fontId); if (it != m_fonts.end()) { return it->second; } FFont* font = new FFont(this, name.c_str()); - m_fonts.insert(FontMapItor::value_type(name, font)); + m_fonts.insert(FontMapItor::value_type(fontId, font)); + if(!m_defaultFontDrawInterface) + { + m_defaultFontDrawInterface = static_cast(font); + } return font; } IFFont* AZ::AtomFont::GetFont(const char* fontName) const { - FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(fontName).MakeLower())); + AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str()); + FontMapConstItor it = m_fonts.find(fontId); return it != m_fonts.end() ? it->second : 0; } +AzFramework::FontDrawInterface* AZ::AtomFont::GetFontDrawInterface(AzFramework::FontId fontId) const +{ + FontMapConstItor it = m_fonts.find(fontId); + return (it != m_fonts.end()) ? it->second : nullptr; +} + +AzFramework::FontDrawInterface* AZ::AtomFont::GetDefaultFontDrawInterface() const +{ + return m_defaultFontDrawInterface; +} + FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName) { FontFamilyPtr fontFamily(nullptr); @@ -648,7 +673,8 @@ void AZ::AtomFont::ReloadAllFonts() void AZ::AtomFont::UnregisterFont(const char* fontName) { - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(fontName)); + AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str()); + FontMapItor it = m_fonts.find(fontId); #if defined(AZ_ENABLE_TRACING) IFFont* fontPtr = it->second; @@ -823,5 +849,49 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o return root; } +void AZ::AtomFont::SceneAboutToBeRemoved(AzFramework::Scene& scene) +{ + AZ::RPI::Scene* rpiScene = scene.GetSubsystem(); + + AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); + if ( auto it = m_sceneToDynamicDrawMap.find(rpiScene); it != m_sceneToDynamicDrawMap.end()) + { + m_sceneToDynamicDrawMap.erase(it); + } +} + +AZ::RHI::Ptr AZ::AtomFont::GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene) +{ + static const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; + + { + // shared lock while reading + AZStd::shared_lock lock(m_sceneToDynamicDrawMutex); + + if (auto it = m_sceneToDynamicDrawMap.find(scene); it != m_sceneToDynamicDrawMap.end()) + { + return it->second; + } + } + + // Create and initialize DynamicDrawContext for font draw + AZ::RHI::Ptr dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene); + + Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); + AZ::RPI::ShaderOptionList shaderOptions; + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false"))); + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); + dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); + dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); + dynamicDraw->EndInit(); + + // exclusive lock while writing + AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); + m_sceneToDynamicDrawMap.insert(AZStd::make_pair(scene, dynamicDraw)); + + return dynamicDraw; +} + + #endif diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index bb4eb23d8f..d32302a07b 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -23,6 +23,9 @@ #include #include +#include +#include + #include #include @@ -42,6 +45,8 @@ #include #include #include +#include +#include #include #include @@ -49,6 +54,7 @@ #include +static const AZ::Vector2 UiDraw_TextSizeFactor = AZ::Vector2(12.0f, 12.0f); static const int TabCharCount = 4; // set buffer sizes to hold max characters that can be drawn in 1 DrawString call static const size_t MaxVerts = 8 * 1024; // 2048 quads @@ -78,6 +84,7 @@ AZ::FFont::FFont(AtomFont* atomFont, const char* fontName) AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); } + bool AZ::FFont::InitFont() { if (m_fontInitialized) @@ -85,24 +92,14 @@ bool AZ::FFont::InitFont() return true; } - InitWindowContext(); - InitViewportContext(); - - const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; + InitDefaultWindowContext(); + InitDefaultViewportContext(); // Create and initialize DynamicDrawContext for font draw - m_dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(m_viewportContext->GetRenderScene().get()); - - Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); - AZ::RPI::ShaderOptionList shaderOptions; - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false"))); - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); - m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); - m_dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); - m_dynamicDraw->EndInit(); + AZ::RPI::Ptr dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(m_defaultViewportContext->GetRenderScene().get()); // Save draw srg input indices for later use - Data::Instance drawSrg = m_dynamicDraw->NewDrawSrg(); + Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); const RHI::ShaderResourceGroupLayout* layout = drawSrg->GetAsset()->GetLayout(); m_fontShaderData.m_imageInputIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::TextureIndexName)); @@ -257,27 +254,39 @@ void AZ::FFont::Free() void AZ::FFont::DrawString(float x, float y, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) { - if (!str || !m_vertexBuffer) + if (!str) { return; } - DrawStringUInternal(x, y, 1.0f, str, asciiMultiLine, ctx); + DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, 1.0f, str, asciiMultiLine, ctx); } void AZ::FFont::DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) { - if (!str || !m_vertexBuffer) + if (!str) { return; } - DrawStringUInternal(x, y, z, str, asciiMultiLine, ctx); + DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, z, str, asciiMultiLine, ctx); } -void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) +void AZ::FFont::DrawStringUInternal( + const RHI::Viewport& viewport, + RPI::ViewportContext* viewportContext, + float x, + float y, + float z, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx) { - if (!str || !m_fontTexture || ctx.m_fxIdx >= m_effects.size() || m_effects[ctx.m_fxIdx].m_passes.empty()) + if (!str + || !m_vertexBuffer // vertex buffer isn't created until BootstrapScene is ready, Editor tries to render text before that. + || !m_fontTexture + || ctx.m_fxIdx >= m_effects.size() + || m_effects[ctx.m_fxIdx].m_passes.empty()) { return; } @@ -296,7 +305,6 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, const bool orthoMode = ctx.m_overrideViewProjMatrices; - const RHI::Viewport& viewport = m_windowContext->GetViewport(); const float viewX = viewport.m_minX; const float viewY = viewport.m_minY; const float viewWidth = viewport.m_maxX - viewport.m_minX; @@ -307,7 +315,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, Matrix4x4 modelViewProjMat; if (!orthoMode) { - AZ::RPI::ViewPtr view = m_viewportContext->GetDefaultView(); + AZ::RPI::ViewPtr view = viewportContext->GetDefaultView(); modelViewProjMat = view->GetWorldToClipMatrix(); } else @@ -322,7 +330,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, size_t startingVertexCount = m_vertexCount; // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [this, startingVertexCount] + AZ::FFont::AddFunction AddQuad = [this, startingVertexCount] (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32_t packedColor) { const bool vertexSpaceLeft = m_vertexCount + 4 < MaxVerts; @@ -367,18 +375,19 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, int numQuads = 0; { AZStd::lock_guard lock(m_vertexDataMutex); - numQuads = CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad); + numQuads = CreateQuadsForText(viewport, x, y, z, str, asciiMultiLine, ctx, AddQuad); } if (numQuads) { + auto dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(viewportContext->GetRenderScene().get()); //setup per draw srg - auto drawSrg = m_dynamicDraw->NewDrawSrg(); + auto drawSrg = dynamicDraw->NewDrawSrg(); drawSrg->SetConstant(m_fontShaderData.m_viewProjInputIndex, modelViewProjMat); drawSrg->SetImageView(m_fontShaderData.m_imageInputIndex, m_fontStreamingImage->GetImageView()); drawSrg->Compile(); - m_dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg); + dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg); m_indexCount = 0; m_vertexCount = 0; } @@ -391,10 +400,14 @@ Vec2 AZ::FFont::GetTextSize(const char* str, const bool asciiMultiLine, const Te return Vec2(0.0f, 0.0f); } - return GetTextSizeUInternal(str, asciiMultiLine, ctx); + return GetTextSizeUInternal(m_defaultWindowContext->GetViewport(), str, asciiMultiLine, ctx); } -Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) +Vec2 AZ::FFont::GetTextSizeUInternal( + const RHI::Viewport& viewport, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx) { const size_t fxSize = m_effects.size(); @@ -411,12 +424,12 @@ Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine, Vec2 size = ctx.m_size; if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } // This scaling takes into account the logical size of the font relative // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); float maxW = 0; float maxH = 0; @@ -733,7 +746,7 @@ uint32_t AZ::FFont::WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16_t return true; }; - CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad); + CreateQuadsForText(m_defaultWindowContext->GetViewport(), x, y, z, str, asciiMultiLine, ctx, AddQuad); return numQuadsWritten; } @@ -743,7 +756,7 @@ uint32_t AZ::FFont::GetFontTextureVersion() return m_fontImageVersion; } -int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx, +int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx, AddFunction AddQuad) { int numQuads = 0; @@ -768,17 +781,17 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co Vec2 size = ctx.m_size; if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } // This scaling takes into account the logical size of the font relative // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); Vec2 baseXY = Vec2(x, y); // in pixels if (ctx.m_sizeIn800x600) { - ScaleCoord(baseXY.x, baseXY.y); + ScaleCoord(viewport, baseXY.x, baseXY.y); } // snap for pixel perfect rendering (better quality for text) @@ -826,7 +839,7 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co ColorB tempColor(255, 255, 255, 255); uint32_t frameColor = tempColor.pack_abgr8888(); //note: this ends up in r,g,b,a order on little-endian machines - Vec2 textSize = GetTextSizeUInternal(str, asciiMultiLine, ctx); + Vec2 textSize = GetTextSizeUInternal(viewport, str, asciiMultiLine, ctx); float x0 = baseXY.x - 12; float y0 = baseXY.y - 6; @@ -1107,13 +1120,13 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co return numQuads; } -AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const TextDrawContext& ctx) const +AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const { Vec2 size = GetRestoredFontSize(ctx); // in pixel if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } float rcpCellWidth; @@ -1196,7 +1209,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const maxWidth = gEnv->pRenderer->ScaleCoordX(maxWidth); } - Vec2 strSize = GetTextSizeUInternal(result.c_str(), true, ctx); + Vec2 strSize = GetTextSize(result.c_str(), true, ctx); if (strSize.x <= maxWidth) { @@ -1245,7 +1258,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc) char codepoint[5]; Unicode::Convert(codepoint, ch); - curCharWidth = GetTextSizeUInternal(codepoint, true, ctx).x; + curCharWidth = GetTextSize(codepoint, true, ctx).x; // keep track of spaces // they are good for splitting the string @@ -1425,7 +1438,12 @@ void AZ::FFont::AddCharsToFontTexture(const char* chars, int glyphSizeX, int gly Vec2 AZ::FFont::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const { - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + return GetKerningInternal(m_defaultWindowContext->GetViewport(), leftGlyph, rightGlyph, ctx); +} + +Vec2 AZ::FFont::GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const +{ + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); return m_fontTexture->GetKerning(leftGlyph, rightGlyph) * scaleInfo.scale.x; } @@ -1436,12 +1454,18 @@ float AZ::FFont::GetAscender(const TextDrawContext& ctx) const float AZ::FFont::GetBaseline(const TextDrawContext& ctx) const { - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + return GetBaselineInternal(m_defaultWindowContext->GetViewport(), ctx); +} + +float AZ::FFont::GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const +{ + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); // Calculate baseline the same way as the font renderer which uses the glyph height * size ratio. // Adding 1 because FontTexture always adds 1 to the char height in GetTextureCoord return (round(m_fontTexture->GetCellHeight() * GetSizeRatio()) + 1.0f) * scaleInfo.scale.y; } + bool AZ::FFont::InitTexture() { using namespace AZ; @@ -1565,14 +1589,8 @@ Vec2 AZ::FFont::GetRestoredFontSize(const TextDrawContext& ctx) const return Vec2(ctx.m_size.x * restoringScale, ctx.m_size.y * restoringScale); } -void AZ::FFont::ScaleCoord(float& x, float& y) const +void AZ::FFont::ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const { - if (!m_windowContext) - { - return; - } - - const RHI::Viewport& viewport = m_windowContext->GetViewport(); float width = viewport.m_maxX - viewport.m_minX; float height = viewport.m_maxY - viewport.m_minY; @@ -1580,11 +1598,161 @@ void AZ::FFont::ScaleCoord(float& x, float& y) const y *= height / WindowScaleHeight; } + void AZ::FFont::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) { InitFont(); } +static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::TextDrawParameters& params) +{ + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center) + { + ctx.m_drawTextFlags |= eDrawText_Center; + } -#endif + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right) + { + ctx.m_drawTextFlags |= eDrawText_Right; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center) + { + ctx.m_drawTextFlags |= eDrawText_CenterV; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom) + { + ctx.m_drawTextFlags |= eDrawText_Bottom; + } + + if (params.m_monospace) + { + ctx.m_drawTextFlags |= eDrawText_Monospace; + } + + if (params.m_depthTest) + { + ctx.m_drawTextFlags |= eDrawText_DepthTest; + } + + if (params.m_virtual800x600ScreenSize) + { + ctx.m_drawTextFlags |= eDrawText_800x600; + } + + if (!params.m_scaleWithWindow) + { + ctx.m_drawTextFlags |= eDrawText_FixedSize; + } +} + +void AZ::FFont::DrawScreenAlignedText2d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) +{ + if (params.m_drawViewportId == AzFramework::InvalidViewportId || + string.empty()) + { + return; + } + + //Code mostly duplicated from CRenderer::Draw2dTextWithDepth + float posX = params.m_position.GetX(); + float posY = params.m_position.GetY(); + AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + const AZ::RHI::Viewport& viewport = viewportContext->GetWindowContext()->GetViewport(); + if (params.m_virtual800x600ScreenSize) + { + posX *= WindowScaleWidth / (viewport.m_maxX - viewport.m_minX); + posY *= WindowScaleHeight / (viewport.m_maxY - viewport.m_minY); + } + TextDrawContext ctx; + ctx.SetBaseState(GS_NODEPTHTEST); + ctx.SetColor(AZColorToLYColorF(params.m_color)); + ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f); + ctx.EnableFrame(false); + ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow); + ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize); + ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale)); + if (params.m_monospace || !params.m_scaleWithWindow) + { + ScaleCoord(viewport, posX, posY); + } + + if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left || + params.m_vAlign != AzFramework::TextVerticalAlignment::Top) + { + Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, ctx); + + // If we're using virtual 800x600 coordinates, convert the text size from + // pixels to that before using it as an offset. + if (ctx.m_sizeIn800x600) + { + float width = 1.0f; + float height = 1.0f; + ScaleCoord(viewport, width, height); + textSize.x /= width; + textSize.y /= height; + } + + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center) + { + posX -= textSize.x * 0.5f; + } + else if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right) + { + posX -= textSize.x; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center) + { + posY -= textSize.y * 0.5f; + } + else if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom) + { + posY -= textSize.y; + } + } + SetCommonContextFlags(ctx, params); + ctx.m_drawTextFlags |= eDrawText_2D; + + DrawStringUInternal( + viewport, + viewportContext, + posX, + posY, + params.m_position.GetZ(), // Z + string.data(), + params.m_multiline, + ctx + ); +} + +void AZ::FFont::DrawScreenAlignedText3d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) +{ + if (params.m_drawViewportId == AzFramework::InvalidViewportId || + string.empty()) + { + return; + } + AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView(); + if (!currentView) + { + return; + } + AZ::Vector3 positionNDC = AzFramework::WorldToScreenNDC( + params.m_position, + currentView->GetViewToWorldMatrix(), + currentView->GetViewToClipMatrix() + ); + AzFramework::TextDrawParameters param2d = params; + param2d.m_position = positionNDC; + DrawScreenAlignedText2d(param2d, string); +} + +#endif //USE_NULLFONT_ALWAYS diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 857e795257..fe40cabc12 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -73,6 +73,9 @@ namespace AZ bool RequiresShapeComponent() const; + //! Returns true if the light type is anything other than unknown. + bool LightTypeIsSelected() const; + //! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic bool IsAttenuationRadiusModeAutomatic() const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 2afa6514cd..2dc439b846 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -73,6 +73,11 @@ namespace AZ || m_lightType == LightType::Polygon; } + bool AreaLightComponentConfig::LightTypeIsSelected() const + { + return m_lightType != LightType::Unknown; + } + bool AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic() const { return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 1bbc2a411e..c1c957ed4c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -234,6 +234,11 @@ namespace AZ::Render !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Polygon && m_configuration.m_shapeType != PoylgonShapeTypeId), "The light type is a polygon, but the shape component is not."); } + + if (m_configuration.m_lightType == AreaLightComponentConfig::LightType::SimpleSpot) + { + m_configuration.m_enableShutters = true; // Simple spot always has shutters. + } } void AreaLightComponentController::ConfigurationChanged() @@ -620,6 +625,10 @@ namespace AZ::Render break; } } + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetConfig(&m_configuration); + } } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 32b6a9f0b7..2758da2b38 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -51,14 +51,52 @@ namespace AZ::Render return m_shapeBus->GetRadius() * GetTransform().GetScale().GetMaxElement(); } - void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const { if (isSelected) { - debugDisplay.SetColor(color); + debugDisplay.PushMatrix(transform); + float radius = GetConfig()->m_attenuationRadius; - // Draw a disk for the attenuation radius - debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity)); + if (GetConfig()->m_enableShutters) + { + + float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees); + float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees); + + // Draw a cone using the cone angle and attenuation radius + innerRadians = GetMin(innerRadians, outerRadians); + float coneRadiusInner = sin(innerRadians) * radius; + float coneHeightInner = cos(innerRadians) * radius; + float coneRadiusOuter = sin(outerRadians) * radius; + float coneHeightOuter = cos(outerRadians) * radius; + + auto DrawConicalFrustum = [&debugDisplay](uint32_t numRadiusLines, float topRadius, float bottomRadius, float height, float brightness) + { + debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f)); + debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), bottomRadius); + + for (uint32_t i = 0; i < numRadiusLines; ++i) + { + float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi; + debugDisplay.DrawLine( + Vector3(cos(radiusLineAngle) * topRadius, sin(radiusLineAngle) * topRadius, 0), + Vector3(cos(radiusLineAngle) * bottomRadius, sin(radiusLineAngle) * bottomRadius, height) + ); + } + }; + + DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusInner, coneHeightInner, 1.0f); + DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusOuter, coneHeightOuter, 0.65f); + + } + else + { + debugDisplay.DrawWireDisk(Vector3::CreateZero(), Vector3::CreateAxisZ(), radius); + debugDisplay.DrawArc(Vector3::CreateZero(), radius, 90.0f, 180.0f, -3.0f, 0); + debugDisplay.DrawArc(Vector3::CreateZero(), radius, 0.0f, 180.0f, 3.0f, 1); + } + debugDisplay.PopMatrix(); } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index bdff97b48e..6a07a8a737 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -67,50 +67,56 @@ namespace AZ editContext->Class( "AreaLightComponentConfig", "") ->ClassElement(Edit::ClassElements::EditorData, "") - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light Type", "Which type of light this component represents.") - ->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a Light Type") - ->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (Sphere)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (Simple)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (Disk)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (Simple)") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light type", "Which type of light this component represents.") + ->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a light type") + ->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (sphere)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (simple punctual)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (disk)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (simple punctual)") ->EnumAttribute(AreaLightComponentConfig::LightType::Capsule, "Capsule") ->EnumAttribute(AreaLightComponentConfig::LightType::Quad, "Quad") ->EnumAttribute(AreaLightComponentConfig::LightType::Polygon, "Polygon") ->DataElement(Edit::UIHandlers::Color, &AreaLightComponentConfig::m_color, "Color", "Color of the light") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->Attribute("ColorEditorConfiguration", RPI::ColorUtils::GetLinearRgbEditorConfig()) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying which photometric unit to work in.") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity mode", "Allows specifying which photometric unit to work in.") ->Attribute(AZ::Edit::Attributes::EnumValues, &AreaLightComponentConfig::GetValidPhotometricUnits) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_intensity, "Intensity", "Intensity of the light in the set photometric unit.") ->Attribute(Edit::Attributes::Min, &AreaLightComponentConfig::GetIntensityMin) ->Attribute(Edit::Attributes::Max, &AreaLightComponentConfig::GetIntensityMax) ->Attribute(Edit::Attributes::SoftMin, &AreaLightComponentConfig::GetIntensitySoftMin) ->Attribute(Edit::Attributes::SoftMax, &AreaLightComponentConfig::GetIntensitySoftMax) ->Attribute(Edit::Attributes::Suffix, &AreaLightComponentConfig::GetIntensitySuffix) - ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both Directions", "Whether light should emit from both sides of the surface or just the front") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both directions", "Whether light should emit from both sides of the surface or just the front") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsBothDirections) - ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast Approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsFastApproximation) - ->ClassElement(Edit::ClassElements::Group, "Attenuation Radius") + ->ClassElement(Edit::ClassElements::Group, "Attenuation radius") ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.") ->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic") ->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.") ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->ClassElement(Edit::ClassElements::Group, "Shutters") ->Attribute(Edit::Attributes::AutoExpand, true) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) - ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable Shutters", "Restrict the light to a specific beam angle depending on shape.") + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable shutters", "Restrict the light to a specific beam angle depending on shape.") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner Angle", "The inner angle of the shutters where the light beam begins to be occluded.") + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner angle", "The inner angle of the shutters where the light beam begins to be occluded.") ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 180.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer Angle", "The outer angle of the shutters where the light beam is completely occluded.") + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer angle", "The outer angle of the shutters where the light beam is completely occluded.") ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 180.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) @@ -119,9 +125,9 @@ namespace AZ ->ClassElement(Edit::ClassElements::Group, "Shadows") ->Attribute(Edit::Attributes::AutoExpand, true) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable Shadow", "Enable shadow for the light") + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable shadow", "Enable shadow for the light") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap Size", "Width/Height of shadowmap") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap size", "Width and height of shadowmap") ->EnumAttribute(ShadowmapSize::Size256, " 256") ->EnumAttribute(ShadowmapSize::Size512, " 512") ->EnumAttribute(ShadowmapSize::Size1024, "1024") @@ -129,13 +135,13 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow Filter Method", + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow filter method", "Filtering method of edge-softening of shadows.\n" " None: no filtering\n" - " PCF: Percentage-Closer Filtering\n" - " ESM: Exponential Shadow Maps\n" + " PCF: Percentage-closer Filtering\n" + " ESM: Exponential shadow maps\n" " ESM+PCF: ESM with a PCF fallback\n" - "For BehaviorContext (or TrackView), None=0, PCF=1, ESM=2, ESM+PCF=3") + "For BehaviorContext (or track view), None=0, PCF=1, ESM=2, ESM+PCF=3") ->EnumAttribute(ShadowFilterMethod::None, "None") ->EnumAttribute(ShadowFilterMethod::Pcf, "PCF") ->EnumAttribute(ShadowFilterMethod::Esm, "ESM") @@ -143,7 +149,7 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening Boundary Width", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening boundary width", "Width of the boundary between shadowed area and lit one. " "Units are in degrees. " "If this is 0, softening edge is disabled.") @@ -152,26 +158,27 @@ namespace AZ ->Attribute(Edit::Attributes::Suffix, " deg") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction sample count", "Sample Count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 16) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering sample count", "It is used only when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 64) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) ->DataElement( - Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf Method", - "Type of Pcf to use.\n" + Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf method", + "Type of PCF to use.\n" " Boundary search: do several taps to first determine if we are on a shadow boundary\n" " Bicubic: a smooth, fixed-size kernel \n") - ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search") + ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled); ; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 4cf94c1a58..da221341c3 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -40,6 +41,8 @@ namespace AZ LightDelegateBase(EntityId entityId, bool isVisible); virtual ~LightDelegateBase(); + void SetConfig(const AreaLightComponentConfig* config) override; + // LightDelegateInterface overrides... void SetChroma(const AZ::Color& chroma) override; void SetIntensity(float intensity) override; @@ -66,6 +69,7 @@ namespace AZ // Trivial getters FeatureProcessorType* GetFeatureProcessor() const { return m_featureProcessor; }; + const AreaLightComponentConfig* GetConfig() const { return m_componentConfig; }; typename FeatureProcessorType::LightHandle GetLightHandle() const { return m_lightHandle; }; const AZ::Transform& GetTransform() const { return m_transform; }; bool GetShuttersEnabled() { return m_shuttersEnabled; }; @@ -81,6 +85,7 @@ namespace AZ private: FeatureProcessorType* m_featureProcessor = nullptr; typename FeatureProcessorType::LightHandle m_lightHandle; + const AreaLightComponentConfig* m_componentConfig = nullptr; LmbrCentral::ShapeComponentRequests* m_shapeBus; AZ::Transform m_transform; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl index ee4a29f1b0..406df42547 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl @@ -59,6 +59,12 @@ namespace AZ m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb()); } } + + template + void LightDelegateBase::SetConfig(const AreaLightComponentConfig* config) + { + m_componentConfig = config; + } template void LightDelegateBase::SetChroma(const AZ::Color& color) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index 110a7d73ad..b3f5fb6014 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -33,6 +33,9 @@ namespace AZ { public: virtual ~LightDelegateInterface() {}; + + //! Sets the area light component config so delegates don't have to cache the same data locally. + virtual void SetConfig(const AreaLightComponentConfig* config) = 0; //! Sets the color of the light independent of light intensity. The color is a mask on the total light intensity. virtual void SetChroma(const AZ::Color& chroma) = 0; //! Sets the light intensity diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp index 255f527557..705a71571a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp @@ -44,15 +44,40 @@ namespace AZ::Render { GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); } - - void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + + void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const { if (isSelected) { - debugDisplay.SetColor(color); + float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees); + float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees); + float radius = GetConfig()->m_attenuationRadius; - // Draw a cone for the cone angle and attenuation radius - debugDisplay.DrawCone(transform.GetTranslation(), transform.GetBasisX(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity), false); + // Draw a cone using the cone angle and attenuation radius + innerRadians = GetMin(innerRadians, outerRadians); + float coneRadiusInner = sin(innerRadians) * radius; + float coneHeightInner = cos(innerRadians) * radius; + float coneRadiusOuter = sin(outerRadians) * radius; + float coneHeightOuter = cos(outerRadians) * radius; + + debugDisplay.PushMatrix(transform); + + auto DrawCone = [&debugDisplay](uint32_t numRadiusLines, float radius, float height, float brightness) + { + debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f)); + debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), radius); + + for (uint32_t i = 0; i < numRadiusLines; ++i) + { + float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi; + debugDisplay.DrawLine(Vector3::CreateZero(), Vector3(cos(radiusLineAngle) * radius, sin(radiusLineAngle) * radius, height)); + } + }; + + DrawCone(16, coneRadiusInner, coneHeightInner, 1.0f); + DrawCone(16, coneRadiusOuter, coneHeightOuter, 0.65f); + + debugDisplay.PopMatrix(); } } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h index 66569fc27c..28359daaef 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h @@ -25,6 +25,8 @@ namespace AZ class SimpleSpotLightDelegate final : public LightDelegateBase { + using Base = LightDelegateBase; + public: SimpleSpotLightDelegate(EntityId entityId, bool isVisible); @@ -34,9 +36,9 @@ namespace AZ float GetSurfaceArea() const override; float GetEffectiveSolidAngle() const override { return PhotometricValue::DirectionalEffectiveSteradians; } void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; + private: virtual void HandleShapeChanged(); - }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp b/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp index 093e068e2a..955b240514 100644 --- a/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp +++ b/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp @@ -519,8 +519,8 @@ void CAtomShimRenderAuxGeom::DrawQuad(float width, float height, const Matrix34& if (auto auxGeom = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(defaultScene)) { AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; - AZ::Transform transform = LYTransformToAZTransform(matWorld); - auxGeom->DrawQuad(width, height, transform, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest); + AZ::Matrix3x4 local2World = LYTransformToAZMatrix3x4(matWorld); + auxGeom->DrawQuad(width, height, local2World, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest); } } diff --git a/cmake/FindTarget.cmake.in b/cmake/FindTarget.cmake.in new file mode 100644 index 0000000000..7d0129d05a --- /dev/null +++ b/cmake/FindTarget.cmake.in @@ -0,0 +1,45 @@ +# +# 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. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +ly_add_target( + +NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED + +@NAMESPACE_PLACEHOLDER@ + +@INCLUDE_DIRECTORIES_PLACEHOLDER@ + +@BUILD_DEPENDENCIES_PLACEHOLDER@ + +@RUNTIME_DEPENDENCIES_PLACEHOLDER@ + +@COMPILE_DEFINITIONS_PLACEHOLDER@ +) + +# The below if was generated from if (NOT HEADER_ONLY_PLACEHOLDER) +# HEADER_ONLY_PLACEHOLDER evaluates to TRUE or FALSE +if (NOT @HEADER_ONLY_PLACEHOLDER@) + # Load information for each installed configuration. + foreach(config @ALL_CONFIGS@) + set(@NAME_PLACEHOLDER@_${config}_FOUND FALSE) + include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake") + endforeach() + + find_package_handle_standard_args(@NAME_PLACEHOLDER@ + "Could not find package @NAME_PLACEHOLDER@" + @TARGET_CONFIG_FOUND_VARS_PLACEHOLDER@) +else() + set(@NAME_PLACEHOLDER@_FOUND TRUE) +endif() \ No newline at end of file diff --git a/cmake/Findo3de.cmake b/cmake/Findo3de.cmake index 30246ebd4b..0b4d0b75e7 100644 --- a/cmake/Findo3de.cmake +++ b/cmake/Findo3de.cmake @@ -27,24 +27,19 @@ if(json_error) message(FATAL_ERROR "Unable to read key 'engine_name' from '${current_path}/../engine.json', error: ${json_error}") endif() -if(NOT this_engine_name STREQUAL LY_ENGINE_NAME_TO_USE) - set(o3de_FOUND FALSE) - set(o3de_NOT_FOUND_MESSAGE) - find_package_handle_standard_args(o3de - "Could not find an engine with matching ${LY_ENGINE_NAME_TO_USE}" - o3de_FOUND - ) - return() +set(found_matching_engine FALSE) +if(this_engine_name STREQUAL LY_ENGINE_NAME_TO_USE) + set(found_matching_engine TRUE) endif() +find_package_handle_standard_args(o3de + "Could not find an engine with matching ${LY_ENGINE_NAME_TO_USE}" + found_matching_engine +) + macro(o3de_initialize) + set(INSTALLED_ENGINE FALSE) set(LY_PROJECTS ${CMAKE_CURRENT_LIST_DIR}) o3de_current_file_path(current_path) add_subdirectory(${current_path}/.. o3de) -endmacro() - -message(STATUS "Found ${this_engine_name} in ${current_path}") -set(o3de_FOUND FALSE) -find_package_handle_standard_args(o3de - o3de_FOUND -) \ No newline at end of file +endmacro() \ No newline at end of file diff --git a/cmake/Findo3de.cmake.in b/cmake/Findo3de.cmake.in new file mode 100644 index 0000000000..7ecb73e874 --- /dev/null +++ b/cmake/Findo3de.cmake.in @@ -0,0 +1,36 @@ +# +# 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. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +# This will be called from within the installed engine's CMakeLists.txt +macro(ly_find_o3de_packages) + @FIND_PACKAGES_PLACEHOLDER@ + find_package(LauncherGenerator) +endmacro() + + +function(o3de_current_file_path path) + set(${path} ${CMAKE_CURRENT_FUNCTION_LIST_DIR} PARENT_SCOPE) +endfunction() + + +# We are using the engine's CMakeLists.txt to handle initialization/importing targets +# Since this is external to the project's source, we need to specify an output directory +# even though we don't build +macro(o3de_initialize) + set(INSTALLED_ENGINE TRUE) + set(LY_PROJECTS ${CMAKE_SOURCE_DIR}) + o3de_current_file_path(current_path) + add_subdirectory(${current_path}/.. o3de) +endmacro() \ No newline at end of file diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 9164105f3a..7ac9a3afa8 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -13,13 +13,6 @@ #! ly_install_target: registers the target to be installed by cmake install. # # \arg:NAME name of the target -# \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies -# \arg:INCLUDE_DIRECTORIES paths to the include directories -# \arg:BUILD_DEPENDENCIES list of interfaces this target depends on (could be a compilation dependency -# if the dependency is only exposing an include path, or could be a linking -# dependency is exposing a lib) -# \arg:RUNTIME_DEPENDENCIES list of dependencies this target depends on at runtime -# \arg:COMPILE_DEFINITIONS list of compilation definitions this target will use to compile function(ly_install_target ly_install_target_NAME) # All include directories marked PUBLIC or INTERFACE will be installed @@ -143,7 +136,7 @@ function(ly_generate_target_find_file) set(HEADER_ONLY_PLACEHOLDER TRUE) endif() - configure_file(${LY_ROOT_FOLDER}/cmake/FindTargetTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) + configure_file(${LY_ROOT_FOLDER}/cmake/FindTarget.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) endfunction() @@ -214,7 +207,7 @@ function(ly_setup_o3de_install) string(REPLACE ";" "\n" FIND_PACKAGES_PLACEHOLDER "${find_package_list}") - configure_file(${LY_ROOT_FOLDER}/cmake/Findo3deTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) + configure_file(${LY_ROOT_FOLDER}/cmake/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) ly_install_launcher_target_generator() From 8378f52ba6c757a2760050a02a3a31f49c80fae5 Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Fri, 16 Apr 2021 12:06:05 -0700 Subject: [PATCH 093/122] Fix bug in ShaderVariantAssetBuilder. Add cvar in MeshDrawPacket class. (#61) Fix bug in ShaderVariantAssetBuilder. Add a console variable to force root shader variant usage. --- .../Code/Source/Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Include/Atom/Feature/Mesh/MeshFeatureProcessor.h | 9 ++++++++- .../Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 5 +++++ .../RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp | 11 ++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 034d0c7cf2..1e3c7b6759 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -162,7 +162,7 @@ namespace AZ AZStd::string expectedHigherPrecedenceFileFullPath; AzFramework::StringFunc::Path::Join(gameProjectPath, RPI::ShaderVariantTreeAsset::CommonSubFolder, expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */); AzFramework::StringFunc::Path::Join(expectedHigherPrecedenceFileFullPath.c_str(), shaderProductFileRelativePath.c_str(), expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */); - AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantAsset::Extension); + AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantListSourceData::Extension); AzFramework::StringFunc::Path::Normalize(expectedHigherPrecedenceFileFullPath); AZStd::string normalizedShaderVariantListFileFullPath = shaderVariantListFileFullPath; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index a595471813..7ad8bd8283 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace AZ { @@ -160,8 +161,14 @@ namespace AZ // called when reflection probes are modified in the editor so that meshes can re-evaluate their probes void UpdateMeshReflectionProbes(); - private: + void ForceRebuildDrawPackets(const AZ::ConsoleCommandContainer& arguments); + AZ_CONSOLEFUNC(MeshFeatureProcessor, + ForceRebuildDrawPackets, + AZ::ConsoleFunctorFlags::Null, + "(For Testing) Invalidates all mesh draw packets, causing them to rebuild on the next frame." + ); + MeshFeatureProcessor(const MeshFeatureProcessor&) = delete; // RPI::SceneNotificationBus::Handler overrides... diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 95bbe13586..5f39c6bc38 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -387,6 +387,11 @@ namespace AZ } } + void MeshFeatureProcessor::ForceRebuildDrawPackets([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) + { + m_forceRebuildDrawPackets = true; + } + void MeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) { m_forceRebuildDrawPackets = true;; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp index 1e5eaab20c..d0a277304e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp @@ -17,11 +17,20 @@ #include #include #include +#include namespace AZ { namespace RPI { + AZ_CVAR(bool, + r_forceRootShaderVariantUsage, + false, + [](const bool&) { AZ::Interface::Get()->PerformCommand("MeshFeatureProcessor.ForceRebuildDrawPackets"); }, + ConsoleFunctorFlags::Null, + "(For Testing) Forces usage of root shader variant in the mesh draw packet level, ignoring any other shader variants that may exist." + ); + MeshDrawPacket::MeshDrawPacket( ModelLod& modelLod, size_t modelLodMeshIndex, @@ -187,7 +196,7 @@ namespace AZ } const ShaderVariantId finalVariantId = shaderOptions.GetShaderVariantId(); - const ShaderVariant& variant = shader->GetVariant(finalVariantId); + const ShaderVariant& variant = r_forceRootShaderVariantUsage ? shader->GetRootVariant() : shader->GetVariant(finalVariantId); Data::Instance drawSrg; if (drawSrgAsset) From 3299730899789aa4de285635bf922c0cc62992be Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 14:23:01 -0500 Subject: [PATCH 094/122] re-adding EPB tests --- .../Gem/PythonTests/CMakeLists.txt | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 056c7982a6..a8ea3f9837 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -117,22 +117,22 @@ endif() #endif() ## Editor Python Bindings ## -#if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) -# ly_add_pytest( -# NAME AutomatedTesting::EditorPythonBindings -# TEST_SUITE sandbox -# TEST_SERIAL -# PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings -# TIMEOUT 3600 -# RUNTIME_DEPENDENCIES -# Legacy::Editor -# Legacy::CryRenderNULL -# AZ::AssetProcessor -# AutomatedTesting.Assets -# Gem::EditorPythonBindings.Editor -# COMPONENT TestTools -# ) -#endif() +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_pytest( + NAME AutomatedTesting::EditorPythonBindings + TEST_SUITE sandbox + TEST_SERIAL + PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings + TIMEOUT 3600 + RUNTIME_DEPENDENCIES + Legacy::Editor + Legacy::CryRenderNULL + AZ::AssetProcessor + AutomatedTesting.Assets + Gem::EditorPythonBindings.Editor + COMPONENT TestTools + ) +endif() ## Python Asset Builder ## if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) From 3e9c08687273700c287356117edf12ddfe80b881 Mon Sep 17 00:00:00 2001 From: jckand Date: Fri, 16 Apr 2021 14:40:44 -0500 Subject: [PATCH 095/122] LYN-2764: Replacing image asset for ImageGradient automated test --- .../Assets/ImageGradients/image_grad_test_gsi.png | 3 +++ AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png | 3 --- .../ImageGradient_ProcessedImageAssignedSuccessfully.py | 4 ++-- .../largeworlds/gradient_signal/test_ImageGradient.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png delete mode 100644 AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png diff --git a/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png b/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png new file mode 100644 index 0000000000..228aa877ce --- /dev/null +++ b/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:171f38d536d7b805cc644513d22dae5552a4eef2bffb88e97e089898cf769530 +size 2126 diff --git a/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png b/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png deleted file mode 100644 index eab76f1f78..0000000000 --- a/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6388466c97009fd3993e5d3b59a2b0961f623c6becbd0a12a0a5eb7bd8da5d4e -size 12302 diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py index 6b4a8bf17c..ccc8c3f101 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py @@ -77,13 +77,13 @@ class TestImageGradient(EditorTestHelper): # 3) Assign the processed gradient signal image as the Image Gradient's image asset and verify success # First, check for the base image in the workspace - base_image = "lumberyard_gsi.png" + base_image = "image_grad_test_gsi.png" base_image_path = os.path.join("AutomatedTesting", "Assets", "ImageGradients", base_image) if os.path.isfile(base_image_path): print(f"{base_image} was found in the workspace") # Next, assign the processed image to the Image Gradient's Image Asset property - processed_image_path = os.path.join("Assets", "ImageGradients", "lumberyard_gsi.gradimage") + processed_image_path = os.path.join("Assets", "ImageGradients", "image_grad_test_gsi.gradimage") asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", processed_image_path, math.Uuid(), False) hydra.get_set_test(image_gradient_entity, 0, "Configuration|Image Asset", asset_id) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py index 11712f8b65..8fc582c2c8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py @@ -57,7 +57,7 @@ class TestImageGradientRequiresShape(object): "Entity has a Image Gradient component", "Entity has a Gradient Transform Modifier component", "Entity has a Box Shape component", - "lumberyard_gsi.png was found in the workspace", + "image_grad_test_gsi.png was found in the workspace", "Entity Configuration|Image Asset: SUCCESS", "ImageGradient_ProcessedImageAssignedSucessfully: result=SUCCESS", ] From 854167c68e56a0a7ba2dc210cfd84b167ac34a0a Mon Sep 17 00:00:00 2001 From: guthadam Date: Fri, 16 Apr 2021 14:53:31 -0500 Subject: [PATCH 096/122] Ensure default material selection works when dialog is opened https://jira.agscollab.com/browse/ATOM-15267 --- .../CreateMaterialDialog.cpp | 29 ++++++++++++++----- .../CreateMaterialDialog.h | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) 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 20d1b587b5..76aee99e52 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp @@ -60,13 +60,17 @@ namespace MaterialEditor AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, enumerateCB, nullptr); //Update the material type file info whenever the combo box selection changes - QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), m_ui->m_materialTypeComboBox, [this](int index) { - QVariant data = m_ui->m_materialTypeComboBox->itemData(index); - m_materialTypeFileInfo = QFileInfo(data.toString()); - }); + QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); }); + QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); }); - //Select StandardPBR by default but we will later data drive this with editor settings - m_ui->m_materialTypeComboBox->setCurrentText("StandardPBR"); + // Select StandardPBR by default but we will later data drive this with editor settings + const int index = m_ui->m_materialTypeComboBox->findText("StandardPBR"); + if (index >= 0) + { + m_ui->m_materialTypeComboBox->setCurrentIndex(index); + } + + UpdateMaterialTypeSelection(); } void CreateMaterialDialog::InitMaterialFileSelection() @@ -88,15 +92,24 @@ namespace MaterialEditor m_materialFileInfo.absoluteFilePath(), QString("Material (*.material)")); - //Reject empty or invalid filenames which indicate user cancellation + // Reject empty or invalid filenames which indicate user cancellation if (!fileInfo.absoluteFilePath().isEmpty()) { m_materialFileInfo = fileInfo; m_ui->m_materialFilePicker->setText(m_materialFileInfo.fileName()); } - }); + }); } + void CreateMaterialDialog::UpdateMaterialTypeSelection() + { + const int index = m_ui->m_materialTypeComboBox->currentIndex(); + if (index >= 0) + { + const QVariant itemData = m_ui->m_materialTypeComboBox->itemData(index); + m_materialTypeFileInfo = QFileInfo(itemData.toString()); + } + } } // namespace MaterialEditor #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h index bf39671343..54d7c2175d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h @@ -36,5 +36,6 @@ namespace MaterialEditor QScopedPointer m_ui; void InitMaterialTypeSelection(); void InitMaterialFileSelection(); + void UpdateMaterialTypeSelection(); }; } // namespace MaterialEditor From c98a1cebaaa613b3ea1634ce7f4e3269691a5ca7 Mon Sep 17 00:00:00 2001 From: alexpete Date: Fri, 16 Apr 2021 13:33:16 -0700 Subject: [PATCH 097/122] GetDefaultView needs full View definition --- .../Code/Source/AtomDebugDisplayViewportInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index 4cab7b8869..77f15284f1 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -17,8 +17,8 @@ #include #include #include - #include +#include #include #include From 3d91b19c194c5736606a10d02846b4e2e5c74f8f Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 15:41:03 -0500 Subject: [PATCH 098/122] printing wrong asset ID in message cleaned up comment --- .../PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py | 2 +- .../Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py index 608c2d224d..54857c2067 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -24,7 +24,7 @@ mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080 mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset' assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False) if (assetId.is_valid() is False): - raise_and_stop(f'Mock AssetId is not valid!') + raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead') if (assetId.to_string().endswith(':54c06b89') is False): raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py index 00a656abd0..c60871ac46 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -58,7 +58,7 @@ def process_file(request): mockFilename = mockFilename.replace('\\', '/').lower() tempFilename = os.path.join(request.tempDirPath, mockFilename) - # write out a tempFilename like a JSON or something? + # write out a tempFilename like a JSON fileOutput = open(tempFilename, "w") fileOutput.write('{}') fileOutput.close() From 41981412c5a2dcd9065725399ed465fa18301164 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 13:56:46 -0700 Subject: [PATCH 099/122] SPEC-6370 Mark a build as "NOT_BUILT" if it didnt build anything --- scripts/build/Jenkins/Jenkinsfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 3d9ddd0411..f77c139342 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -469,6 +469,8 @@ try { return } + def someBuildHappened = false + // Build and Post-Build Testing Stage def buildConfigs = [:] @@ -479,6 +481,7 @@ try { def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this def nodeLabel = envVars['NODE_LABEL'] + someBuildHappened = true buildConfigs["${platform.key} [${build_job.key}]"] = { node("${nodeLabel}") { @@ -538,6 +541,9 @@ try { echo 'All builds successful' } + if (!someBuildHappened) { + currentBuild.result = 'NOT_BUILT' + } } catch(Exception e) { error "Exception: ${e}" From 0db617f4d849d71bc77aec41731e0f1d210c137d Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 16 Apr 2021 14:19:45 -0700 Subject: [PATCH 100/122] Make EMotionFX shaders load from the Shaders directory, instead of prepending "Shaders" to all filenames (#56) Because the `shaderPath` variable is used as a base directory, it needs to end with the directory separator. Otherwise the parts before the data dir become a file prefix used when loading all shaders. Attempts to load "Line_VS.glsl" from "Shaders/" end up instead trying to load "ShadersLine_VS.glsl". --- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 10 +++- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 20 ++++---- .../Rendering/OpenGL2/Source/GLSLShader.h | 7 +-- .../OpenGL2/Source/GraphicsManager.cpp | 47 +++++++------------ .../OpenGL2/Source/GraphicsManager.h | 19 ++++---- .../OpenGL2/Source/PostProcessShader.cpp | 3 +- .../OpenGL2/Source/PostProcessShader.h | 3 +- .../Rendering/OpenGL2/Source/ShaderCache.cpp | 6 +-- .../Rendering/OpenGL2/Source/shadercache.h | 4 +- .../OpenGLRender/OpenGLRenderPlugin.cpp | 2 +- 10 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index 3ef3908271..b8b4843555 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -131,8 +131,14 @@ namespace RenderGL void GLRenderUtil::Validate() { - mLineShader->Validate(); - mMeshShader->Validate(); + if (mLineShader) + { + mLineShader->Validate(); + } + if (mMeshShader) + { + mMeshShader->Validate(); + } } // destroy the allocated memory diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 54b926c4fa..b11c3cb955 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -116,12 +116,12 @@ namespace RenderGL } - bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, const char* filename) + bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename) { - QFile file(filename); + QFile file(QString::fromUtf8(filename.Native().data(), aznumeric_caster(filename.Native().size()))); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%s'.", filename); + AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%.*s'.", AZ_STRING_ARG(filename.Native())); return false; } @@ -156,7 +156,7 @@ namespace RenderGL if (success == false) { - MCore::LogError("[GLSL] Failed to compile shader '%s'.", filename); + MCore::LogError("[GLSL] Failed to compile shader '%.*s'.", AZ_STRING_ARG(filename.Native())); return false; } @@ -212,7 +212,7 @@ namespace RenderGL // Init - bool GLSLShader::Init(const char* vFile, const char* pFile, MCore::Array& defines) + bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) { initializeOpenGLFunctions(); /*const char* args[] = { "unroll all", @@ -225,24 +225,24 @@ namespace RenderGL glUseProgram(0); // compile shaders - if (vFile && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vFile) == false) + if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vertexFileName) == false) { return false; } - if (pFile && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pFile) == false) + if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pixelFileName) == false) { return false; } // create program mProgram = glCreateProgram(); - if (vFile) + if (!vertexFileName.empty()) { glAttachShader(mProgram, mVertexShader); } - if (pFile) + if (!pixelFileName.empty()) { glAttachShader(mProgram, mPixelShader); } @@ -256,7 +256,7 @@ namespace RenderGL if (!success) { - MCore::LogInfo("[OpenGL] Failed to link shaders '%s' and '%s' ", vFile, pFile); + MCore::LogInfo("[OpenGL] Failed to link shaders '%.*s' and '%.*s' ", AZ_STRING_ARG(vertexFileName.Native()), AZ_STRING_ARG(pixelFileName.Native())); InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog); return false; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h index b9251dd718..73aee4313f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h @@ -14,6 +14,7 @@ #define __RENDERGL_GLSLSHADER_H #include +#include #include "Shader.h" // include OpenGL @@ -45,7 +46,7 @@ namespace RenderGL MCORE_INLINE unsigned int GetProgram() const { return mProgram; } bool CheckIfIsDefined(const char* attributeName); - bool Init(const char* vertexFileName, const char* pixelFileName, MCore::Array& defines); + bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override; void SetUniform(const char* name, float value) override; @@ -81,11 +82,11 @@ namespace RenderGL ShaderParameter* FindAttribute(const char* name); ShaderParameter* FindUniform(const char* name); - bool CompileShader(const GLenum type, unsigned int* outShader, const char* filename); + bool CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename); template void InfoLog(GLuint object, T func); - AZStd::string mFileName; + AZ::IO::Path mFileName; MCore::Array mActivatedAttribs; MCore::Array mActivatedTextures; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp index 127f18ba67..5512028ad5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp @@ -203,7 +203,7 @@ namespace RenderGL // try to initialize the graphics system - bool GraphicsManager::Init(const char* shaderPath) + bool GraphicsManager::Init(AZ::IO::PathView shaderPath) { initializeOpenGLFunctions(); @@ -364,7 +364,7 @@ namespace RenderGL // try to load a texture - Texture* GraphicsManager::LoadTexture([[maybe_unused]] const char* filename, [[maybe_unused]] bool createMipMaps) + Texture* GraphicsManager::LoadTexture([[maybe_unused]] AZ::IO::PathView filename, [[maybe_unused]] bool createMipMaps) { //Texture Library is no longer used //temporarily blank @@ -373,19 +373,19 @@ namespace RenderGL // try to load a texture - Texture* GraphicsManager::LoadTexture(const char* filename) + Texture* GraphicsManager::LoadTexture(AZ::IO::PathView filename) { return LoadTexture(filename, mCreateMipMaps); } // LoadPostProcessShader - PostProcessShader* GraphicsManager::LoadPostProcessShader(const char* cFileName) + PostProcessShader* GraphicsManager::LoadPostProcessShader(AZ::IO::PathView cFileName) { - AZStd::string filename = mShaderPath + AZStd::string(cFileName); + AZ::IO::PathView filename = mShaderPath / cFileName; // check if the shader is already in the cache - Shader* s = mShaderCache.FindShader(filename.c_str()); + Shader* s = mShaderCache.FindShader(filename.Native()); if (s) { return (PostProcessShader*)s; @@ -393,19 +393,19 @@ namespace RenderGL // load the shader from disk PostProcessShader* shader = new PostProcessShader(); - if (!shader->Init(filename.c_str())) + if (!shader->Init(filename)) { delete shader; return nullptr; } - mShaderCache.AddShader(filename.c_str(), shader); + mShaderCache.AddShader(filename.Native(), shader); return shader; } // LoadShader - GLSLShader* GraphicsManager::LoadShader(const char* vertexFileName, const char* pixelFileName) + GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName) { MCore::Array defines; return LoadShader(vertexFileName, pixelFileName, defines); @@ -413,34 +413,21 @@ namespace RenderGL // LoadShader - GLSLShader* GraphicsManager::LoadShader(const char* vFile, const char* pFile, MCore::Array& defines) + GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) { - AZStd::string vStr; - AZStd::string pStr; - - if (vFile) - { - vStr = AZStd::string::format("%s%s", mShaderPath.c_str(), vFile); - } - - if (pFile) - { - pStr = AZStd::string::format("%s%s", mShaderPath.c_str(), pFile); - } + const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName}; + const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName}; // construct the lookup string for the shader cache - AZStd::string dStr; + AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native(); const uint32 numDefines = defines.GetLength(); for (uint32 n = 0; n < numDefines; n++) { - dStr += AZStd::string::format("#%s", defines[n].c_str()); + cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str()); } - AZStd::string cStr; - cStr = AZStd::string::format("%s%s%s", vStr.c_str(), pStr.c_str(), dStr.c_str()); - // check if the shader is already in the cache - Shader* cShader = mShaderCache.FindShader(cStr.c_str()); + Shader* cShader = mShaderCache.FindShader(cacheLookupStr); if (cShader) { return (GLSLShader*)cShader; @@ -448,13 +435,13 @@ namespace RenderGL // load the shader from disk GLSLShader* shader = new GLSLShader(); - if (!shader->Init(vFile ? vStr.c_str() : nullptr, pFile ? pStr.c_str() : nullptr, defines)) + if (!shader->Init(vertexPath, pixelPath, defines)) { delete shader; return nullptr; } - mShaderCache.AddShader(cStr.c_str(), shader); + mShaderCache.AddShader(cacheLookupStr, shader); return shader; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h index 811fe2998b..4aaf6a16d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h @@ -13,6 +13,7 @@ #ifndef __RENDERGL_GRAPHICSMANAGER__H #define __RENDERGL_GRAPHICSMANAGER__H +#include #include #include #include @@ -57,21 +58,21 @@ namespace RenderGL const char* GetDeviceName(); const char* GetDeviceVendor(); MCORE_INLINE RenderTexture* GetRenderTexture() { return mRenderTexture; } - MCORE_INLINE const char* GetShaderPath() const { return mShaderPath.c_str(); } + MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return mShaderPath; } MCORE_INLINE TextureCache* GetTextureCache() { return &mTextureCache; } - bool Init(const char* shaderPath = "Shaders/"); + bool Init(AZ::IO::PathView shaderPath = "Shaders"); bool GetIsPostProcessingEnabled() const { return mPostProcessing; } - PostProcessShader* LoadPostProcessShader(const char* filename); - GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName); - GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName, MCore::Array& defines); + PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename); + GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName); + GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; } MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; } - Texture* LoadTexture(const char* filename, bool createMipMaps); - Texture* LoadTexture(const char* filename); + Texture* LoadTexture(AZ::IO::PathView filename, bool createMipMaps); + Texture* LoadTexture(AZ::IO::PathView filename); void SetCreateMipMaps(bool createMipMaps) { mCreateMipMaps = createMipMaps; } MCORE_INLINE bool GetCreateMipMaps() const { return mCreateMipMaps; } @@ -96,7 +97,7 @@ namespace RenderGL void SetShader(Shader* shader); MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { mRenderTexture = texture; } - MCORE_INLINE void SetShaderPath(const char* shaderPath) { mShaderPath = shaderPath; } + MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { mShaderPath = shaderPath; } MCORE_INLINE void SetBloomEnabled(bool enabled) { mBloomEnabled = enabled; } MCORE_INLINE void SetBloomThreshold(float threshold) { mBloomThreshold = threshold; } @@ -154,7 +155,7 @@ namespace RenderGL MCommon::Camera* mCamera; /**< The camera used for rendering. */ ShaderCache mShaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */ - AZStd::string mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ + AZ::IO::Path mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ MCore::RGBAColor mClearColor; /**< The scene background color. */ MCore::RGBAColor mGradientSourceColor; /**< The background gradient source color. */ MCore::RGBAColor mGradientTargetColor; /**< The background gradient target color. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp index 11f46d2d13..8c5c79391f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp @@ -11,6 +11,7 @@ */ #include +#include #include "PostProcessShader.h" #include "GraphicsManager.h" @@ -82,7 +83,7 @@ namespace RenderGL // Init - bool PostProcessShader::Init(const char* filename) + bool PostProcessShader::Init(AZ::IO::PathView filename) { MCore::Array defines; return GLSLShader::Init(nullptr, filename, defines); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h index c16554faa7..b3068a9b8a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h @@ -13,6 +13,7 @@ #ifndef __RENDERGL_POSTPROCESS_SHADER_H #define __RENDERGL_POSTPROCESS_SHADER_H +#include #include "GLSLShader.h" #include "RenderTexture.h" @@ -34,7 +35,7 @@ namespace RenderGL void Deactivate() override; - bool Init(const char* filename); + bool Init(AZ::IO::PathView filename); void Render(); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp index cef9c93388..b3f2accb66 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp @@ -48,7 +48,7 @@ namespace RenderGL // add the shader to the cache (assume there are no duplicate names) - void ShaderCache::AddShader(const char* filename, Shader* shader) + void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader) { mEntries.AddEmpty(); mEntries.GetLast().mName = filename; @@ -57,12 +57,12 @@ namespace RenderGL // try to locate a shader based on its name - Shader* ShaderCache::FindShader(const char* filename) const + Shader* ShaderCache::FindShader(AZStd::string_view filename) const { const uint32 numEntries = mEntries.GetLength(); for (uint32 i = 0; i < numEntries; ++i) { - if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare + if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare { return mEntries[i].mShader; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h index d7ec884e6a..98bb87d373 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h @@ -33,8 +33,8 @@ namespace RenderGL ~ShaderCache(); // automatically calls Release void Release(); - void AddShader(const char* filename, Shader* shader); - Shader* FindShader(const char* filename) const; + void AddShader(AZStd::string_view filename, Shader* shader); + Shader* FindShader(AZStd::string_view filename) const; bool CheckIfHasShader(Shader* shader) const; private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp index 99f203d6e7..bfd6a3921f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp @@ -64,7 +64,7 @@ namespace EMStudio // create graphics manager and initialize it mGraphicsManager = new RenderGL::GraphicsManager(); - if (mGraphicsManager->Init(shaderPath.c_str()) == false) + if (mGraphicsManager->Init(shaderPath) == false) { MCore::LogError("Could not initialize OpenGL graphics manager."); return false; From 01a2ea64235761b4b9f7eaa284052eee4ec656b6 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 14:21:20 -0700 Subject: [PATCH 101/122] Moving thumbnail assets to AtomLyIntegration --- .../Common/Assets}/Materials/basic_grey.material | 0 .../Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Gems/Atom/{Tools/MaterialEditor/Assets/MaterialEditor => Feature/Common/Assets}/Materials/basic_grey.material (100%) diff --git a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/Materials/basic_grey.material b/Gems/Atom/Feature/Common/Assets/Materials/basic_grey.material similarity index 100% rename from Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/Materials/basic_grey.material rename to Gems/Atom/Feature/Common/Assets/Materials/basic_grey.material diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h index 9c8ea57cea..8a7bace6aa 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h @@ -36,7 +36,7 @@ namespace AZ struct ThumbnailRendererData final { static constexpr const char* LightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; - static constexpr const char* DefaultModelPath = "materialeditor/viewportmodels/quadsphere.azmodel"; + static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial"; RPI::ScenePtr m_scene; From 73f275f479ad7ef48bd0f00291ecf1196eb241f8 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 16 Apr 2021 15:37:26 -0700 Subject: [PATCH 102/122] Get FindOpenGLInterface to use ly_add_external_target() instead --- cmake/3rdParty.cmake | 4 ---- cmake/3rdParty/FindOpenGLInterface.cmake | 14 +++++++------- .../Platform/Linux/OpenGLInterface_linux.cmake | 10 ---------- .../Platform/Linux/cmake_linux_files.cmake | 1 - .../Platform/Mac/OpenGLInterface_mac.cmake | 7 ++----- .../Platform/Windows/OpenGLInterface_windows.cmake | 10 ---------- .../Platform/Windows/cmake_windows_files.cmake | 1 - 7 files changed, 9 insertions(+), 38 deletions(-) delete mode 100644 cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake delete mode 100644 cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index 4cd3ab2917..8d0c030302 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -116,10 +116,6 @@ function(ly_add_external_target) # Setting BASE_PATH variable in the parent scope to allow for the Find<3rdParty>.cmake scripts to use them set(BASE_PATH ${BASE_PATH} PARENT_SCOPE) - if(NOT EXISTS ${BASE_PATH}) - message(FATAL_ERROR "Cannot find 3rdParty library ${ly_add_external_target_NAME} on path ${BASE_PATH}") - endif() - add_library(3rdParty::${NAME_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) if(ly_add_external_target_INCLUDE_DIRECTORIES) diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake index 99bf19c4d7..1e4992290f 100644 --- a/cmake/3rdParty/FindOpenGLInterface.cmake +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -9,11 +9,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -find_package(OpenGL QUIET REQUIRED) -# Imported targets (like OpenGL::GL) are scoped to a directory. Add a -# a global scope -add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) -target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) +find_package(OpenGL) -set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -include(${pal_file}) \ No newline at end of file +ly_add_external_target( + NAME OpenGLInterface + VERSION "" + BUILD_DEPENDENCIES + OpenGL::GL +) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index cce929b909..2b1ba4d0e5 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -16,7 +16,6 @@ set(FILES Clang_linux.cmake dyad_linux.cmake FbxSdk_linux.cmake - OpenGLInterface_linux.cmake OpenSSL_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake index c9a52f4b1b..7d0d47740f 100644 --- a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake @@ -9,8 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -target_compile_definitions(3rdParty::OpenGLInterface - INTERFACE - # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. - GL_SILENCE_DEPRECATION -) \ No newline at end of file +# MacOS 10.14 deprecates OpenGL. This silences the warnings for now. +set(OPENGLINTERFACE_COMPILE_DEFINITIONS GL_SILENCE_DEPRECATION) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 675ae7f695..2c7890fcc4 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -18,7 +18,6 @@ set(FILES dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake - OpenGLInterface_windows.cmake OpenSSL_windows.cmake Wwise_windows.cmake ) From a6c7815685b5e8ec69eb725c23208828ff797ba0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 16:06:54 -0700 Subject: [PATCH 103/122] SPEC-6371 Change the asset_profile and test_profile steps to be no_unity so it doesnt recompile --- .../Tests/AssetSeedManager.cpp | 12 +++---- .../build/Platform/Linux/build_config.json | 32 +++++++++++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp index 2003f8eafd..5ccbd95f09 100644 --- a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp +++ b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp @@ -68,7 +68,7 @@ namespace UnitTest { assets[idx] = AssetId(AZ::Uuid::CreateRandom(), 0); AZ::Data::AssetInfo info; - info.m_relativePath = AZStd::string::format("Asset%d.txt", idx); + info.m_relativePath = AZStd::string::format("asset%d.txt", idx); m_assetsPath[idx] = info.m_relativePath; info.m_assetId = assets[idx]; m_assetRegistry->RegisterAsset(assets[idx], info); @@ -623,7 +623,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList1, assets[fileIndex])); if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath)) { - AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex); + AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex); m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str()); m_fileStreams[0][fileIndex].Close(); } @@ -654,7 +654,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList1, assets[fileIndex])); if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath)) { - AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex + 1);// changing file content + AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex + 1);// changing file content m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str()); m_fileStreams[0][fileIndex].Close(); } @@ -987,7 +987,7 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); - m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 0); } @@ -1003,7 +1003,7 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); - m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC); + m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 1); } @@ -1017,7 +1017,7 @@ namespace UnitTest EXPECT_EQ(seedList.size(), 1); - m_assetSeedManager->RemoveSeedAsset("Asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 1); } diff --git a/scripts/build/Platform/Linux/build_config.json b/scripts/build/Platform/Linux/build_config.json index d7f5ddc9d0..426bf1d7ce 100644 --- a/scripts/build/Platform/Linux/build_config.json +++ b/scripts/build/Platform/Linux/build_config.json @@ -7,14 +7,14 @@ "CMAKE_LY_PROJECTS": "AutomatedTesting" } }, - "profile_pipe": { + "profile_nounity_pipe": { "TAGS": [ "default" ], "steps": [ "profile_nounity", - "asset_profile", - "test_profile" + "asset_profile_nounity", + "test_profile_nounity" ] }, "metrics": { @@ -84,6 +84,18 @@ "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" } }, + "test_profile_nounity": { + "TAGS": [], + "COMMAND": "build_test_linux.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/linux", + "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "all", + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" + } + }, "asset_profile": { "TAGS": [ "weekly-build-metrics" @@ -100,6 +112,20 @@ "ASSET_PROCESSOR_PLATFORMS": "pc,server" } }, + "asset_profile_nounity": { + "TAGS": [], + "COMMAND": "build_asset_linux.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/linux", + "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "AssetProcessorBatch", + "ASSET_PROCESSOR_BINARY": "bin/profile/AssetProcessorBatch", + "ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode", + "ASSET_PROCESSOR_PLATFORMS": "pc,server" + } + }, "asset_clean_profile": { "TAGS": [ "nightly" From 250f8d8db01811dbeb5e0e1fee1f27320acb6f47 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 16:36:21 -0700 Subject: [PATCH 104/122] SPEC-6246 Prevent job overrides from PR branches (#110) --- scripts/build/Jenkins/Jenkinsfile | 35 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index f77c139342..297c406b7b 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -26,8 +26,7 @@ def pipelineParameters = [ booleanParam(defaultValue: false, description: 'Deletes the contents of the output directory before building. This will cause a \"clean\" build. NOTE: does not imply CLEAN_ASSETS', name: 'CLEAN_OUTPUT_DIRECTORY'), booleanParam(defaultValue: false, description: 'Deletes the contents of the output directories of the AssetProcessor before building.', name: 'CLEAN_ASSETS'), booleanParam(defaultValue: false, description: 'Deletes the contents of the workspace and forces a complete pull.', name: 'CLEAN_WORKSPACE'), - booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME'), - string(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE') + booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME') ] def palSh(cmd, lbl = '', winSlashReplacement = true) { @@ -76,18 +75,22 @@ def palRmDir(path) { } } -def IsJobEnabled(buildTypeMap, pipelineName, platformName) { - def job_list_override = params.JOB_LIST_OVERRIDE.tokenize(',') +def IsPullRequest(branchName) { + // temporarily using the name to detect if we are in a PR + // In the future we will check with github + return branchName.startsWith('PR-') +} + +def IsJobEnabled(branchName, buildTypeMap, pipelineName, platformName) { + if (IsPullRequest(branchName)) { + return buildTypeMap.value.TAGS && buildTypeMap.value.TAGS.contains(pipelineName) + } + def job_list_override = params.JOB_LIST_OVERRIDE ? params.JOB_LIST_OVERRIDE.tokenize(',') : '' if (!job_list_override.isEmpty()) { return params[platformName] && job_list_override.contains(buildTypeMap.key); } else { - if (params[platformName]) { - if(buildTypeMap.value.TAGS) { - return buildTypeMap.value.TAGS.contains(pipelineName) - } - } + return params[platformName] && buildTypeMap.value.TAGS && buildTypeMap.value.TAGS.contains(pipelineName) } - return false } def GetRunningPipelineName(JENKINS_JOB_NAME) { @@ -448,8 +451,12 @@ try { pipelineConfig = LoadPipelineConfig(pipelineName, branchName) // Add each platform as a parameter that the user can disable if needed - pipelineConfig.platforms.each { platform -> - pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) + if (!IsPullRequest(branchName)) { + pipelineParameters.add(stringParam(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE')) + + pipelineConfig.platforms.each { platform -> + pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) + } } pipelineProperties.add(parameters(pipelineParameters)) properties(pipelineProperties) @@ -462,7 +469,7 @@ try { } } - if(env.BUILD_NUMBER == '1' && !branchName.startsWith('PR-')) { + if(env.BUILD_NUMBER == '1' && !IsPullRequest(branchName)) { // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 currentBuild.result = 'SUCCESS' @@ -477,7 +484,7 @@ try { // Platform Builds run on EC2 pipelineConfig.platforms.each { platform -> platform.value.build_types.each { build_job -> - if (IsJobEnabled(build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline + if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this def nodeLabel = envVars['NODE_LABEL'] From a519bd6d0cc04845584094b55f3b9db20e1555b5 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Thu, 15 Apr 2021 15:15:53 -0700 Subject: [PATCH 105/122] Fix EditorViewportWidget stealing keyboard focus grabKeyboard was used by CRenderViewport to ensure it received some events, but that logic is no longer needed and the corresponding release was removed. This just removes grabKeyboard entirely - eventually all input event logic will be removed as well. --- Code/Sandbox/Editor/EditorViewportWidget.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index a3b2542418..695a0fa5f1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1617,11 +1617,6 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) // because we want the movement to be butter smooth. if (!event->isAutoRepeat()) { - if (m_keyDown.isEmpty()) - { - grabKeyboard(); - } - m_keyDown.insert(event->key()); } From ab11b234a867b2c0927c03d07e392eede63b350b Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Thu, 15 Apr 2021 15:02:35 -0500 Subject: [PATCH 106/122] Removed AssetProcessor Settings from the bootstrap.cfg file as they are being shadowed by the /Engine/Registry/bootstrap.setreg file. Attempting to set those values in the bootstrap.cfg would only result in them being overridden when the bootstrap.setreg is merged into the settings registry --- bootstrap.cfg | 90 ++++++--------------------------------------------- 1 file changed, 9 insertions(+), 81 deletions(-) diff --git a/bootstrap.cfg b/bootstrap.cfg index cbe6ed025e..3486806a5d 100644 --- a/bootstrap.cfg +++ b/bootstrap.cfg @@ -1,84 +1,12 @@ --- When you see an option that does not have a platform preceeding it, that is the default --- value for anything not specificly set per platform. So if remote_filesystem=0 and you have --- ios_remote_file_system=1 then remote filesystem will be off for all platforms except ios --- Any of the settings in this file can be prefixed with a platform name: --- android, ios, mac, linux, windows, etc... --- or left unprefixed, to set all platforms not specified. The rules apply in the order they're declared +; This file is deprecated and is only use currently for setting the path when running O3DE in an engine-centric manner +; By engine-centric, what is meant is using CMake to configure from the directory and passing in the LY_PROJECTS value project_path=AutomatedTesting --- remote_filesystem - enable Virtual File System (VFS) --- This feature allows a remote instance of the game to run off assets --- on the asset processor computers cache instead of deploying them the remote device --- By default it is off and can be overridden for any platform -remote_filesystem=0 -provo_remote_filesystem=0 -android_remote_filesystem=0 -ios_remote_filesystem=0 -mac_remote_filesystem=0 - --- What type of assets are we going to load? --- We need to know this before we establish VFS because different platform assets --- are stored in different root folders in the cache. These correspond to the names --- In the asset processor config file. This value also controls what config file is read --- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_es3.cfg) --- by default, pc assets (in the 'pc' folder) are used, with RC being fed 'pc' as the platform --- by default on console we use the default assets=pc for better iteration times --- we should turn on console specific assets only when in release and/or testing assets and/or loading performance --- that way most people will not need to have 3 different caches taking up disk space -assets = pc --- provo_assets = provo --- salem_assets = salem --- jasper_assets = jasper -android_assets = es3 -ios_assets = ios -mac_assets = osx_gl - --- Add the IP address of your console to the allowed list that will connect to the asset processor here --- You can list addresses or CIDR's. CIDR's are helpful if you are using DHCP. A CIDR looks like an ip address with --- a /n on the end means how many bits are significant. 8bits.8bits.8bits.8bits = /32 --- Example: 192.168.1.3 --- Example: 192.168.1.3, 192.168.1.15 --- Example: 192.168.1.0/24 will allow any address starting with 192.168.1. --- Example: 192.168.0.0/16 will allow any address starting with 192.168. --- Example: 192.168.0.0/8 will allow any address starting with 192. --- allowed_list = - --- IP address and optionally port of the asset processor. --- Set your PC IP here: (and uncomment the next line) --- If you are running your asset processor on a windows machine you --- can find out your ip address by opening a cmd prompt and typing in ipconfig --- remote_ip = 127.0.0.1 --- remote_port = 45643 - --- Which way do you want to connect the asset processor to the game: 1=game connects to AP "connect", 0=AP connects to game "listen" --- Note: android and IOS over USB port forwarding may need to listen instead of connect -connect_to_remote=0 -windows_connect_to_remote=1 -provo_connect_to_remote=1 -salem_connect_to_remote=0 -jasper_connect_to_remote=0 -android_connect_to_remote=0 -ios_connect_to_remote=0 -mac_connect_to_remote=0 - --- Should we tell the game to wait and not proceed unless we have a connection to the AP or --- do we allow it to continue to try to connect in the background without waiting --- Note: Certain options REQUIRE that we do not proceed unless we have a connection, and will override this option to 1 when set --- Since remote_filesystem=1 requires a connection to proceed it will override our option to 1 -wait_for_connect=0 -provo_wait_for_connect=0 -salem_wait_for_connect=0 -jasper_wait_for_connect=0 -windows_wait_for_connect=1 -android_wait_for_connect=0 -ios_wait_for_connect=0 -mac_wait_for_connect=0 - --- How long applications should wait while attempting to connect to an already launched AP(in seconds) --- connect_ap_timeout=3 - --- How long application should wait when launching the AP and wait for the AP to connect back to it(in seconds) --- This time is dependent on Machine load as well as how long it takes for the new AP instance to initialize --- A debug AP takes longer to start up than a profile AP --- launch_ap_timeout=15 +; The Asset Processor Specific settings are now the /Engine/Registry/bootstrap.setreg settings +; The Engine specific settings can be overridden in order of least precedence to most +; 1. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Gem Settings) +; 2. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Project Settings) +; 3. Override the settings in a "/Registry/*.setreg(patch)" file (User per Project Settings) +; 4. Override the settings in a "~/.o3de/Registry/*.setreg(patch)" file (User Global Settings) +; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms \ No newline at end of file From 373f60f29c5a91b27216dd72adb6533966c8af7d Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 21:44:50 -0500 Subject: [PATCH 107/122] Added a call to update the runtime file paths again after merging all Engine, Gem and Project Settings Registry in case they modified the asset platform key which is used for setting the project cache root --- Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp | 2 ++ .../AzGameFramework/Application/GameApplication.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index b8d3e12712..5266cefca2 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -909,6 +909,8 @@ namespace AZ SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true); #endif + // Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); } void ComponentApplication::SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations) diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index f4fc9364f7..edd4af293d 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -80,6 +80,8 @@ namespace AzGameFramework AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true); #endif + // Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); } AZ::ComponentTypeList GameApplication::GetRequiredSystemComponents() const From 6b1e2c52b1bae499b4ac18b769c64de7eb48d7c7 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 16:48:04 -0500 Subject: [PATCH 108/122] Adding newline at end of file of bootstrap.cfg --- bootstrap.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.cfg b/bootstrap.cfg index 3486806a5d..aa7af07645 100644 --- a/bootstrap.cfg +++ b/bootstrap.cfg @@ -9,4 +9,4 @@ project_path=AutomatedTesting ; 2. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Project Settings) ; 3. Override the settings in a "/Registry/*.setreg(patch)" file (User per Project Settings) ; 4. Override the settings in a "~/.o3de/Registry/*.setreg(patch)" file (User Global Settings) -; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms \ No newline at end of file +; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms From bf2732a26d698246296db8089d80948e69131281 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 17:54:37 -0500 Subject: [PATCH 109/122] Moved the PlatformDefaults files from AzFramework to AzCore --- .../Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.cpp | 0 .../Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Code/Framework/{AzFramework/AzFramework/Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.cpp (100%) rename Code/Framework/{AzFramework/AzFramework/Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.h (100%) diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp similarity index 100% rename from Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.cpp rename to Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h similarity index 100% rename from Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h rename to Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h From 96ef3499316b8d1d255e74d1f33e0ee40c52de1b Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:05:11 -0500 Subject: [PATCH 110/122] Update the AzFramework and AzCore cmake files to point at the new location of the PlatformDefaults.h and PlatformDefaults.cpp file Added an inline namespace for the PlatformDefaults code to ease with aliasing it into the AzFramework namespace --- .../AzCore/PlatformId/PlatformDefaults.cpp | 538 +++++++++--------- .../AzCore/PlatformId/PlatformDefaults.h | 214 +++---- .../AzCore/AzCore/azcore_files.cmake | 2 + .../AzFramework/Platform/PlatformDefaults.h | 23 + .../AzFramework/azframework_files.cmake | 1 - 5 files changed, 403 insertions(+), 375 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp index 81154bae35..63aad1ecf4 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp @@ -11,328 +11,330 @@ */ #include -#include +#include #include -namespace AzFramework +namespace AZ { - static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; - - const char* PlatformIdToPalFolder(AzFramework::PlatformId platform) + inline namespace PlatformDefaults { + static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; + + const char* PlatformIdToPalFolder(AZ::PlatformId platform) + { #ifdef IOS #define AZ_REDEFINE_IOS_AT_END IOS #undef IOS #endif - switch (platform) - { - case AzFramework::PC: - return "PC"; - case AzFramework::ES3: - return "Android"; - case AzFramework::IOS: - return "iOS"; - case AzFramework::OSX: - return "Mac"; - case AzFramework::PROVO: - return "Provo"; - case AzFramework::SALEM: - return "Salem"; - case AzFramework::JASPER: - return "Jasper"; - case AzFramework::SERVER: - return "Server"; - case AzFramework::ALL: - case AzFramework::ALL_CLIENT: - case AzFramework::NumPlatformIds: - case AzFramework::Invalid: - default: - return ""; - } + switch (platform) + { + case AZ::PC: + return "PC"; + case AZ::ES3: + return "Android"; + case AZ::IOS: + return "iOS"; + case AZ::OSX: + return "Mac"; + case AZ::PROVO: + return "Provo"; + case AZ::SALEM: + return "Salem"; + case AZ::JASPER: + return "Jasper"; + case AZ::SERVER: + return "Server"; + case AZ::ALL: + case AZ::ALL_CLIENT: + case AZ::NumPlatformIds: + case AZ::Invalid: + default: + return ""; + } #ifdef AZ_REDEFINE_IOS_AT_END #define IOS AZ_REDEFINE_IOS_AT_END #endif - } - - const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform) - { - if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux) - { - return PlatformPC; - } - else if (osPlatform == PlatformCodeNameMac) - { - return PlatformOSX; - } - else if (osPlatform == PlatformCodeNameAndroid) - { - return PlatformES3; - } - else if (osPlatform == PlatformCodeNameiOS) - { - return PlatformIOS; - } - else if (osPlatform == PlatformCodeNameProvo) - { - return PlatformProvo; - } - else if (osPlatform == PlatformCodeNameSalem) - { - return PlatformSalem; - } - else if (osPlatform == PlatformCodeNameJasper) - { - return PlatformJasper; } - AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)", - aznumeric_cast(osPlatform.size()), osPlatform.data()); - return ""; - } - - PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex) - { - if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds) + const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform) { - return PlatformFlags::Platform_NONE; - } - if (platformIndex == PlatformId::ALL) - { - return PlatformFlags::Platform_ALL; - } - if (platformIndex == PlatformId::ALL_CLIENT) - { - return PlatformFlags::Platform_ALL_CLIENT; - } - return static_cast(1 << platformIndex); - } - - AZStd::fixed_vector PlatformHelper::GetPlatforms(PlatformFlags platformFlags) - { - AZStd::fixed_vector platforms; - for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum) - { - const bool isAllPlatforms = PlatformId::ALL == static_cast(platformNum) - && ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE); - - const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast(platformNum) - && ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE); - - if (isAllPlatforms || isAllClientPlatforms - || (platformFlags & static_cast(1 << platformNum)) != PlatformFlags::Platform_NONE) + if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux) { - platforms.push_back(PlatformNames[platformNum]); + return PlatformPC; } - } - - return platforms; - } - - AZStd::fixed_vector PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags) - { - return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags)); - } - - AZStd::fixed_vector PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags) - { - AZStd::fixed_vector platformIndices; - for (int i = 0; i < PlatformId::NumPlatformIds; i++) - { - PlatformId index = static_cast(i); - if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE) + else if (osPlatform == PlatformCodeNameMac) { - platformIndices.emplace_back(index); + return PlatformOSX; } + else if (osPlatform == PlatformCodeNameAndroid) + { + return PlatformES3; + } + else if (osPlatform == PlatformCodeNameiOS) + { + return PlatformIOS; + } + else if (osPlatform == PlatformCodeNameProvo) + { + return PlatformProvo; + } + else if (osPlatform == PlatformCodeNameSalem) + { + return PlatformSalem; + } + else if (osPlatform == PlatformCodeNameJasper) + { + return PlatformJasper; + } + + AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)", + aznumeric_cast(osPlatform.size()), osPlatform.data()); + return ""; } - return platformIndices; - } - AZStd::fixed_vector PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags) - { - return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags)); - } - - PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform) - { - int platformIndex = GetPlatformIndexFromName(platform); - if (platformIndex == PlatformId::Invalid) + PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex) { - AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast(platform.length()), platform.data()); - return PlatformFlags::Platform_NONE; + if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds) + { + return PlatformFlags::Platform_NONE; + } + if (platformIndex == PlatformId::ALL) + { + return PlatformFlags::Platform_ALL; + } + if (platformIndex == PlatformId::ALL_CLIENT) + { + return PlatformFlags::Platform_ALL_CLIENT; + } + return static_cast(1 << platformIndex); } - if(platformIndex == PlatformId::ALL) + AZStd::fixed_vector PlatformHelper::GetPlatforms(PlatformFlags platformFlags) { - return PlatformFlags::Platform_ALL; + AZStd::fixed_vector platforms; + for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum) + { + const bool isAllPlatforms = PlatformId::ALL == static_cast(platformNum) + && ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE); + + const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast(platformNum) + && ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE); + + if (isAllPlatforms || isAllClientPlatforms + || (platformFlags & static_cast(1 << platformNum)) != PlatformFlags::Platform_NONE) + { + platforms.push_back(PlatformNames[platformNum]); + } + } + + return platforms; } - if (platformIndex == PlatformId::ALL_CLIENT) + AZStd::fixed_vector PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags) { - return PlatformFlags::Platform_ALL_CLIENT; + return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags)); } - return static_cast(1 << platformIndex); - } - - const char* PlatformHelper::GetPlatformName(PlatformId platform) - { - if (platform < 0 || platform > PlatformId::NumPlatformIds) + AZStd::fixed_vector PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags) { - return "invalid"; + AZStd::fixed_vector platformIndices; + for (int i = 0; i < PlatformId::NumPlatformIds; i++) + { + PlatformId index = static_cast(i); + if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE) + { + platformIndices.emplace_back(index); + } + } + return platformIndices; } - return PlatformNames[platform]; - } - void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformId) - { - PlatformId platform = GetPlatformIdFromName(platformId); - AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast(platformId.length()), platformId.data()); - AppendPlatformCodeNames(platformCodes, platform); - } + AZStd::fixed_vector PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags) + { + return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags)); + } - void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId) - { -// The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1". + PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform) + { + int platformIndex = GetPlatformIndexFromName(platform); + if (platformIndex == PlatformId::Invalid) + { + AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast(platform.length()), platform.data()); + return PlatformFlags::Platform_NONE; + } + + if (platformIndex == PlatformId::ALL) + { + return PlatformFlags::Platform_ALL; + } + + if (platformIndex == PlatformId::ALL_CLIENT) + { + return PlatformFlags::Platform_ALL_CLIENT; + } + + return static_cast(1 << platformIndex); + } + + const char* PlatformHelper::GetPlatformName(PlatformId platform) + { + if (platform < 0 || platform > PlatformId::NumPlatformIds) + { + return "invalid"; + } + return PlatformNames[platform]; + } + + void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformId) + { + PlatformId platform = GetPlatformIdFromName(platformId); + AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast(platformId.length()), platformId.data()); + AppendPlatformCodeNames(platformCodes, platform); + } + + void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId) + { + // The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1". #pragma push_macro("IOS") #undef IOS // To reduce work the Asset Processor groups assets that can be shared between hardware platforms together. For this // reason "PC" can for instance cover both the Windows and Linux platforms and "IOS" can cover AppleTV and iOS. - switch (platformId) - { - case PlatformId::PC: - platformCodes.emplace_back(PlatformCodeNameWindows); - platformCodes.emplace_back(PlatformCodeNameLinux); - break; - case PlatformId::ES3: - platformCodes.emplace_back(PlatformCodeNameAndroid); - break; - case PlatformId::IOS: - platformCodes.emplace_back(PlatformCodeNameiOS); - break; - case PlatformId::OSX: - platformCodes.emplace_back(PlatformCodeNameMac); - break; - case PlatformId::PROVO: - platformCodes.emplace_back(PlatformCodeNameProvo); - break; - case PlatformId::SALEM: - platformCodes.emplace_back(PlatformCodeNameSalem); - break; - case PlatformId::JASPER: - platformCodes.emplace_back(PlatformCodeNameJasper); - break; - case PlatformId::SERVER: - // Server is not a hardware platform - break; - default: - AZ_Assert(false, "Unsupported Platform ID: %i", platformId); - break; - } + switch (platformId) + { + case PlatformId::PC: + platformCodes.emplace_back(PlatformCodeNameWindows); + platformCodes.emplace_back(PlatformCodeNameLinux); + break; + case PlatformId::ES3: + platformCodes.emplace_back(PlatformCodeNameAndroid); + break; + case PlatformId::IOS: + platformCodes.emplace_back(PlatformCodeNameiOS); + break; + case PlatformId::OSX: + platformCodes.emplace_back(PlatformCodeNameMac); + break; + case PlatformId::PROVO: + platformCodes.emplace_back(PlatformCodeNameProvo); + break; + case PlatformId::SALEM: + platformCodes.emplace_back(PlatformCodeNameSalem); + break; + case PlatformId::JASPER: + platformCodes.emplace_back(PlatformCodeNameJasper); + break; + case PlatformId::SERVER: + // Server is not a hardware platform + break; + default: + AZ_Assert(false, "Unsupported Platform ID: %i", platformId); + break; + } #pragma pop_macro("IOS") - } - - int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName) - { - for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++) - { - if (platformName == PlatformNames[idx]) - { - return idx; - } } - return PlatformId::Invalid; - } - - PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName) - { - return aznumeric_caster(GetPlatformIndexFromName(platformName)); - } - - AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags) - { - AZStd::fixed_vector platformNames = GetPlatforms(platformFlags); - AssetPlatformCombinedString platformsString; - AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", "); - return platformsString; - } - - PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags) - { - PlatformFlags returnFlags = PlatformFlags::Platform_NONE; - - if((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE) + int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName) { - for (int i = 0; i < NumPlatforms; ++i) + for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++) { - auto platformId = static_cast(i); - - if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT) + if (platformName == PlatformNames[idx]) { - returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + return idx; } } + + return PlatformId::Invalid; } - else if((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE) + + PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName) { - for (int i = 0; i < NumPlatforms; ++i) + return aznumeric_caster(GetPlatformIndexFromName(platformName)); + } + + AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags) + { + AZStd::fixed_vector platformNames = GetPlatforms(platformFlags); + AssetPlatformCombinedString platformsString; + AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", "); + return platformsString; + } + + PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags) + { + PlatformFlags returnFlags = PlatformFlags::Platform_NONE; + + if ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE) { - auto platformId = static_cast(i); - - if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER) + for (int i = 0; i < NumPlatforms; ++i) { - returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + auto platformId = static_cast(i); + + if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT) + { + returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + } } } - } - else - { - returnFlags = platformFlags; + else if ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE) + { + for (int i = 0; i < NumPlatforms; ++i) + { + auto platformId = static_cast(i); + + if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER) + { + returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + } + } + } + else + { + returnFlags = platformFlags; + } + + return returnFlags; } - return returnFlags; + bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags) + { + return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE + || (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE; + } + + bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform) + { + return (flags & checkPlatform) == checkPlatform; + } + + + bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform) + { + // If checkPlatform contains any kind of invalid id, just exit out here + if (checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms) + { + return false; + } + + // ALL_CLIENT + SERVER = ALL + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER)) + { + flags = PlatformFlags::Platform_ALL; + } + + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL)) + { + // It doesn't matter what checkPlatform is set to in this case, just return true + return true; + } + + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT)) + { + return checkPlatform != PlatformId::SERVER; + } + + return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform)); + } } - - bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags) - { - return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE - || (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE; - } - - bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform) - { - return (flags & checkPlatform) == checkPlatform; - } - - - bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform) - { - // If checkPlatform contains any kind of invalid id, just exit out here - if(checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms) - { - return false; - } - - // ALL_CLIENT + SERVER = ALL - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER)) - { - flags = PlatformFlags::Platform_ALL; - } - - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL)) - { - // It doesn't matter what checkPlatform is set to in this case, just return true - return true; - } - - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT)) - { - return checkPlatform != PlatformId::SERVER; - } - - return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform)); - } - } diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h index d7f467ec0f..2d67c860cd 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h @@ -22,134 +22,136 @@ #pragma push_macro("IOS") #undef IOS -namespace AzFramework +namespace AZ { - constexpr char PlatformPC[] = "pc"; - constexpr char PlatformES3[] = "es3"; - constexpr char PlatformIOS[] = "ios"; - constexpr char PlatformOSX[] = "osx_gl"; - constexpr char PlatformProvo[] = "provo"; - constexpr char PlatformSalem[] = "salem"; - constexpr char PlatformJasper[] = "jasper"; - constexpr char PlatformServer[] = "server"; - - constexpr char PlatformCodeNameWindows[] = "Windows"; - constexpr char PlatformCodeNameLinux[] = "Linux"; - constexpr char PlatformCodeNameAndroid[] = "Android"; - constexpr char PlatformCodeNameiOS[] = "iOS"; - constexpr char PlatformCodeNameMac[] = "Mac"; - constexpr char PlatformCodeNameProvo[] = "Provo"; - constexpr char PlatformCodeNameSalem[] = "Salem"; - constexpr char PlatformCodeNameJasper[] = "Jasper"; - constexpr char PlatformAll[] = "all"; - constexpr char PlatformAllClient[] = "all_client"; - - // Used for the capacity of a fixed vector to store the code names of platforms - // The value needs to be higher than the number of unique OS platforms that are supported(at this time 8) - constexpr size_t MaxPlatformCodeNames = 16; - - //! This platform enum have platform values in sequence and can also be used to get the platform count. - AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int, - (Invalid, -1), - PC, - ES3, - IOS, - OSX, - PROVO, - SALEM, - JASPER, - SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc - ALL, - ALL_CLIENT, - - // Add new platforms above this - NumPlatformIds - ); - constexpr int NumClientPlatforms = 7; - constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently - enum class PlatformFlags : AZ::u32 + inline namespace PlatformDefaults { - Platform_NONE = 0x00, - Platform_PC = 1 << PlatformId::PC, - Platform_ES3 = 1 << PlatformId::ES3, - Platform_IOS = 1 << PlatformId::IOS, - Platform_OSX = 1 << PlatformId::OSX, - Platform_PROVO = 1 << PlatformId::PROVO, - Platform_SALEM = 1 << PlatformId::SALEM, - Platform_JASPER = 1 << PlatformId::JASPER, - Platform_SERVER = 1 << PlatformId::SERVER, + constexpr char PlatformPC[] = "pc"; + constexpr char PlatformES3[] = "es3"; + constexpr char PlatformIOS[] = "ios"; + constexpr char PlatformOSX[] = "osx_gl"; + constexpr char PlatformProvo[] = "provo"; + constexpr char PlatformSalem[] = "salem"; + constexpr char PlatformJasper[] = "jasper"; + constexpr char PlatformServer[] = "server"; - // A special platform that will always correspond to all platforms, even if new ones are added - Platform_ALL = 1ULL << 30, + constexpr char PlatformCodeNameWindows[] = "Windows"; + constexpr char PlatformCodeNameLinux[] = "Linux"; + constexpr char PlatformCodeNameAndroid[] = "Android"; + constexpr char PlatformCodeNameiOS[] = "iOS"; + constexpr char PlatformCodeNameMac[] = "Mac"; + constexpr char PlatformCodeNameProvo[] = "Provo"; + constexpr char PlatformCodeNameSalem[] = "Salem"; + constexpr char PlatformCodeNameJasper[] = "Jasper"; + constexpr char PlatformAll[] = "all"; + constexpr char PlatformAllClient[] = "all_client"; - // A special platform that will always correspond to all non-server platforms, even if new ones are added - Platform_ALL_CLIENT = 1ULL << 31, + // Used for the capacity of a fixed vector to store the code names of platforms + // The value needs to be higher than the number of unique OS platforms that are supported(at this time 8) + constexpr size_t MaxPlatformCodeNames = 16; - AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, - }; + //! This platform enum have platform values in sequence and can also be used to get the platform count. + AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int, + (Invalid, -1), + PC, + ES3, + IOS, + OSX, + PROVO, + SALEM, + JASPER, + SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc + ALL, + ALL_CLIENT, - AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags); + // Add new platforms above this + NumPlatformIds + ); + constexpr int NumClientPlatforms = 7; + constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently + enum class PlatformFlags : AZ::u32 + { + Platform_NONE = 0x00, + Platform_PC = 1 << PlatformId::PC, + Platform_ES3 = 1 << PlatformId::ES3, + Platform_IOS = 1 << PlatformId::IOS, + Platform_OSX = 1 << PlatformId::OSX, + Platform_PROVO = 1 << PlatformId::PROVO, + Platform_SALEM = 1 << PlatformId::SALEM, + Platform_JASPER = 1 << PlatformId::JASPER, + Platform_SERVER = 1 << PlatformId::SERVER, - // 32 characters should be more than enough to store a platform name - using AssetPlatformFixedString = AZStd::fixed_string<32>; - // Fixed string which can store a comma separated list of platforms names - // Additional byte is added to take into account the comma - using AssetPlatformCombinedString = AZStd::fixed_string<(AssetPlatformFixedString{}.max_size() + 1) * PlatformId::NumPlatformIds>; + // A special platform that will always correspond to all platforms, even if new ones are added + Platform_ALL = 1ULL << 30, - const char* PlatformIdToPalFolder(AzFramework::PlatformId platform); + // A special platform that will always correspond to all non-server platforms, even if new ones are added + Platform_ALL_CLIENT = 1ULL << 31, - const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform); + AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, + }; - //! Platform Helper is an utility class that can be used to retrieve platform related information - class PlatformHelper - { - public: + AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags); - //! Given a platformIndex returns the platform name - static const char* GetPlatformName(PlatformId platform); + // 32 characters should be more than enough to store a platform name + using AssetPlatformFixedString = AZStd::fixed_string<32>; + // Fixed string which can store a comma separated list of platforms names + // Additional byte is added to take into account the comma + using AssetPlatformCombinedString = AZStd::fixed_string < (AssetPlatformFixedString{}.max_size() + 1)* PlatformId::NumPlatformIds > ; - //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. - static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformName); + const char* PlatformIdToPalFolder(PlatformId platform); - //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. - static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId); + const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform); - //! Given a platform name returns a platform index. - //! If the platform is not found, the method returns -1. - static int GetPlatformIndexFromName(AZStd::string_view platformName); + //! Platform Helper is an utility class that can be used to retrieve platform related information + class PlatformHelper + { + public: - //! Given a platform name returns a platform id. - //! If the platform is not found, the method returns -1. - static PlatformId GetPlatformIdFromName(AZStd::string_view platformName); + //! Given a platformIndex returns the platform name + static const char* GetPlatformName(PlatformId platform); - //! Given a platformIndex returns the platformFlags - static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform); + //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. + static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformName); - //! Given a platformFlags returns all the platform identifiers that are set. - static AZStd::fixed_vector GetPlatforms(PlatformFlags platformFlags); - //! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving - static AZStd::fixed_vector GetPlatformsInterpreted(PlatformFlags platformFlags); + //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. + static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId); - //! Given a platformFlags return a list of PlatformId indices - static AZStd::fixed_vector GetPlatformIndices(PlatformFlags platformFlags); - //! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving - static AZStd::fixed_vector GetPlatformIndicesInterpreted(PlatformFlags platformFlags); + //! Given a platform name returns a platform index. + //! If the platform is not found, the method returns -1. + static int GetPlatformIndexFromName(AZStd::string_view platformName); - //! Given a platform identifier returns its corresponding platform flag. - static PlatformFlags GetPlatformFlag(AZStd::string_view platform); + //! Given a platform name returns a platform id. + //! If the platform is not found, the method returns -1. + static PlatformId GetPlatformIdFromName(AZStd::string_view platformName); - //! Given any platformFlags returns a string listing the input platforms - static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags); + //! Given a platformIndex returns the platformFlags + static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform); - //! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent - static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags); + //! Given a platformFlags returns all the platform identifiers that are set. + static AZStd::fixed_vector GetPlatforms(PlatformFlags platformFlags); + //! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving + static AZStd::fixed_vector GetPlatformsInterpreted(PlatformFlags platformFlags); - //! Returns true if platformFlags contains any special flags - static bool IsSpecialPlatform(PlatformFlags platformFlags); + //! Given a platformFlags return a list of PlatformId indices + static AZStd::fixed_vector GetPlatformIndices(PlatformFlags platformFlags); + //! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving + static AZStd::fixed_vector GetPlatformIndicesInterpreted(PlatformFlags platformFlags); - //! Returns true if platformFlags has checkPlatform flag set. - static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform); - }; + //! Given a platform identifier returns its corresponding platform flag. + static PlatformFlags GetPlatformFlag(AZStd::string_view platform); + + //! Given any platformFlags returns a string listing the input platforms + static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags); + + //! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent + static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags); + + //! Returns true if platformFlags contains any special flags + static bool IsSpecialPlatform(PlatformFlags platformFlags); + + //! Returns true if platformFlags has checkPlatform flag set. + static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform); + }; + } } - #pragma pop_macro("IOS") diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index e100b240c2..5357ed66a6 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -607,6 +607,8 @@ set(FILES Utils/Utils.h Script/lua/lua.h Memory/HeapSchema.cpp + PlatformId/PlatformDefaults.h + PlatformId/PlatformDefaults.cpp PlatformId/PlatformId.h PlatformId/PlatformId.cpp Socket/AzSocket_fwd.h diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h b/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h new file mode 100644 index 0000000000..13f7fa20e5 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h @@ -0,0 +1,23 @@ +/* +* 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 + +// As the Platform defaults is needed within AzCore, +// those structures have been moved to AzCore and brought into +// The AzFramework namespace for backwards compatibility +namespace AzFramework +{ + using namespace AZ::PlatformDefaults; +} diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index cde2afb930..312a3766ac 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -317,7 +317,6 @@ set(FILES Terrain/TerrainDataRequestBus.h Terrain/TerrainDataRequestBus.cpp Platform/PlatformDefaults.h - Platform/PlatformDefaults.cpp Windowing/WindowBus.h Windowing/NativeWindow.cpp Windowing/NativeWindow.h From 603ee5bf838612125e962a4676897914a03251da Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:07:33 -0500 Subject: [PATCH 111/122] Updated the MergeSettingsToRegistry_AddRuntimeFilePaths to use the default asset platform associated with the OS, if the /Amazon/AzCore/Bootstrap/assets key isn't found in the settings registry --- .../Settings/SettingsRegistryMergeUtils.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 392e95bf6e..d68bdc97f3 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -463,18 +464,6 @@ namespace AZ::SettingsRegistryMergeUtils void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry) { ConfigParserSettings parserSettings; - parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view - { - constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" }; - for (AZStd::string_view commentPrefix : commentPrefixes) - { - if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos) - { - return line.substr(0, commentOffset); - } - } - return line; - }; parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey; MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings); } @@ -501,9 +490,10 @@ namespace AZ::SettingsRegistryMergeUtils // and if that's missing just get "assets". constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER; - SettingsRegistryInterface::FixedValueString assetPlatform; buffer = AZStd::fixed_string::format("%s/%s_assets", BootstrapSettingsRootKey, platformName); AZStd::string_view assetPlatformKey(buffer); + // Use the platform codename to retrieve the default asset platform value + SettingsRegistryInterface::FixedValueString assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME); if (!registry.Get(assetPlatform, assetPlatformKey)) { buffer = AZStd::fixed_string::format("%s/assets", BootstrapSettingsRootKey); From 41db22be3d0d1699850f840fcd75830af3d001b1 Mon Sep 17 00:00:00 2001 From: chiyenteng <82238204+chiyenteng@users.noreply.github.com> Date: Fri, 16 Apr 2021 17:06:58 -0700 Subject: [PATCH 112/122] [CherryPick][LYN-2738] Fix Reflect functions of IAnimSequence and CAnimSequence (#103) * [CherryPick][LYN-2738] Fix Reflect functions of IAnimSequence and CAnimSequence (#85) --- Code/CryEngine/CryCommon/IMovieSystem.h | 14 +++++- .../Code/Source/Cinematics/AnimSequence.cpp | 43 +++++++++++++------ .../Code/Source/Cinematics/AnimSequence.h | 2 +- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/Code/CryEngine/CryCommon/IMovieSystem.h b/Code/CryEngine/CryCommon/IMovieSystem.h index 654ccfd240..7a1125ae2b 100644 --- a/Code/CryEngine/CryCommon/IMovieSystem.h +++ b/Code/CryEngine/CryCommon/IMovieSystem.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -914,9 +915,18 @@ struct IAnimStringTable */ struct IAnimSequence { - AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}") + AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}"); + AZ_CLASS_ALLOCATOR(IAnimSequence, AZ::SystemAllocator, 0); - static const int kSequenceVersion = 4; + static const int kSequenceVersion = 5; + + static void Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class(); + } + } //! Flags used for SetFlags(),GetFlags(),SetParentFlags(),GetParentFlags() methods. enum EAnimSequenceFlags diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp index 8d6c547c0e..ffbdce8ed6 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp @@ -823,20 +823,37 @@ void CAnimSequence::SetId(uint32 newId) } ////////////////////////////////////////////////////////////////////////// -void CAnimSequence::Reflect(AZ::SerializeContext* serializeContext) +static bool AnimSequenceVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) { - serializeContext->Class() - ->Version(4) - ->Field("Name", &CAnimSequence::m_name) - ->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId) - ->Field("Flags", &CAnimSequence::m_flags) - ->Field("TimeRange", &CAnimSequence::m_timeRange) - ->Field("ID", &CAnimSequence::m_id) - ->Field("Nodes", &CAnimSequence::m_nodes) - ->Field("SequenceType", &CAnimSequence::m_sequenceType) - ->Field("Events", &CAnimSequence::m_events) - ->Field("Expanded", &CAnimSequence::m_expanded) - ->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId); + if (rootElement.GetVersion() < 5) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid()); + } + + return true; +} + +void CAnimSequence::Reflect(AZ::ReflectContext* context) +{ + IAnimSequence::Reflect(context); + + if (auto serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class() + ->Version(IAnimSequence::kSequenceVersion, &AnimSequenceVersionConverter) + ->Field("Name", &CAnimSequence::m_name) + ->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId) + ->Field("Flags", &CAnimSequence::m_flags) + ->Field("TimeRange", &CAnimSequence::m_timeRange) + ->Field("ID", &CAnimSequence::m_id) + ->Field("Nodes", &CAnimSequence::m_nodes) + ->Field("SequenceType", &CAnimSequence::m_sequenceType) + ->Field("Events", &CAnimSequence::m_events) + ->Field("Expanded", &CAnimSequence::m_expanded) + ->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId); + } } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h index 3069896f50..d54b48c9eb 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h @@ -154,7 +154,7 @@ public: return m_nextTrackId++; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: void ComputeTimeRange(); From 37b4b69bb9d9330f08059a9de802016dd93940e7 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 20:07:20 -0500 Subject: [PATCH 113/122] Adding the */Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.* path to the pal allowed list to allow mention of the IOS macro in the PlatformDefaults.h/PlatformDefaults.cpp file --- scripts/commit_validation/commit_validation/pal_allowedlist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/commit_validation/commit_validation/pal_allowedlist.txt b/scripts/commit_validation/commit_validation/pal_allowedlist.txt index 3b1dfdb3b9..278262d59c 100644 --- a/scripts/commit_validation/commit_validation/pal_allowedlist.txt +++ b/scripts/commit_validation/commit_validation/pal_allowedlist.txt @@ -17,6 +17,7 @@ */Code/Framework/AzCore/AzCore/Math/VectorFloat.h */Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl */Code/Framework/AzCore/AzCore/Memory/nedmalloc.inl +*/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.* */Code/Framework/AzCore/AzCore/PlatformDef.h */Code/Framework/AzCore/AzCore/std/containers/compressed_pair.h */Code/Framework/AzCore/AzCore/std/containers/variant.h From b3cc14dd5cfddb945584c6274c88614b7baade10 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 18:59:21 -0700 Subject: [PATCH 114/122] disabling source control thumbnails in material editor --- .../MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp index bd7e1d94ab..6272312b90 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp @@ -73,7 +73,7 @@ namespace MaterialEditor m_filterModel->SetFilter(CreateFilter()); m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel); - m_ui->m_assetBrowserTreeViewWidget->SetShowSourceControlIcons(true); + m_ui->m_assetBrowserTreeViewWidget->SetShowSourceControlIcons(false); m_ui->m_assetBrowserTreeViewWidget->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); // Maintains the tree expansion state between runs From 456bcb3bf9d04692849259310ef82d37ded2eef0 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Sun, 18 Apr 2021 14:57:52 -0700 Subject: [PATCH 115/122] Updated the EnvironmentCubeMapPipeline to match recent changes to the MainPipeline. Set the multisample state on the EnvironmentCubeMapPipeline render settings. --- .../Passes/EnvironmentCubeMapForwardMSAA.pass | 19 +-- .../Passes/EnvironmentCubeMapPipeline.pass | 116 +++--------------- .../Passes/EnvironmentCubeMapSkyBox.pass | 7 +- .../ReflectionProbe/ReflectionProbe.cpp | 3 + .../Pass/Specific/EnvironmentCubeMapPass.cpp | 12 +- 5 files changed, 45 insertions(+), 112 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass index 60de5e10b9..aa422aa227 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass @@ -49,11 +49,6 @@ "IsArray": 1 } }, - { - "Name": "DepthStencilInputOutput", - "SlotType": "InputOutput", - "ScopeAttachmentUsage": "DepthStencil" - }, { "Name": "TileLightData", "SlotType": "Input", @@ -66,6 +61,13 @@ "ShaderInputName": "m_lightListRemapped", "ScopeAttachmentUsage": "Shader" }, + // Input/Outputs... + { + "Name": "DepthStencilInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "DepthStencil" + }, + // Outputs... { "Name": "DiffuseOutput", "SlotType": "Output", @@ -222,11 +224,12 @@ "Attachment": "Output" } }, + "MultisampleSource": { + "Pass": "This", + "Attachment": "DepthStencilInputOutput" + }, "ImageDescriptor": { "Format": "R8G8B8A8_UNORM", - "MultisampleState": { - "samples": 4 - }, "SharedQueueMask": "Graphics" } }, diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass index 79a42b11f7..0e2fb93359 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass @@ -9,7 +9,8 @@ "Slots": [ { "Name": "Output", - "SlotType": 2 + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" } ], "PassRequests": [ @@ -101,13 +102,8 @@ ] }, { - "Name": "DepthMSAAPass", - "TemplateName": "EnvironmentCubeMapDepthMSAAPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depth", - "PipelineViewTag": "MainCamera" - }, + "Name": "DepthPrePass", + "TemplateName": "DepthMSAAParentTemplate", "Connections": [ { "LocalSlot": "SkinnedMeshes", @@ -115,70 +111,11 @@ "Pass": "SkinningPass", "Attachment": "SkinnedMeshOutputStream" } - } - ] - }, - // The light culling system can do highly accurate culling of transparent objects but it needs - // more depth information than the opaque geometry pass can provide - // Specifically the minimum and maximum depth of transparent objects - { - "Name": "DepthTransparentMinPass", - "TemplateName": "DepthPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depthTransparentMin", - "PipelineViewTag": "MainCamera" - }, - "Connections": [ - { - "LocalSlot": "SkinnedMeshes", - "AttachmentRef": { - "Pass": "SkinningPass", - "Attachment": "SkinnedMeshOutputStream" - } - } - ] - }, - { - "Name": "DepthTransparentMaxPass", - "TemplateName": "DepthMaxPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depthTransparentMax", - "PipelineViewTag": "MainCamera" - }, - "Connections": [ - { - "LocalSlot": "SkinnedMeshes", - "AttachmentRef": { - "Pass": "SkinningPass", - "Attachment": "SkinnedMeshOutputStream" - } - } - ] - }, - { - "Name": "LightCullingTilePreparePass", - "TemplateName": "LightCullingTilePrepareMSAATemplate", - "Connections": [ - { - "LocalSlot": "Depth", - "AttachmentRef": { - "Pass": "DepthMSAAPass", - "Attachment": "Output" - } }, { - "LocalSlot": "DepthTransparentMin", + "LocalSlot": "SwapChainOutput", "AttachmentRef": { - "Pass": "DepthTransparentMinPass", - "Attachment": "Output" - } - }, - { - "LocalSlot": "DepthTransparentMax", - "AttachmentRef": { - "Pass": "DepthTransparentMaxPass", + "Pass": "Parent", "Attachment": "Output" } } @@ -186,40 +123,27 @@ }, { "Name": "LightCullingPass", - "TemplateName": "LightCullingTemplate", + "TemplateName": "LightCullingParentTemplate", "Connections": [ { - "LocalSlot": "TileLightData", + "LocalSlot": "SkinnedMeshes", "AttachmentRef": { - "Pass": "LightCullingTilePreparePass", - "Attachment": "TileLightData" - } - } - ] - }, - { - "Name": "LightCullingRemapPass", - "TemplateName": "LightCullingRemapTemplate", - "Connections": [ - { - "LocalSlot": "TileLightData", - "AttachmentRef": { - "Pass": "LightCullingTilePreparePass", - "Attachment": "TileLightData" + "Pass": "SkinningPass", + "Attachment": "SkinnedMeshOutputStream" } }, { - "LocalSlot": "LightCount", + "LocalSlot": "DepthMSAA", "AttachmentRef": { - "Pass": "LightCullingPass", - "Attachment": "LightCount" + "Pass": "DepthPrePass", + "Attachment": "DepthMSAA" } }, { - "LocalSlot": "LightList", + "LocalSlot": "SwapChainOutput", "AttachmentRef": { - "Pass": "LightCullingPass", - "Attachment": "LightList" + "Pass": "Parent", + "Attachment": "Output" } } ] @@ -259,21 +183,21 @@ { "LocalSlot": "DepthStencilInputOutput", "AttachmentRef": { - "Pass": "DepthMSAAPass", - "Attachment": "Output" + "Pass": "DepthPrePass", + "Attachment": "DepthMSAA" } }, { "LocalSlot": "TileLightData", "AttachmentRef": { - "Pass": "LightCullingRemapPass", + "Pass": "LightCullingPass", "Attachment": "TileLightData" } }, { "LocalSlot": "LightListRemapped", "AttachmentRef": { - "Pass": "LightCullingRemapPass", + "Pass": "LightCullingPass", "Attachment": "LightListRemapped" } } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass index b16cd1cbcc..4c74f9e967 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass @@ -32,11 +32,12 @@ "Attachment": "SpecularInputOutput" } }, + "MultisampleSource": { + "Pass": "This", + "Attachment": "SpecularInputOutput" + }, "ImageDescriptor": { "Format": "R16G16B16A16_FLOAT", - "MultisampleState": { - "samples": 4 - }, "SharedQueueMask": "Graphics" } } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 86c012731c..0826739119 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -248,6 +248,9 @@ namespace AZ AZ::RPI::RenderPipelineDescriptor environmentCubeMapPipelineDesc; environmentCubeMapPipelineDesc.m_mainViewTagName = "MainCamera"; + environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4; + environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_width = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; + environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_height = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; // create a unique name for the pipeline AZ::Uuid uuid = AZ::Uuid::CreateRandom(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp index 5ba43f9f7e..78d99de7d6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp @@ -57,7 +57,7 @@ namespace AZ PassConnection childInputConnection; childInputConnection.m_localSlot = "Output"; childInputConnection.m_attachmentRef.m_pass = "Parent"; - childInputConnection.m_attachmentRef.m_attachment = "CubeMapOutput"; + childInputConnection.m_attachmentRef.m_attachment = "Output"; childRequest.m_connections.emplace_back(childInputConnection); PassSystemInterface* passSystem = PassSystemInterface::Get(); @@ -120,15 +120,17 @@ namespace AZ // create output PassAttachment m_passAttachment = aznew PassAttachment(); - m_passAttachment->m_name = "CubeMapOutput"; - m_passAttachment->m_path = "CubeMapOutput"; + m_passAttachment->m_name = "Output"; + //m_passAttachment->m_path = "Output"; + AZ::Name attachmentPath(AZStd::string::format("%s.%s", GetPathName().GetCStr(), m_passAttachment->m_name.GetCStr())); + m_passAttachment->m_path = attachmentPath; m_passAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient; m_passAttachment->m_descriptor = m_outputImageDesc; // create pass attachment binding PassAttachmentBinding outputAttachment; - outputAttachment.m_name = "CubeMapOutput"; - outputAttachment.m_slotType = PassSlotType::Output; + outputAttachment.m_name = "Output"; + outputAttachment.m_slotType = PassSlotType::InputOutput; outputAttachment.m_attachment = m_passAttachment; outputAttachment.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::RenderTarget; From 46b9f1934de4f8bb280526104fb3e042d50696a1 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Sun, 18 Apr 2021 23:15:02 -0700 Subject: [PATCH 116/122] Removed commented line --- .../Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp index 78d99de7d6..c72712bce5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp @@ -121,7 +121,6 @@ namespace AZ // create output PassAttachment m_passAttachment = aznew PassAttachment(); m_passAttachment->m_name = "Output"; - //m_passAttachment->m_path = "Output"; AZ::Name attachmentPath(AZStd::string::format("%s.%s", GetPathName().GetCStr(), m_passAttachment->m_name.GetCStr())); m_passAttachment->m_path = attachmentPath; m_passAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient; From 9412078992fe64aa0d91fe3d0eb84e345dba3be5 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Mon, 19 Apr 2021 10:19:03 -0500 Subject: [PATCH 117/122] Fixed issue if the "/Amazon/AzCore/Bootstrap/_assets" or "/Amazon/AzCore/Bootstrap/assets" key is set, then it would append that value to the default asset platform value for the OS --- .../Settings/SettingsRegistryMergeUtils.cpp | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 52085757fe..27f6f222dd 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -506,6 +506,7 @@ namespace AZ::SettingsRegistryMergeUtils void MergeSettingsToRegistry_AddRuntimeFilePaths(SettingsRegistryInterface& registry) { + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; // Binary folder AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory(); registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native()); @@ -514,28 +515,25 @@ namespace AZ::SettingsRegistryMergeUtils AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry); registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native()); - constexpr size_t bufferSize = 64; - auto buffer = AZStd::fixed_string::format("%s/project_path", BootstrapSettingsRootKey); - - AZ::SettingsRegistryInterface::FixedValueString projectPathKey(buffer); + auto projectPathKey = FixedValueString::format("%s/project_path", BootstrapSettingsRootKey); SettingsRegistryInterface::FixedValueString projectPathValue; if (registry.Get(projectPathValue, projectPathKey)) { // Cache folder // Get the name of the asset platform assigned by the bootstrap. First check for platform version such as "windows_assets" // and if that's missing just get "assets". - constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER; - - buffer = AZStd::fixed_string::format("%s/%s_assets", BootstrapSettingsRootKey, platformName); - AZStd::string_view assetPlatformKey(buffer); - // Use the platform codename to retrieve the default asset platform value - SettingsRegistryInterface::FixedValueString assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME); - if (!registry.Get(assetPlatform, assetPlatformKey)) + FixedValueString assetPlatform; + if (auto assetPlatformKey = FixedValueString::format("%s/%s_assets", BootstrapSettingsRootKey, AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER); + !registry.Get(assetPlatform, assetPlatformKey)) { - buffer = AZStd::fixed_string::format("%s/assets", BootstrapSettingsRootKey); - assetPlatformKey = AZStd::string_view(buffer); + assetPlatformKey = FixedValueString::format("%s/assets", BootstrapSettingsRootKey); registry.Get(assetPlatform, assetPlatformKey); } + if (assetPlatform.empty()) + { + // Use the platform codename to retrieve the default asset platform value + assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME); + } // Project path - corresponds to the @devassets@ alias // NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded. @@ -575,8 +573,7 @@ namespace AZ::SettingsRegistryMergeUtils { // Cache: project root - no corresponding fileIO alias, but this is where the asset database lives. // A registry override is accepted using the "project_cache_path" key. - buffer = AZStd::fixed_string::format("%s/project_cache_path", BootstrapSettingsRootKey); - AZStd::string_view projectCacheRootOverrideKey(buffer); + auto projectCacheRootOverrideKey = FixedValueString::format("%s/project_cache_path", BootstrapSettingsRootKey); // Clear path to make sure that the `project_cache_path` value isn't concatenated to the project path path.clear(); if (registry.Get(path.Native(), projectCacheRootOverrideKey)) From febad58c6413bafac48b69d510ba98007c0c986a Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Mon, 19 Apr 2021 10:26:41 -0500 Subject: [PATCH 118/122] LYN-652 to unblock Linux Automated Testing --- Gems/Blast/Editor/Scripts/bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Blast/Editor/Scripts/bootstrap.py b/Gems/Blast/Editor/Scripts/bootstrap.py index c0fd83e64e..8614cb7d1d 100755 --- a/Gems/Blast/Editor/Scripts/bootstrap.py +++ b/Gems/Blast/Editor/Scripts/bootstrap.py @@ -9,5 +9,5 @@ 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. """ -import asset_builder_blast - +# LYN-652 to re-enable the next line +# import asset_builder_blast From 4c2260af97bc770cd26cfad156b776693f0c045b Mon Sep 17 00:00:00 2001 From: AMZN-stankowi Date: Mon, 19 Apr 2021 08:51:52 -0700 Subject: [PATCH 119/122] Lyn 2651 rebased to main (#74) * Helios - LYN-2651 Lerping bones, cleaned up key frame generation for morph targets. Merge from 1.0. --- .../Importers/AssImpAnimationImporter.cpp | 238 ++++++++++-------- .../Importers/AssImpAnimationImporter.h | 2 +- .../EMotionFX/Source/KeyTrackLinearDynamic.h | 2 +- 3 files changed, 140 insertions(+), 102 deletions(-) diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp index 2f71ebcb78..9522512619 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -42,7 +42,108 @@ namespace AZ // Downstream only supports 30 frames per second sample rate. Adjusting to 60 doubles the // length of the animations, they still play back at 30 frames per second. - const double AssImpAnimationImporter::s_defaultTimeStepSampleRate = 1.0 / 30.0; + const double AssImpAnimationImporter::s_defaultTimeStepBetweenFrames = 1.0 / 30.0; + + AZ::u32 GetNumKeyFrames(AZ::u32 keysSize, double duration, double ticksPerSecond) + { + if (AZ::IsClose(ticksPerSecond, 0)) + { + AZ_Warning("AnimationImporter", false, "Animation ticks per second should not be zero, defaulting to %d keyframes for animation.", keysSize); + return keysSize; + } + const double totalTicks = duration / ticksPerSecond; + AZ::u32 numKeys = keysSize; + // +1 because the animation is from [0, duration] - we have a keyframe at the end of the duration which needs to be included + double totalFramesAtDefaultTimeStep = totalTicks / AssImpAnimationImporter::s_defaultTimeStepBetweenFrames + 1; + if (!AZ::IsClose(totalFramesAtDefaultTimeStep, numKeys, 1)) + { + numKeys = AZStd::ceilf(totalFramesAtDefaultTimeStep); + } + return numKeys; + } + + double GetTimeForFrame(AZ::u32 frame, double ticksPerSecond) + { + return frame * AssImpAnimationImporter::s_defaultTimeStepBetweenFrames * ticksPerSecond; + } + + // Helper class to store key data, when translating from AssImp layout to the engine's scene format. + struct KeyData + { + KeyData(float value, float time) : + mValue(value), + mTime(time) + { + + } + + bool operator<(const KeyData& other) const + { + return mTime < other.mTime; + } + + float mValue = 0; + float mTime = 0; + }; + + template + void LerpTemplate(T& start, const T& end, float t) + { + start = start * (1.0f - t) + end * t; + } + + template<> + void LerpTemplate(aiQuaternion& start, const aiQuaternion& end, float t) + { + aiQuaternion::Interpolate(start, start, end, t); + } + + template<> + void LerpTemplate(float& start, const float& end, float t) + { + start = AZ::Lerp(start, end, t); + } + + template + bool SampleKeyFrame(FrameValueType& result, const KeyContainerType& keys, AZ::u32 numKeys, double time, AZ::u32& lastIndex) + { + if (numKeys == 0) + { + AZ_Error("AnimationImporter", numKeys > 0, "Animation key set must have at least 1 key"); + return false; + } + if (numKeys == 1) + { + result = keys[0].mValue; + return true; + } + + while (lastIndex < numKeys - 1 && time >= keys[lastIndex + 1].mTime) + { + ++lastIndex; + } + result = keys[lastIndex].mValue; + if (lastIndex < numKeys - 1) + { + auto nextValue = keys[lastIndex + 1].mValue; + float normalizedTimeBetweenFrames = 0; + if (keys[lastIndex + 1].mTime != keys[lastIndex].mTime) + { + normalizedTimeBetweenFrames = + (time - keys[lastIndex].mTime) / (keys[lastIndex + 1].mTime - keys[lastIndex].mTime); + } + else + { + AZ_Warning("AnimationImporter", false, + "Animation has keys with duplicate time %5.5f, at indices %d and %d. The second will be ignored.", + keys[lastIndex].mTime, + lastIndex, + lastIndex + 1); + } + LerpTemplate(result, nextValue, normalizedTimeBetweenFrames); + } + return true; + } AssImpAnimationImporter::AssImpAnimationImporter() { @@ -199,6 +300,14 @@ namespace AZ for (AZ::u32 animIndex = 0; animIndex < scene->mNumAnimations; ++animIndex) { const aiAnimation* animation = scene->mAnimations[animIndex]; + if (animation->mTicksPerSecond == 0) + { + AZ_Error( + "AnimationImporter", false, + "Animation name %s has a sample rate of 0 ticks per second and cannot be processed.", + animation->mName.C_Str()); + return Events::ProcessingResult::Failure; + } mapAnimationsFunc(animation->mNumChannels, animation->mChannels, animation, boneAnimations); @@ -410,70 +519,38 @@ namespace AZ anim->mNumPositionKeys, anim->mNumRotationKeys, anim->mNumScalingKeys); return Events::ProcessingResult::Failure; } - - auto sampleKeyFrame = [](const auto& keys, AZ::u32 numKeys, double time, AZ::u32& lastIndex) - { - AZ_Error("AnimationImporter", numKeys > 0, "Animation key set must have at least 1 key"); - - if (numKeys == 1) - { - return keys[0].mValue; - } - - auto returnValue = keys[0].mValue; - - for (AZ::u32 keyIndex = lastIndex; keyIndex < numKeys; ++keyIndex) - { - const auto& key = keys[keyIndex]; - lastIndex = keyIndex; - - // We want to return the key that exactly matches the time if possible, otherwise we'll keep track of the previous time - // If we don't find an exact match and end up going past the desired time (or run out of keyframes) then we return the previous key - if (key.mTime < time) - { - returnValue = key.mValue; - } - else if (AZ::IsClose(key.mTime, time)) - { - return key.mValue; - } - else - { - return returnValue; - } - } - - return returnValue; - }; // Resample the animations at a fixed time step. This matches the behaviour of // the previous SDK used. Longer term, this could be data driven, or based on the // smallest time step between key frames. // AssImp has an animation->mTicksPerSecond and animation->mDuration, but those // are less predictable than just using a fixed time step. - const double duration = animation->mDuration / animation->mTicksPerSecond; + // AssImp documentation claims animation->mDuration is the duration of the animation in ticks, but + // not all animations we've tested follow that pattern. Sometimes duration is in seconds. + const AZ::u32 numKeyFrames = GetNumKeyFrames( + AZStd::max(AZStd::max(anim->mNumScalingKeys, anim->mNumPositionKeys), anim->mNumRotationKeys), + animation->mDuration, + animation->mTicksPerSecond); - AZ::u32 numKeyFrames = AZStd::max(AZStd::max(anim->mNumScalingKeys, anim->mNumPositionKeys), anim->mNumRotationKeys); - if (!AZ::IsClose(duration / s_defaultTimeStepSampleRate, numKeyFrames, 1)) - { - double dT = duration / s_defaultTimeStepSampleRate; - numKeyFrames = AZStd::ceilf(dT) + 1; // +1 because the animation is from [0, duration] - we have a keyframe at the end of the duration which needs to be included - } - AZStd::shared_ptr createdAnimationData = AZStd::make_shared(); createdAnimationData->ReserveKeyFrames(numKeyFrames); - createdAnimationData->SetTimeStepBetweenFrames(s_defaultTimeStepSampleRate); + createdAnimationData->SetTimeStepBetweenFrames(s_defaultTimeStepBetweenFrames); AZ::u32 lastScaleIndex = 0; AZ::u32 lastPositionIndex = 0; AZ::u32 lastRotationIndex = 0; for (AZ::u32 frame = 0; frame < numKeyFrames; ++frame) { - double time = frame * s_defaultTimeStepSampleRate * animation->mTicksPerSecond; - aiVector3D scale = sampleKeyFrame(anim->mScalingKeys, anim->mNumScalingKeys, time, lastScaleIndex); - aiVector3D position = sampleKeyFrame(anim->mPositionKeys, anim->mNumPositionKeys, time, lastPositionIndex); - aiQuaternion rotation = sampleKeyFrame(anim->mRotationKeys, anim->mNumRotationKeys, time, lastRotationIndex); + const double time = GetTimeForFrame(frame, animation->mTicksPerSecond); + aiVector3D scale = aiVector3D(1.f, 1.f, 1.f), position = aiVector3D(0.f, 0.f, 0.f); + aiQuaternion rotation(1.f, 0.f, 0.f, 0.f); + if (!SampleKeyFrame(scale, anim->mScalingKeys, anim->mNumScalingKeys, time, lastScaleIndex) || + !SampleKeyFrame(position, anim->mPositionKeys, anim->mNumPositionKeys, time, lastPositionIndex) || + !SampleKeyFrame(rotation, anim->mRotationKeys, anim->mNumRotationKeys, time, lastRotationIndex)) + { + return Events::ProcessingResult::Failure; + } aiMatrix4x4 transform(scale, rotation, position); @@ -520,28 +597,6 @@ namespace AZ // SetTimeStepBetweenFrames set on the animation data // Keyframes. Weights (Values in FBX SDK) per key time. // Keyframes generated for every single frame of the animation. - - // Helper class to store key data, when translating from AssImp layout to the engine's scene format. - struct KeyData - { - KeyData(float weight, float time) : - m_weight(weight), - m_time(time) - { - - } - - bool operator<(const KeyData& other) const - { - return m_time < other.m_time; - } - - // Naming in the previous SDK (FBX SDK) and in the engine's scene format - // doesn't match AssImp's naming convention. - // weight here is the AssImp's name for the data, it was named value in FBX SDK. - float m_weight = 0; - float m_time = 0; - }; typedef AZStd::map> ValueToKeyDataMap; ValueToKeyDataMap valueToKeyDataMap; @@ -562,44 +617,27 @@ namespace AZ { AZStd::shared_ptr morphAnimNode = AZStd::make_shared(); - morphAnimNode->ReserveKeyFrames(animation->mDuration + 1); - morphAnimNode->SetTimeStepBetweenFrames(1.0 / animation->mTicksPerSecond); + + const AZ::u32 numKeyFrames = GetNumKeyFrames(keys.size(), animation->mDuration, animation->mTicksPerSecond); + morphAnimNode->ReserveKeyFrames(numKeyFrames); + morphAnimNode->SetTimeStepBetweenFrames(s_defaultTimeStepBetweenFrames); aiAnimMesh* aiAnimMesh = mesh->mAnimMeshes[meshIdx]; AZStd::string_view nodeName(aiAnimMesh->mName.C_Str()); const AZ::u32 maxKeys = keys.size(); AZ::u32 keyIdx = 0; - for (AZ::u32 time = 0; time <= animation->mDuration; ++time) + for (AZ::u32 frame = 0; frame <= numKeyFrames; ++frame) { - if (keyIdx < maxKeys - 1 && time >= keys[keyIdx+1].m_time) - { - ++keyIdx; - } - float weight_value = keys[keyIdx].m_weight; - if (keyIdx < maxKeys - 1) - { - float nextWeight = keys[keyIdx+1].m_weight; - float normalizedTimeBetweenFrames = 0; + const double time = GetTimeForFrame(frame, animation->mTicksPerSecond); - if (keys[keyIdx + 1].m_time != keys[keyIdx].m_time) - { - normalizedTimeBetweenFrames = - (time - keys[keyIdx].m_time) / (keys[keyIdx + 1].m_time - keys[keyIdx].m_time); - } - else - { - AZ_Warning("AnimationImporter", false, - "Morph target mesh %s has keys with duplicate time, at indices %d and %d. The second will be ignored.", - nodeName.data(), - keyIdx, - keyIdx+1); - } - - // AssImp and FBX both only support linear interpolation for blend shapes. - weight_value = AZ::Lerp(weight_value, nextWeight, normalizedTimeBetweenFrames); + float weight = 0; + if (!SampleKeyFrame(weight, keys, keys.size(), time, keyIdx)) + { + return Events::ProcessingResult::Failure; } - morphAnimNode->AddKeyFrame(weight_value); + + morphAnimNode->AddKeyFrame(weight); } diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h index 72180dea1a..3c06153d04 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h @@ -45,7 +45,7 @@ namespace AZ const aiMeshMorphAnim* meshMorphAnim, const aiMesh* mesh); - static const double s_defaultTimeStepSampleRate; + static const double s_defaultTimeStepBetweenFrames; protected: static const char* s_animationNodeName; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h index 18135e94d6..958cf61183 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h @@ -229,7 +229,7 @@ namespace EMotionFX void MakeLoopable(float fadeTime = 0.3f); /** - * Optimize the keytrack by removing redundent frames. + * Optimize the keytrack by removing redundant frames. * The way this is done is by comparing differences between the resulting curves when removing specific keyframes. * If the error (difference) between those curve before and after keyframe removal is within a given maximum error value, the keyframe can be * safely removed since there will not be much "visual" difference. From 568b31cf1c5453e170f73f74b8ee00826b2d62a8 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Mon, 19 Apr 2021 18:03:28 +0200 Subject: [PATCH 120/122] [LYN-2856] EMotionFX: Creating an Anim Graph snapshot crashes the Editor (#67) Cherry picking bug fix from 1.0 --- .../Components/AnimGraphComponent.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp index 44cc6304a9..9dabade61f 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp @@ -346,13 +346,20 @@ namespace EMotionFX void AnimGraphComponent::CreateSnapshot(bool isAuthoritative) { - AZ_Error("EMotionFX", m_animGraphInstance, "Call create snapshot function only when anim graph is ready in this component."); - m_animGraphInstance->CreateSnapshot(isAuthoritative); - m_animGraphInstance->OnNetworkConnected(); + if (m_animGraphInstance) + { + m_animGraphInstance->CreateSnapshot(isAuthoritative); + m_animGraphInstance->OnNetworkConnected(); - // This will stop the MCore Job schedule update the actor instance and anim graph for authoritative entity. - // After doing so, we will have to update this actor manuelly in the networking update. - m_animGraphInstance->GetActorInstance()->SetIsEnabled(!isAuthoritative); + // This will stop the MCore Job schedule update the actor instance and anim graph for authoritative entity. + // After doing so, we will have to update this actor manually in the networking update. + m_animGraphInstance->GetActorInstance()->SetIsEnabled(!isAuthoritative); + } + else + { + AZ_Error("EMotionFX", false, "Cannot create snapshot as anim graph instance has not been created yet. " + "Please make sure you selected an anim graph in the anim graph component."); + } } void AnimGraphComponent::SetActiveStates(const AZStd::vector& activeStates) From 387dd1e43ae58a2e120b3aef1b091b0b99f6463f Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Mon, 19 Apr 2021 11:09:55 -0500 Subject: [PATCH 121/122] normalizing Linux path --- .../Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py index c60871ac46..ab033dc57f 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -48,7 +48,7 @@ def on_create_jobs(args): def process_file(request): # prepare output folder basePath, _ = os.path.split(request.sourceFile) - outputPath = os.path.join(request.tempDirPath, basePath) + outputPath = os.path.join(request.tempDirPath, basePath).lower() os.makedirs(outputPath, exist_ok=True) # write out a mock file From 5c3e5aa7dbabd80520ffe9f6bb8b0ac699f2c2cc Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Mon, 19 Apr 2021 11:26:15 -0500 Subject: [PATCH 122/122] removing all to_lower() --- .../Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py index ab033dc57f..3b695e3ccd 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -48,14 +48,14 @@ def on_create_jobs(args): def process_file(request): # prepare output folder basePath, _ = os.path.split(request.sourceFile) - outputPath = os.path.join(request.tempDirPath, basePath).lower() + outputPath = os.path.join(request.tempDirPath, basePath) os.makedirs(outputPath, exist_ok=True) # write out a mock file basePath, sourceFile = os.path.split(request.sourceFile) mockFilename = os.path.splitext(sourceFile)[0] + '.mock_asset' mockFilename = os.path.join(basePath, mockFilename) - mockFilename = mockFilename.replace('\\', '/').lower() + mockFilename = mockFilename.replace('\\', '/') tempFilename = os.path.join(request.tempDirPath, mockFilename) # write out a tempFilename like a JSON