diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToActor.py b/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToActor.py index 357067b176..e4150f7af8 100644 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToActor.py +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToActor.py @@ -50,6 +50,7 @@ def NvCloth_AddClothSimulationToActor(): # Constants FRAMES_IN_GAME_MODE = 200 + CLOTH_GEM_ERROR_WARNING_LIST = ["Cloth", "NvCloth", "ClothComponentMesh", "ActorClothSkinning", "ActorClothSkinning", "TangentSpaceHelper", "MeshAssetHelper", "ActorAssetHelper", "ClothDebugDisplay"] helper.init_idle() # 1) Load the level @@ -64,14 +65,16 @@ def NvCloth_AddClothSimulationToActor(): general.idle_wait_frames(FRAMES_IN_GAME_MODE) # 5) Verify there are no errors and warnings in the logs - success_condition = not (section_tracer.has_errors or section_tracer.has_warnings) - Report.result(Tests.no_errors_and_warnings_found, success_condition) - if not success_condition: - if section_tracer.has_warnings: - Report.info(f"Warnings found: {section_tracer.warnings}") - if section_tracer.has_errors: - Report.info(f"Errors found: {section_tracer.errors}") - Report.failure(Tests.no_errors_and_warnings_found) + has_errors_or_warnings = False + for error_msg in section_tracer.errors: + if error_msg.window in CLOTH_GEM_ERROR_WARNING_LIST: + has_errors_or_warnings = True + Report.info(f"Cloth error found: {error_msg}") + for warning_msg in section_tracer.warnings: + if warning_msg.window in CLOTH_GEM_ERROR_WARNING_LIST: + has_errors_or_warnings = True + Report.info(f"Cloth warning found: {warning_msg}") + Report.result(Tests.no_errors_and_warnings_found, not has_errors_or_warnings) # 6) Exit game mode helper.exit_game_mode(Tests.exit_game_mode) diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToMesh.py b/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToMesh.py index 0f9d8448f7..707f745cea 100644 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToMesh.py +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/tests/NvCloth_AddClothSimulationToMesh.py @@ -50,6 +50,7 @@ def NvCloth_AddClothSimulationToMesh(): # Constants FRAMES_IN_GAME_MODE = 200 + CLOTH_GEM_ERROR_WARNING_LIST = ["Cloth", "NvCloth", "ClothComponentMesh", "ActorClothSkinning", "ActorClothSkinning", "TangentSpaceHelper", "MeshAssetHelper", "ActorAssetHelper", "ClothDebugDisplay"] helper.init_idle() # 1) Load the level @@ -64,14 +65,16 @@ def NvCloth_AddClothSimulationToMesh(): general.idle_wait_frames(FRAMES_IN_GAME_MODE) # 5) Verify there are no errors and warnings in the logs - success_condition = not (section_tracer.has_errors or section_tracer.has_warnings) - Report.result(Tests.no_errors_and_warnings_found, success_condition) - if not success_condition: - if section_tracer.has_warnings: - Report.info(f"Warnings found: {section_tracer.warnings}") - if section_tracer.has_errors: - Report.info(f"Errors found: {section_tracer.errors}") - Report.failure(Tests.no_errors_and_warnings_found) + has_errors_or_warnings = False + for error_msg in section_tracer.errors: + if error_msg.window in CLOTH_GEM_ERROR_WARNING_LIST: + has_errors_or_warnings = True + Report.info(f"Cloth error found: {error_msg}") + for warning_msg in section_tracer.warnings: + if warning_msg.window in CLOTH_GEM_ERROR_WARNING_LIST: + has_errors_or_warnings = True + Report.info(f"Cloth warning found: {warning_msg}") + Report.result(Tests.no_errors_and_warnings_found, not has_errors_or_warnings) # 6) Exit game mode helper.exit_game_mode(Tests.exit_game_mode) diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp index ce4a0a2e33..72fd37605a 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.cpp +++ b/Code/Editor/EditorModularViewportCameraComposer.cpp @@ -13,9 +13,32 @@ #include #include #include +#include #include #include +AZ_CVAR( + bool, + ed_cameraPinDefaultOrbit, + true, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "Sets whether the default orbit point moves with the camera or not"); +AZ_CVAR( + bool, + ed_cameraDefaultOrbitAxesOrtho, + true, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "Sets whether to draw the default orbit point as orthographic or not"); +AZ_CVAR( + float, + ed_cameraDefaultOrbitFadeDuration, + 0.5f, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "Sets how long the default orbit point should take to appear and disappear"); + namespace SandboxEditor { static AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() @@ -174,7 +197,7 @@ namespace SandboxEditor return SandboxEditor::CameraScrollSpeed(); }; - const auto pivotFn = [] + const auto pivotFn = []() -> AZStd::optional { // use the manipulator transform as the pivot point AZStd::optional entityPivot; @@ -187,8 +210,7 @@ namespace SandboxEditor return entityPivot->GetTranslation(); } - // otherwise just use the identity - return AZ::Vector3::CreateZero(); + return AZStd::nullopt; }; m_firstPersonFocusCamera = @@ -199,9 +221,26 @@ namespace SandboxEditor m_orbitCamera = AZStd::make_shared(SandboxEditor::CameraOrbitChannelId()); m_orbitCamera->SetPivotFn( - [pivotFn]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) + [this, pivotFn](const AZ::Vector3& position, const AZ::Vector3& direction) { - return pivotFn(); + // return the pivot + if (auto pivot = pivotFn()) + { + return pivot.value(); + } + + // start ticking and drawing (for the default pivot) + AZ::TickBus::Handler::BusConnect(); + AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + + m_defaultOrbiting = true; + // calculate the default orbit point + if (!ed_cameraPinDefaultOrbit || m_orbitCamera->Beginning()) + { + m_defaultOrbitPoint = position + direction * SandboxEditor::CameraDefaultOrbitDistance(); + } + + return m_defaultOrbitPoint; }); m_orbitRotateCamera = AZStd::make_shared(SandboxEditor::CameraOrbitLookChannelId()); @@ -306,4 +345,67 @@ namespace SandboxEditor m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::ClearReferenceFrame); } } + + void EditorModularViewportCameraComposer::OnTick(const float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + const float delta = [duration = &ed_cameraDefaultOrbitFadeDuration, deltaTime] { + if (*duration == 0.0f) { + return 1.0f; + } + return deltaTime / *duration; + }(); + + if (m_defaultOrbiting) + { + m_defaultOrbitOpacity = AZStd::min(m_defaultOrbitOpacity + delta, 1.0f); + } + else + { + m_defaultOrbitOpacity = AZStd::max(m_defaultOrbitOpacity - delta, 0.0f); + if (m_defaultOrbitOpacity == 0.0f) + { + AZ::TickBus::Handler::BusDisconnect(); + AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); + } + } + + m_defaultOrbiting = false; + } + + static void DrawTransformAxis( + AzFramework::DebugDisplayRequests& display, + const AzFramework::CameraState& cameraState, + const AZ::Vector3& pivot, + const float axisLength, + const float alpha) + { + const int prevState = display.GetState(); + + display.DepthWriteOff(); + display.DepthTestOff(); + display.CullOff(); + + const float orthoScale = + ed_cameraDefaultOrbitAxesOrtho ? AzToolsFramework::CalculateScreenToWorldMultiplier(pivot, cameraState) : 1.0f; + + display.SetColor(AZ::Color::CreateFromVector3AndFloat(AZ::Colors::Red.GetAsVector3(), alpha)); + display.DrawLine(pivot, pivot + AZ::Vector3::CreateAxisX() * axisLength * orthoScale); + display.SetColor(AZ::Color::CreateFromVector3AndFloat(AZ::Colors::LawnGreen.GetAsVector3(), alpha)); + display.DrawLine(pivot, pivot + AZ::Vector3::CreateAxisY() * axisLength * orthoScale); + display.SetColor(AZ::Color::CreateFromVector3AndFloat(AZ::Colors::Blue.GetAsVector3(), alpha)); + display.DrawLine(pivot, pivot + AZ::Vector3::CreateAxisZ() * axisLength * orthoScale); + + display.DepthWriteOn(); + display.DepthTestOn(); + display.CullOn(); + + display.SetState(prevState); + } + + void EditorModularViewportCameraComposer::DisplayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + DrawTransformAxis( + debugDisplay, AzToolsFramework::GetCameraState(viewportInfo.m_viewportId), m_defaultOrbitPoint, 1.0f, m_defaultOrbitOpacity); + } } // namespace SandboxEditor diff --git a/Code/Editor/EditorModularViewportCameraComposer.h b/Code/Editor/EditorModularViewportCameraComposer.h index 9cfd6f3554..6cd5df533c 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.h +++ b/Code/Editor/EditorModularViewportCameraComposer.h @@ -9,6 +9,8 @@ #pragma once #include +#include +#include #include #include #include @@ -20,6 +22,8 @@ namespace SandboxEditor class EditorModularViewportCameraComposer : private EditorModularViewportCameraComposerNotificationBus::Handler , private Camera::EditorCameraNotificationBus::Handler + , private AzFramework::ViewportDebugDisplayEventBus::Handler + , private AZ::TickBus::Handler { public: SANDBOX_API explicit EditorModularViewportCameraComposer(AzFramework::ViewportId viewportId); @@ -29,6 +33,12 @@ namespace SandboxEditor SANDBOX_API AZStd::shared_ptr CreateModularViewportCameraController(); private: + // AzFramework::ViewportDebugDisplayEventBus overrides ... + void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + + // AZ::TickBus overrides ... + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + //! Setup all internal camera inputs. void SetupCameras(); @@ -52,5 +62,9 @@ namespace SandboxEditor AZStd::shared_ptr m_orbitFocusCamera; AzFramework::ViewportId m_viewportId; + + float m_defaultOrbitOpacity = 0.0f; //!< The default orbit axes opacity (to fade in and out). + AZ::Vector3 m_defaultOrbitPoint = AZ::Vector3::CreateZero(); //!< The orbit point to use when no entity is selected. + bool m_defaultOrbiting = false; //!< Is the camera default orbiting (orbiting when there's no selected entity). }; } // namespace SandboxEditor diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.cpp b/Code/Editor/EditorPreferencesPageViewportCamera.cpp index 2f6e6b1b9d..c81eac0414 100644 --- a/Code/Editor/EditorPreferencesPageViewportCamera.cpp +++ b/Code/Editor/EditorPreferencesPageViewportCamera.cpp @@ -61,7 +61,7 @@ static AZStd::vector GetEditorInputNames() void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serialize) { serialize.Class() - ->Version(3) + ->Version(4) ->Field("TranslateSpeed", &CameraMovementSettings::m_translateSpeed) ->Field("RotateSpeed", &CameraMovementSettings::m_rotateSpeed) ->Field("BoostMultiplier", &CameraMovementSettings::m_boostMultiplier) @@ -76,9 +76,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial ->Field("OrbitYawRotationInverted", &CameraMovementSettings::m_orbitYawRotationInverted) ->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX) ->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY) - ->Field("DefaultPositionX", &CameraMovementSettings::m_defaultCameraPositionX) - ->Field("DefaultPositionY", &CameraMovementSettings::m_defaultCameraPositionY) - ->Field("DefaultPositionZ", &CameraMovementSettings::m_defaultCameraPositionZ); + ->Field("DefaultPosition", &CameraMovementSettings::m_defaultPosition) + ->Field("DefaultOrbitDistance", &CameraMovementSettings::m_defaultOrbitDistance); serialize.Class() ->Version(2) @@ -159,14 +158,12 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_captureCursorLook, "Camera Capture Look Cursor", "Should the cursor be captured (hidden) while performing free look") ->DataElement( - AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionX, "Default X Camera Position", - "Default X Camera Position when a level is opened") + AZ::Edit::UIHandlers::Vector3, &CameraMovementSettings::m_defaultPosition, "Default Camera Position", + "Default Camera Position when a level is first opened") ->DataElement( - AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionY, "Default Y Camera Position", - "Default Y Camera Position when a level is opened") - ->DataElement( - AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionZ, "Default Z Camera Position", - "Default Z Camera Position when a level is opened"); + AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultOrbitDistance, "Default Orbit Distance", + "The default distance to orbit about when there is no entity selected") + ->Attribute(AZ::Edit::Attributes::Min, minValue); editContext->Class("Camera Input Settings", "") ->DataElement( @@ -283,12 +280,8 @@ void CEditorPreferencesPage_ViewportCamera::OnApply() SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted); SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX); SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY); - SandboxEditor::SetDefaultCameraEditorPosition( - AZ::Vector3( - m_cameraMovementSettings.m_defaultCameraPositionX, - m_cameraMovementSettings.m_defaultCameraPositionY, - m_cameraMovementSettings.m_defaultCameraPositionZ - )); + SandboxEditor::SetCameraDefaultEditorPosition(m_cameraMovementSettings.m_defaultPosition); + SandboxEditor::SetCameraDefaultOrbitDistance(m_cameraMovementSettings.m_defaultOrbitDistance); SandboxEditor::SetCameraTranslateForwardChannelId(m_cameraInputSettings.m_translateForwardChannelId); SandboxEditor::SetCameraTranslateBackwardChannelId(m_cameraInputSettings.m_translateBackwardChannelId); @@ -325,11 +318,8 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings() m_cameraMovementSettings.m_orbitYawRotationInverted = SandboxEditor::CameraOrbitYawRotationInverted(); m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX(); m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY(); - - AZ::Vector3 defaultCameraPosition = SandboxEditor::DefaultEditorCameraPosition(); - m_cameraMovementSettings.m_defaultCameraPositionX = defaultCameraPosition.GetX(); - m_cameraMovementSettings.m_defaultCameraPositionY = defaultCameraPosition.GetY(); - m_cameraMovementSettings.m_defaultCameraPositionZ = defaultCameraPosition.GetZ(); + m_cameraMovementSettings.m_defaultPosition = SandboxEditor::CameraDefaultEditorPosition(); + m_cameraMovementSettings.m_defaultOrbitDistance = SandboxEditor::CameraDefaultOrbitDistance(); m_cameraInputSettings.m_translateForwardChannelId = SandboxEditor::CameraTranslateForwardChannelId().GetName(); m_cameraInputSettings.m_translateBackwardChannelId = SandboxEditor::CameraTranslateBackwardChannelId().GetName(); diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.h b/Code/Editor/EditorPreferencesPageViewportCamera.h index a2705bfd24..41816de51c 100644 --- a/Code/Editor/EditorPreferencesPageViewportCamera.h +++ b/Code/Editor/EditorPreferencesPageViewportCamera.h @@ -9,9 +9,12 @@ #pragma once #include "Include/IPreferencesPage.h" + +#include #include #include #include + #include inline AZ::Crc32 EditorPropertyVisibility(const bool enabled) @@ -43,6 +46,7 @@ private: { AZ_TYPE_INFO(CameraMovementSettings, "{60B8C07E-5F48-4171-A50B-F45558B5CCA1}") + AZ::Vector3 m_defaultPosition; float m_translateSpeed; float m_rotateSpeed; float m_scrollSpeed; @@ -50,16 +54,14 @@ private: float m_panSpeed; float m_boostMultiplier; float m_rotateSmoothness; - bool m_rotateSmoothing; float m_translateSmoothness; - bool m_translateSmoothing; + float m_defaultOrbitDistance; bool m_captureCursorLook; bool m_orbitYawRotationInverted; bool m_panInvertedX; bool m_panInvertedY; - float m_defaultCameraPositionX; - float m_defaultCameraPositionY; - float m_defaultCameraPositionZ; + bool m_rotateSmoothing; + bool m_translateSmoothing; AZ::Crc32 RotateSmoothingVisibility() const { diff --git a/Code/Editor/EditorViewportSettings.cpp b/Code/Editor/EditorViewportSettings.cpp index 8f2be1de6c..ae188c7d98 100644 --- a/Code/Editor/EditorViewportSettings.cpp +++ b/Code/Editor/EditorViewportSettings.cpp @@ -38,6 +38,7 @@ namespace SandboxEditor constexpr AZStd::string_view CameraTranslateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/TranslateSmoothing"; constexpr AZStd::string_view CameraRotateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/RotateSmoothing"; constexpr AZStd::string_view CameraCaptureCursorLookSetting = "/Amazon/Preferences/Editor/Camera/CaptureCursorLook"; + constexpr AZStd::string_view CameraDefaultOrbitDistanceSetting = "/Amazon/Preferences/Editor/Camera/DefaultOrbitDistance"; constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId"; constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId"; constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId"; @@ -114,15 +115,15 @@ namespace SandboxEditor return AZStd::make_unique(); } - AZ::Vector3 DefaultEditorCameraPosition() + AZ::Vector3 CameraDefaultEditorPosition() { - float xPosition = aznumeric_cast(GetRegistry(CameraDefaultStartingPositionX, 0.0)); - float yPosition = aznumeric_cast(GetRegistry(CameraDefaultStartingPositionY, -10.0)); - float zPosition = aznumeric_cast(GetRegistry(CameraDefaultStartingPositionZ, 4.0)); - return AZ::Vector3(xPosition, yPosition, zPosition); + return AZ::Vector3( + aznumeric_cast(GetRegistry(CameraDefaultStartingPositionX, 0.0)), + aznumeric_cast(GetRegistry(CameraDefaultStartingPositionY, -10.0)), + aznumeric_cast(GetRegistry(CameraDefaultStartingPositionZ, 4.0))); } - void SetDefaultCameraEditorPosition(const AZ::Vector3 defaultCameraPosition) + void SetCameraDefaultEditorPosition(const AZ::Vector3& defaultCameraPosition) { SetRegistry(CameraDefaultStartingPositionX, defaultCameraPosition.GetX()); SetRegistry(CameraDefaultStartingPositionY, defaultCameraPosition.GetY()); @@ -359,6 +360,16 @@ namespace SandboxEditor SetRegistry(CameraCaptureCursorLookSetting, capture); } + float CameraDefaultOrbitDistance() + { + return aznumeric_cast(GetRegistry(CameraDefaultOrbitDistanceSetting, 20.0)); + } + + void SetCameraDefaultOrbitDistance(const float distance) + { + SetRegistry(CameraDefaultOrbitDistanceSetting, distance); + } + AzFramework::InputChannelId CameraTranslateForwardChannelId() { return AzFramework::InputChannelId( diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h index 9c3f0a46e5..fe1253ed0c 100644 --- a/Code/Editor/EditorViewportSettings.h +++ b/Code/Editor/EditorViewportSettings.h @@ -33,9 +33,6 @@ namespace SandboxEditor //! event will fire when a value in the settings registry (editorpreferences.setreg) is modified. SANDBOX_API AZStd::unique_ptr CreateEditorViewportSettingsCallbacks(); - SANDBOX_API AZ::Vector3 DefaultEditorCameraPosition(); - SANDBOX_API void SetDefaultCameraEditorPosition(AZ::Vector3 defaultCameraPosition); - SANDBOX_API AZ::u64 MaxItemsShownInAssetBrowserSearch(); SANDBOX_API void SetMaxItemsShownInAssetBrowserSearch(AZ::u64 numberOfItemsShown); @@ -105,6 +102,12 @@ namespace SandboxEditor SANDBOX_API bool CameraCaptureCursorForLook(); SANDBOX_API void SetCameraCaptureCursorForLook(bool capture); + SANDBOX_API AZ::Vector3 CameraDefaultEditorPosition(); + SANDBOX_API void SetCameraDefaultEditorPosition(const AZ::Vector3& position); + + SANDBOX_API float CameraDefaultOrbitDistance(); + SANDBOX_API void SetCameraDefaultOrbitDistance(float distance); + SANDBOX_API AzFramework::InputChannelId CameraTranslateForwardChannelId(); SANDBOX_API void SetCameraTranslateForwardChannelId(AZStd::string_view cameraTranslateForwardId); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 8e6983a9d7..290f0fd17f 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -620,9 +620,9 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) break; case eNotify_OnEndNewScene: - PopDisableRendering(); - { + PopDisableRendering(); + Matrix34 viewTM; viewTM.SetIdentity(); @@ -638,9 +638,9 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) break; case eNotify_OnEndTerrainCreate: - PopDisableRendering(); - { + PopDisableRendering(); + Matrix34 viewTM; viewTM.SetIdentity(); @@ -2021,10 +2021,6 @@ void EditorViewportWidget::SetDefaultCamera() GetViewManager()->SetCameraObjectId(GUID_NULL); SetName(m_defaultViewName); - // Set the default Editor Camera position. - m_defaultViewTM.SetTranslation(Vec3(m_editorViewportSettings.DefaultEditorCameraPosition())); - SetViewTM(m_defaultViewTM); - // Synchronize the configured editor viewport FOV to the default camera if (m_viewPane) { @@ -2041,6 +2037,10 @@ void EditorViewportWidget::SetDefaultCamera() atomViewportRequests->PushView(contextName, m_defaultView); } + // Set the default Editor Camera position. + m_defaultViewTM.SetTranslation(Vec3(m_editorViewportSettings.DefaultEditorCameraPosition())); + SetViewTM(m_defaultViewTM); + PostCameraSet(); } @@ -2527,7 +2527,7 @@ bool EditorViewportSettings::StickySelectEnabled() const AZ::Vector3 EditorViewportSettings::DefaultEditorCameraPosition() const { - return SandboxEditor::DefaultEditorCameraPosition(); + return SandboxEditor::CameraDefaultEditorPosition(); } AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index ddee63e191..26c9db64aa 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -806,12 +806,20 @@ namespace AzFramework [[maybe_unused]] float scrollDelta, [[maybe_unused]] float deltaTime) { + const auto pivot = m_pivotFn(); + + if (!pivot.has_value()) + { + EndActivation(); + return targetCamera; + } + if (Beginning()) { // as the camera starts, record the camera we would like to end up as - m_nextCamera.m_offset = m_offsetFn(m_pivotFn().GetDistance(targetCamera.Translation())); + m_nextCamera.m_offset = m_offsetFn(pivot.value().GetDistance(targetCamera.Translation())); const auto angles = - EulerAngles(AZ::Matrix3x3::CreateFromMatrix3x4(AZ::Matrix3x4::CreateLookAt(targetCamera.Translation(), m_pivotFn()))); + EulerAngles(AZ::Matrix3x3::CreateFromMatrix3x4(AZ::Matrix3x4::CreateLookAt(targetCamera.Translation(), pivot.value()))); m_nextCamera.m_pitch = angles.GetX(); m_nextCamera.m_yaw = angles.GetZ(); m_nextCamera.m_pivot = targetCamera.m_pivot; diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 2b7cc3ea9e..2d02bb0b6d 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -651,7 +651,7 @@ namespace AzFramework class FocusCameraInput : public CameraInput { public: - using PivotFn = AZStd::function; + using PivotFn = AZStd::function()>; FocusCameraInput(const InputChannelId& focusChannelId, FocusOffsetFn offsetFn); diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp index c6f481b65b..a3381dabb8 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include @@ -24,14 +26,20 @@ namespace AzFramework::AssetSystem::Platform AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory }; // In Mac the Editor and game is within a bundle, so the path to the sibling app // has to go up from the Contents/MacOS folder the binary is in - assetProcessorPath /= "../../../AssetProcessor.app"; + assetProcessorPath /= "../../../AssetProcessor.app/Contents/MacOS/AssetProcessor"; assetProcessorPath = assetProcessorPath.LexicallyNormal(); if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { - // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. - assetProcessorPath = - AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_TRAIT_OS_PLATFORM_NAME / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app"; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + if (AZ::IO::FixedMaxPath installedBinariesPath; + settingsRegistry->Get(installedBinariesPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. + assetProcessorPath = AZ::IO::FixedMaxPath{ engineRoot } / installedBinariesPath / "AssetProcessor.app/Contents/MacOS/AssetProcessor"; + } + } if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { @@ -39,23 +47,21 @@ namespace AzFramework::AssetSystem::Platform } } - auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str()); + AZStd::string commandLineParams; // Add the engine path to the launch command if not empty if (!engineRoot.empty()) { - fullLaunchCommand += R"( --engine-path=")"; - fullLaunchCommand += engineRoot; - fullLaunchCommand += '"'; + commandLineParams += AZStd::string::format("\"--engine-path=\"%s\"\"", engineRoot.data()); } - // Add the active project path to the launch command if not empty if (!projectPath.empty()) { - fullLaunchCommand += R"( --project-path=")"; - fullLaunchCommand += projectPath; - fullLaunchCommand += '"'; + commandLineParams += AZStd::string::format(" \"--regset=/Amazon/AzCore/Bootstrap/project_path=\"%s\"\"", projectPath.data()); } - return system(fullLaunchCommand.c_str()) == 0; + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + processLaunchInfo.m_processExecutableString = AZStd::move(assetProcessorPath.Native()); + processLaunchInfo.m_commandlineParameters = commandLineParams; + return AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 4048156b60..ee1ec49456 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -40,9 +40,9 @@ namespace AzToolsFramework QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QModelIndex parent(const QModelIndex& child) const override; QModelIndex sibling(int row, int column, const QModelIndex& idx) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; protected: - int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; //////////////////////////////////////////////////////////////////// @@ -55,7 +55,7 @@ namespace AzToolsFramework private slots: void SourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); private: - AZ::u64 m_numberOfItemsDisplayed = 0; + AZ::u64 m_numberOfItemsDisplayed = 50; int m_displayedItemsCounter = 0; QPointer m_filterModel; QMap m_indexMap; diff --git a/Code/Framework/AzToolsFramework/Tests/UI/AssetBrowserTests.cpp b/Code/Framework/AzToolsFramework/Tests/UI/AssetBrowserTests.cpp new file mode 100644 index 0000000000..ae5ea5f0ae --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/UI/AssetBrowserTests.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace UnitTest +{ + // Test fixture for the AssetBrowser model that uses a QAbstractItemModelTester to validate the state of the model + // when QAbstractItemModel signals fire. Tests will exit with a fatal error if an invalid state is detected. + class AssetBrowserTest + : public ToolsApplicationFixture + , public testing::WithParamInterface + { + protected: + enum class AssetEntryType + { + Root, + Folder, + Source, + Product + }; + + enum class FolderType + { + Root, + File + }; + + void SetUpEditorFixtureImpl() override; + void TearDownEditorFixtureImpl() override; + + //! Creates a Mock Scan Folder + void AddScanFolder(AZ::s64 folderID, AZStd::string folderPath, AZStd::string displayName, FolderType folderType = FolderType::File); + + //! Creates a Source entry from a mock file + AZ::Uuid CreateSourceEntry( + AZ::s64 fileID, AZ::s64 parentFolderID, AZStd::string filename, AssetEntryType sourceType = AssetEntryType::Source); + + //! Creates a product from a given sourceEntry + void CreateProduct(AZ::s64 productID, AZ::Uuid sourceUuid, AZStd::string productName); + + void SetupAssetBrowser(); + void PrintModel(const QAbstractItemModel* model, AZStd::function printer); + QModelIndex GetModelIndex(const QAbstractItemModel* model, int targetDepth, int row = 0); + AZStd::shared_ptr GetRootEntry(); + AZStd::vector GetVectorFromFormattedString(const QString& formattedString); + + protected: + QString m_assetBrowserHierarchy = QString(); + + AZStd::unique_ptr m_searchWidget; + AZStd::unique_ptr m_assetBrowserComponent; + + AZStd::unique_ptr m_filterModel; + AZStd::unique_ptr m_tableModel; + + AZStd::unique_ptr m_modelTesterAssetBrowser; + AZStd::unique_ptr m_modelTesterFilterModel; + AZStd::unique_ptr m_modelTesterTableModel; + + QVector m_folderIds = { 13, 14, 15 }; + QVector m_sourceIDs = { 1, 2, 3, 4, 5 }; + QVector m_productIDs = { 1, 2, 3, 4, 5 }; + }; + + void AssetBrowserTest::SetUpEditorFixtureImpl() + { + GetApplication()->RegisterComponentDescriptor(AzToolsFramework::EditorEntityContextComponent::CreateDescriptor()); + + m_assetBrowserComponent = AZStd::make_unique(); + m_assetBrowserComponent->Activate(); + + m_filterModel = AZStd::make_unique(); + m_tableModel = AZStd::make_unique(); + + m_filterModel->setSourceModel(m_assetBrowserComponent->GetAssetBrowserModel()); + m_tableModel->setSourceModel(m_filterModel.get()); + + m_modelTesterAssetBrowser = AZStd::make_unique(m_assetBrowserComponent->GetAssetBrowserModel()); + m_modelTesterFilterModel = AZStd::make_unique(m_filterModel.get()); + m_modelTesterTableModel = AZStd::make_unique(m_tableModel.get()); + m_searchWidget = AZStd::make_unique(); + + // Setup String filters + m_searchWidget->Setup(true, true); + m_filterModel->SetFilter(m_searchWidget->GetFilter()); + + SetupAssetBrowser(); + } + + void AssetBrowserTest::TearDownEditorFixtureImpl() + { + m_modelTesterAssetBrowser.reset(); + m_modelTesterFilterModel.reset(); + m_modelTesterTableModel.reset(); + + m_tableModel.reset(); + m_filterModel.reset(); + m_assetBrowserComponent->Deactivate(); + + m_assetBrowserComponent.reset(); + m_searchWidget.reset(); + } + + void AssetBrowserTest::AddScanFolder( + AZ::s64 folderID, AZStd::string folderPath, AZStd::string displayName, FolderType folderType /*= FolderType::File*/) + { + AzToolsFramework::AssetDatabase::ScanFolderDatabaseEntry scanFolder = AzToolsFramework::AssetDatabase::ScanFolderDatabaseEntry(); + scanFolder.m_scanFolderID = folderID; + scanFolder.m_scanFolder = folderPath; + scanFolder.m_displayName = displayName; + scanFolder.m_isRoot = folderType == FolderType::Root; + GetRootEntry()->AddScanFolder(scanFolder); + } + + AZ::Uuid AssetBrowserTest::CreateSourceEntry( + AZ::s64 fileID, AZ::s64 parentFolderID, AZStd::string filename, AssetEntryType sourceType /*= AssetEntryType::Source*/) + { + AzToolsFramework::AssetDatabase::FileDatabaseEntry entry = AzToolsFramework::AssetDatabase::FileDatabaseEntry(); + entry.m_scanFolderPK = parentFolderID; + entry.m_fileID = fileID; + entry.m_fileName = filename; + entry.m_isFolder = sourceType == AssetEntryType::Folder; + GetRootEntry()->AddFile(entry); + + if (!entry.m_isFolder) + { + AzToolsFramework::AssetBrowser::SourceWithFileID entrySource = AzToolsFramework::AssetBrowser::SourceWithFileID(); + entrySource.first = entry.m_fileID; + entrySource.second = AzToolsFramework::AssetDatabase::SourceDatabaseEntry(); + entrySource.second.m_scanFolderPK = parentFolderID; + entrySource.second.m_sourceName = filename; + entrySource.second.m_sourceID = fileID; + entrySource.second.m_sourceGuid = AZ::Uuid::CreateRandom(); + + GetRootEntry()->AddSource(entrySource); + + return entrySource.second.m_sourceGuid; + } + + return AZ::Uuid::CreateNull(); + } + + void AssetBrowserTest::CreateProduct(AZ::s64 productID, AZ::Uuid sourceUuid, AZStd::string productName) + { + AzToolsFramework::AssetBrowser::ProductWithUuid product = AzToolsFramework::AssetBrowser::ProductWithUuid(); + product.first = sourceUuid; + product.second = AzToolsFramework::AssetDatabase::ProductDatabaseEntry(); + product.second.m_productID = productID; + + product.second.m_subID = aznumeric_cast(productID); + product.second.m_productName = productName; + + GetRootEntry()->AddProduct(product); + } + + void AssetBrowserTest::SetupAssetBrowser() + { + // RootEntries : 1 | Folders : 4 | SourceEntries : 5 | ProductEntries : 9 + m_assetBrowserHierarchy = R"( + D: + \ + dev + o3de + GameProject + Assets + Source_1 + Product_1_1 + Product_1_0 + Source_0 + Product_0_3 + Product_0_2 + Product_0_1 + Product_0_0 + Scripts + Source_3 + Source_2 + Product_2_2 + Product_2_1 + Product_2_0 + Misc + Source_4 + Product_4_2 + Product_4_1 + Product_4_0 )"; + + namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; + + AddScanFolder(m_folderIds.at(2), "D:/dev/o3de/GameProject/Misc", "Misc"); + AZ::Uuid sourceUuid_4 = CreateSourceEntry(m_sourceIDs.at(4), m_folderIds.at(2), "Source_4"); + CreateProduct(m_productIDs.at(0), sourceUuid_4, "Product_4_0"); + CreateProduct(m_productIDs.at(1), sourceUuid_4, "Product_4_1"); + CreateProduct(m_productIDs.at(2), sourceUuid_4, "Product_4_2"); + + AddScanFolder(m_folderIds.at(1), "D:/dev/o3de/GameProject/Scripts", "Scripts"); + + AZ::Uuid sourceUuid_2 = CreateSourceEntry(m_sourceIDs.at(2), m_folderIds.at(1), "Source_2"); + CreateProduct(m_productIDs.at(0), sourceUuid_2, "Product_2_0"); + CreateProduct(m_productIDs.at(1), sourceUuid_2, "Product_2_1"); + CreateProduct(m_productIDs.at(2), sourceUuid_2, "Product_2_2"); + + CreateSourceEntry(m_sourceIDs.at(3), m_folderIds.at(1), "Source_3"); + + AddScanFolder(m_folderIds.at(0), "D:/dev/o3de/GameProject/Assets", "Assets"); + + AZ::Uuid sourceUuid_0 = CreateSourceEntry(m_sourceIDs.at(0), m_folderIds.at(0), "Source_0"); + CreateProduct(m_productIDs.at(0), sourceUuid_0, "Product_0_0"); + CreateProduct(m_productIDs.at(1), sourceUuid_0, "Product_0_1"); + CreateProduct(m_productIDs.at(2), sourceUuid_0, "Product_0_2"); + CreateProduct(m_productIDs.at(3), sourceUuid_0, "Product_0_3"); + + AZ::Uuid sourceUuid_1 = CreateSourceEntry(m_sourceIDs.at(1), m_folderIds.at(0), "Source_1"); + CreateProduct(m_productIDs.at(0), sourceUuid_1, "Product_1_0"); + CreateProduct(m_productIDs.at(1), sourceUuid_1, "Product_1_1"); + } + + void AssetBrowserTest::PrintModel(const QAbstractItemModel* model, AZStd::function printer) + { + AZStd::deque> indices; + indices.push_back({ model->index(0, 0), 0 }); + while (!indices.empty()) + { + auto [index, depth] = indices.front(); + indices.pop_front(); + + QString indentString; + for (int i = 0; i < depth; ++i) + { + indentString += " "; + } + const QString message = indentString + index.data(Qt::DisplayRole).toString(); + printer(message); + + for (int i = 0; i < model->rowCount(index); ++i) + { + indices.emplace_front(model->index(i, 0, index), depth + 1); + } + } + } + + QModelIndex AssetBrowserTest::GetModelIndex(const QAbstractItemModel* model, int targetDepth, int row) + { + AZStd::deque> indices; + indices.push_back({ model->index(0, 0), 0 }); + while (!indices.empty()) + { + auto [index, depth] = indices.front(); + indices.pop_front(); + + for (int i = 0; i < model->rowCount(index); ++i) + { + if (depth + 1 == targetDepth && row == i) + { + return model->index(i, 0, index); + } + indices.emplace_front(model->index(i, 0, index), depth + 1); + } + } + return QModelIndex(); + } + + AZStd::shared_ptr AssetBrowserTest::GetRootEntry() + { + return m_assetBrowserComponent->GetAssetBrowserModel()->GetRootEntry(); + } + + AZStd::vector AssetBrowserTest::GetVectorFromFormattedString(const QString& formattedString) + { + AZStd::vector hierarchySections; + QStringList splittedList = formattedString.split('\n', Qt::SkipEmptyParts); + + for (auto& str : splittedList) + { + str.replace(" ", ""); + hierarchySections.push_back(str); + } + return hierarchySections; + } + + TEST_F(AssetBrowserTest, CheckCorrectNumberOfEntriesInTableView) + { + m_filterModel->FilterUpdatedSlotImmediate(); + const int tableViewRowcount = m_tableModel->rowCount(); + + // RowCount should be 17 -> 5 SourceEntries + 12 ProductEntries) + EXPECT_EQ(tableViewRowcount, 17); + } + + TEST_F(AssetBrowserTest, CheckCorrectNumberOfEntriesInTableViewAfterStringFilter) + { + /* + *-Source_1 + * | + * |-product_1_0 + * |-product_1_1 + * + * + * Matching entries = 3 + */ + + // Apply string filter + m_searchWidget->SetTextFilter(QString("source_1")); + m_filterModel->FilterUpdatedSlotImmediate(); + + const int tableViewRowcount = m_tableModel->rowCount(); + EXPECT_EQ(tableViewRowcount, 3); + } + + TEST_F(AssetBrowserTest, CheckScanFolderAddition) + { + EXPECT_EQ(m_assetBrowserComponent->GetAssetBrowserModel()->rowCount(), 1); + const int newFolderId = 20; + AddScanFolder(newFolderId, "E:/TestFolder/TestFolder2", "TestFolder"); + + // Since the folder is empty it shouldn't be added to the model. + EXPECT_EQ(m_assetBrowserComponent->GetAssetBrowserModel()->rowCount(), 1); + + CreateSourceEntry(123, newFolderId, "DummyFile"); + + // When we add a file to the folder it should be added to the model + EXPECT_EQ(m_assetBrowserComponent->GetAssetBrowserModel()->rowCount(), 2); + } + +} // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index 008c09188b..d597c9b570 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -123,6 +123,7 @@ set(FILES UI/EntityIdQLineEditTests.cpp UI/EntityOutlinerTests.cpp UI/EntityPropertyEditorTests.cpp + UI/AssetBrowserTests.cpp UndoStack.cpp Viewport/ClusterTests.cpp Viewport/ViewportEditorModeTests.cpp diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 5c9ee68e27..550a67bc49 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -76,6 +76,12 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC Legacy::CrySystem ) + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + set(server_runtime_dependencies + Legacy::CrySystem + ) + endif() + endif() ################################################################################ diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index 948977d02a..dd29209b24 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -1121,8 +1121,8 @@ inline ISystem* GetISystem() // Description: // This function must be called once by each module at the beginning, to setup global pointers. -extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, const char* moduleName); -extern "C" AZ_DLL_EXPORT void ModuleShutdownISystem(ISystem* pSystem); +void ModuleInitISystem(ISystem* pSystem, const char* moduleName); +void ModuleShutdownISystem(ISystem* pSystem); extern "C" AZ_DLL_EXPORT void InjectEnvironment(void* env); extern "C" AZ_DLL_EXPORT void DetachEnvironment(); diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index a68a5150db..845a1101a4 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -74,7 +74,7 @@ void InitCRTHandlers() {} ////////////////////////////////////////////////////////////////////////// // This is an entry to DLL initialization function that must be called for each loaded module ////////////////////////////////////////////////////////////////////////// -extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, [[maybe_unused]] const char* moduleName) +void ModuleInitISystem(ISystem* pSystem, [[maybe_unused]] const char* moduleName) { if (gEnv) // Already registered. { @@ -96,7 +96,7 @@ extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, [[maybe_unused } // if pSystem } -extern "C" AZ_DLL_EXPORT void ModuleShutdownISystem([[maybe_unused]] ISystem* pSystem) +void ModuleShutdownISystem([[maybe_unused]] ISystem* pSystem) { // Unregister with AZ environment. AZ::Environment::Detach(); diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index ac0683cf1b..99cc92ee6a 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -173,8 +173,6 @@ void CryEngineSignalHandler(int signal) ////////////////////////////////////////////////////////////////////////// #if defined(WIN32) || defined(LINUX) || defined(APPLE) -# define DLL_MODULE_INIT_ISYSTEM "ModuleInitISystem" -# define DLL_MODULE_SHUTDOWN_ISYSTEM "ModuleShutdownISystem" # define DLL_INITFUNC_RENDERER "PackageRenderConstructor" # define DLL_INITFUNC_SOUND "CreateSoundSystem" # define DLL_INITFUNC_FONT "CreateCryFontInterface" @@ -188,8 +186,6 @@ void CryEngineSignalHandler(int signal) #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #else -# define DLL_MODULE_INIT_ISYSTEM (LPCSTR)2 -# define DLL_MODULE_SHUTDOWN_ISYSTEM (LPCSTR)3 # define DLL_INITFUNC_RENDERER (LPCSTR)1 # define DLL_INITFUNC_RENDERER (LPCSTR)1 # define DLL_INITFUNC_SOUND (LPCSTR)1 @@ -445,18 +441,6 @@ AZStd::unique_ptr CSystem::LoadDLL(const char* dllName) return handle; } - ////////////////////////////////////////////////////////////////////////// - // After loading DLL initialize it by calling ModuleInitISystem - ////////////////////////////////////////////////////////////////////////// - AZStd::string moduleName = PathUtil::GetFileName(dllName); - - typedef void*(*PtrFunc_ModuleInitISystem)(ISystem* pSystem, const char* moduleName); - PtrFunc_ModuleInitISystem pfnModuleInitISystem = handle->GetFunction(DLL_MODULE_INIT_ISYSTEM); - if (pfnModuleInitISystem) - { - pfnModuleInitISystem(this, moduleName.c_str()); - } - return handle; } @@ -497,13 +481,6 @@ void CSystem::ShutdownModuleLibraries() #if !defined(AZ_MONOLITHIC_BUILD) for (auto iterator = m_moduleDLLHandles.begin(); iterator != m_moduleDLLHandles.end(); ++iterator) { - typedef void*( * PtrFunc_ModuleShutdownISystem )(ISystem* pSystem); - - PtrFunc_ModuleShutdownISystem pfnModuleShutdownISystem = iterator->second->GetFunction(DLL_MODULE_SHUTDOWN_ISYSTEM); - if (pfnModuleShutdownISystem) - { - pfnModuleShutdownISystem(this); - } if (iterator->second->IsLoaded()) { iterator->second->Unload(); diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 9f60a9dd8d..22c61d3f22 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -333,11 +333,6 @@ void CXConsole::Init(ISystem* pSystem) m_nLoadingBackTexID = -1; - if (gEnv->IsDedicated()) - { - m_bConsoleActive = true; - } - REGISTER_COMMAND("ConsoleShow", &ConsoleShow, VF_NULL, "Opens the console"); REGISTER_COMMAND("ConsoleHide", &ConsoleHide, VF_NULL, "Closes the console"); diff --git a/Code/Tools/AssetProcessor/native/tests/AssetProcessorTest.h b/Code/Tools/AssetProcessor/native/tests/AssetProcessorTest.h index 719b04610c..8f26155fd3 100644 --- a/Code/Tools/AssetProcessor/native/tests/AssetProcessorTest.h +++ b/Code/Tools/AssetProcessor/native/tests/AssetProcessorTest.h @@ -25,7 +25,7 @@ namespace AssetProcessor : public ::testing::Test { protected: - UnitTestUtils::AssertAbsorber* m_errorAbsorber; + AZStd::unique_ptr m_errorAbsorber{}; FileStatePassthrough m_fileStateCache; void SetUp() override @@ -40,7 +40,7 @@ namespace AssetProcessor m_ownsSysAllocator = true; AZ::AllocatorInstance::Create(); } - m_errorAbsorber = new UnitTestUtils::AssertAbsorber(); + m_errorAbsorber = AZStd::make_unique(); m_application = AZStd::make_unique(); @@ -62,8 +62,8 @@ namespace AssetProcessor AssetUtilities::ResetAssetRoot(); m_application.reset(); - delete m_errorAbsorber; - m_errorAbsorber = nullptr; + m_errorAbsorber.reset(); + if (m_ownsSysAllocator) { AZ::AllocatorInstance::Destroy(); diff --git a/Code/Tools/BundleLauncher/O3DE_SDK_Launcher.cpp b/Code/Tools/BundleLauncher/O3DE_SDK_Launcher.cpp index 0c362ac829..4dd7e184e9 100644 --- a/Code/Tools/BundleLauncher/O3DE_SDK_Launcher.cpp +++ b/Code/Tools/BundleLauncher/O3DE_SDK_Launcher.cpp @@ -49,6 +49,12 @@ int main(int argc, char* argv[]) AZStd::unique_ptr shellProcess(AzFramework::ProcessWatcher::LaunchProcess(shellProcessLaunch, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE)); shellProcess->WaitForProcessToExit(120); shellProcess.reset(); + + parameters = AZStd::string::format("-c \"%s/scripts/o3de.sh register --this-engine\"", enginePath.c_str()); + shellProcessLaunch.m_commandlineParameters = parameters; + shellProcess.reset(AzFramework::ProcessWatcher::LaunchProcess(shellProcessLaunch, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE)); + shellProcess->WaitForProcessToExit(120); + shellProcess.reset(); AZ::IO::FixedMaxPath projectManagerPath = installedBinariesFolder/"o3de.app"/"Contents"/"MacOS"/"o3de"; AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp index 0d66009d90..e901d807b4 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp @@ -10,6 +10,8 @@ #include #include +#include + namespace O3DE::ProjectManager { namespace ProjectUtils @@ -94,5 +96,10 @@ namespace O3DE::ProjectManager QProcessEnvironment::systemEnvironment(), QObject::tr("Running get_python script...")); } + + AZ::IO::FixedMaxPath GetEditorDirectory() + { + return AZ::Utils::GetExecutableDirectory(); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp index e36f6cd0c8..b768200398 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + namespace O3DE::ProjectManager { namespace ProjectUtils @@ -104,5 +107,35 @@ namespace O3DE::ProjectManager QProcessEnvironment::systemEnvironment(), QObject::tr("Running get_python script...")); } + + AZ::IO::FixedMaxPath GetEditorDirectory() + { + AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory(); + AZ::IO::FixedMaxPath editorPath{ executableDirectory }; + editorPath /= "../../../Editor.app/Contents/MacOS"; + editorPath = editorPath.LexicallyNormal(); + if (!AZ::IO::SystemFile::IsDirectory(editorPath.c_str())) + { + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + if (AZ::IO::FixedMaxPath installedBinariesPath; + settingsRegistry->Get(installedBinariesPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + if (AZ::IO::FixedMaxPath engineRootFolder; + settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder)) + { + editorPath = engineRootFolder / installedBinariesPath / "Editor.app/Contents/MacOS"; + } + } + } + + if (!AZ::IO::SystemFile::IsDirectory(editorPath.c_str())) + { + AZ_Error("ProjectManager", false, "Unable to find the Editor app bundle!"); + } + } + + return editorPath; + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp index 831529d5e4..871f8e9567 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp @@ -14,6 +14,8 @@ #include #include +#include + namespace O3DE::ProjectManager { namespace ProjectUtils @@ -139,5 +141,10 @@ namespace O3DE::ProjectManager QProcessEnvironment::systemEnvironment(), QObject::tr("Running get_python script...")); } + + AZ::IO::FixedMaxPath GetEditorDirectory() + { + return AZ::Utils::GetExecutableDirectory(); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h index 1fdf76913e..890d50d2de 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.h +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h @@ -14,6 +14,7 @@ #include #include +#include #include namespace O3DE::ProjectManager @@ -67,7 +68,8 @@ namespace O3DE::ProjectManager AZ::Outcome GetProjectBuildPath(const QString& projectPath); AZ::Outcome OpenCMakeGUI(const QString& projectPath); AZ::Outcome RunGetPythonScript(const QString& enginePath); - + + AZ::IO::FixedMaxPath GetEditorDirectory(); } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index cf42da88fa..f86a689e59 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -392,11 +392,11 @@ namespace O3DE::ProjectManager { if (!WarnIfInBuildQueue(projectPath)) { - AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory(); + AZ::IO::FixedMaxPath executableDirectory = ProjectUtils::GetEditorDirectory(); AZStd::string executableFilename = "Editor"; AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION); auto cmdPath = AZ::IO::FixedMaxPathString::format( - "%s -regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(), + "%s --regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(), projectPath.toStdString().c_str()); AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; diff --git a/Code/Tools/SceneAPI/SceneUI/CommonWidgets/ProcessingOverlayWidget.cpp b/Code/Tools/SceneAPI/SceneUI/CommonWidgets/ProcessingOverlayWidget.cpp index bc9c4679df..a1326b0c82 100644 --- a/Code/Tools/SceneAPI/SceneUI/CommonWidgets/ProcessingOverlayWidget.cpp +++ b/Code/Tools/SceneAPI/SceneUI/CommonWidgets/ProcessingOverlayWidget.cpp @@ -63,7 +63,7 @@ namespace AZ } ProcessingOverlayWidget::ProcessingOverlayWidget(UI::OverlayWidget* overlay, Layout layout, Uuid traceTag) - : QWidget() + : QWidget(nullptr, Qt::Tool | Qt::WindowStaysOnTopHint) , m_traceTag(traceTag) , ui(new Ui::ProcessingOverlayWidget()) , m_overlay(overlay) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageObject.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageObject.h index 5796a0c84d..475c72c0eb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageObject.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageObject.h @@ -100,13 +100,6 @@ namespace ImageProcessingAtom //compare whether two images are same. return true if they are same. virtual bool CompareImage(const IImageObjectPtr otherImage) const = 0; - // Writes this image to file used for runtime, overwrites any existing file. - // It may write alpha image as attached image into the same file - // outFilePaths will save filenames finally saved to since the image might be split and saved to multiple files - virtual bool SaveImage(const char* filename, IImageObjectPtr alphaImage, AZStd::vector& outFilePaths) const = 0; - virtual bool SaveImage(AZ::IO::SystemFileStream& out) const = 0; - virtual bool SaveMipToFile(AZ::u32 mip, const AZStd::string& filename) const = 0; - //get total image data size in memory of all mipmaps. Not includs header and flags. virtual AZ::u32 GetTextureMemory() const = 0; @@ -135,9 +128,6 @@ namespace ImageProcessingAtom // The algorithm is based on the Frequency Domain Normal Mapping implementation presented by Neubelt and Pettineo at Siggraph 2013. virtual void GlossFromNormals(bool hasAuthoredGloss) = 0; - //convert gloss map from legacy distribution to new one. New World is still using legacy gloss map. - virtual void ConvertLegacyGloss() = 0; - //clear image with color virtual void ClearColor(float r, float g, float b, float a) = 0; }; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp index 3812b86026..046c4faa87 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp @@ -45,10 +45,7 @@ namespace ImageProcessingAtom ->Field("MinTextureSize", &PresetSettings::m_minTextureSize) ->Field("IsPowerOf2", &PresetSettings::m_isPowerOf2) ->Field("SizeReduceLevel", &PresetSettings::m_sizeReduceLevel) - ->Field("IsColorChart", &PresetSettings::m_isColorChart) - ->Field("HighPassMip", &PresetSettings::m_highPassMip) ->Field("GlossFromNormal", &PresetSettings::m_glossFromNormals) - ->Field("UseLegacyGloss", &PresetSettings::m_isLegacyGloss) ->Field("MipRenormalize", &PresetSettings::m_isMipRenormalize) ->Field("NumberResidentMips", &PresetSettings::m_numResidentMips) ->Field("Swizzle", &PresetSettings::m_swizzle) @@ -200,10 +197,7 @@ namespace ImageProcessingAtom m_maxTextureSize == other.m_maxTextureSize && m_isPowerOf2 == other.m_isPowerOf2 && m_sizeReduceLevel == other.m_sizeReduceLevel && - m_isColorChart == other.m_isColorChart && - m_highPassMip == other.m_highPassMip && m_glossFromNormals == other.m_glossFromNormals && - m_isLegacyGloss == other.m_isLegacyGloss && m_swizzle == other.m_swizzle && m_isMipRenormalize == other.m_isMipRenormalize && m_numResidentMips == other.m_numResidentMips; @@ -239,10 +233,7 @@ namespace ImageProcessingAtom m_maxTextureSize = other.m_maxTextureSize; m_isPowerOf2 = other.m_isPowerOf2; m_sizeReduceLevel = other.m_sizeReduceLevel; - m_isColorChart = other.m_isColorChart; - m_highPassMip = other.m_highPassMip; m_glossFromNormals = other.m_glossFromNormals; - m_isLegacyGloss = other.m_isLegacyGloss; m_swizzle = other.m_swizzle; m_isMipRenormalize = other.m_isMipRenormalize; m_numResidentMips = other.m_numResidentMips; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h index 941437bbf4..3dc223cf80 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h @@ -84,16 +84,7 @@ namespace ImageProcessingAtom //settings for mipmap generation. it's null if this preset disable mipmap. AZStd::unique_ptr m_mipmapSetting; - - //some specific settings - // "colorchart". This is to indicate if need to extract color chart from the image and output the color chart data. - // This is very specific usage for cryEngine. Check ColorChart.cpp for better explanation. - bool m_isColorChart = false; - - //"highpass". Defines which mip level is subtracted when applying the high pass filter - //this is only used for terrain asset. we might remove it later since it can be done with source image directly - AZ::u32 m_highPassMip = 0; - + //"glossfromnormals". Bake normal variance into smoothness stored in alpha channel AZ::u32 m_glossFromNormals = 0; @@ -109,10 +100,6 @@ namespace ImageProcessingAtom //that add up to 64K or lower AZ::u8 m_numResidentMips = 0; - //legacy options might be removed later - //"glosslegacydist". If the gloss map use legacy distribution. NW is still using legacy dist - bool m_isLegacyGloss = false; - //"swizzle". need to be 4 character and each character need to be one of "rgba01" AZStd::string m_swizzle; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp deleted file mode 100644 index b6e9cf4c8c..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include -#include - -namespace ImageProcessingAtom -{ - const int COLORCHART_IMAGE_WIDTH = 78; - const int COLORCHART_IMAGE_HEIGHT = 66; - - // color chart in cry engine is a special image data, with size 78x66, you may see in game screenshot which is defined by a rectangle - // area with a yellow-black dash line boarder - // Create color chart function is to read that block of image data and convert it to a color table then save it to another image - // with size 256x16. - - class C3dLutColorChart - { - public: - C3dLutColorChart() {} - ~C3dLutColorChart() {}; - - //generate default color chart data - void GenerateDefault(); - - //generate color chart data from input image - bool GenerateFromInput(IImageObjectPtr image); - - //ouput the color chart data to an image object - IImageObjectPtr GenerateChartImage(); - - protected: - //extract color chart data from specified location in an image - void ExtractFromImageAt(IImageObjectPtr pImg, AZ::u32 x, AZ::u32 y); - - //find color chart location in an image - static bool FindColorChart(const IImageObjectPtr pImg, AZ::u32& outLocX, AZ::u32& outLocY); - - //if there is a color chart at specified location - static bool IsColorChartAt(AZ::u32 x, AZ::u32 y, void* pData, AZ::u32 pitch); - - private: - enum EPrimaryShades - { - ePS_Red = 16, - ePS_Green = 16, - ePS_Blue = 16, - - ePS_NumColors = ePS_Red * ePS_Green * ePS_Blue - }; - - struct SColor - { - unsigned char r, g, b, _padding; - }; - - typedef AZStd::vector ColorMapping; - - ColorMapping m_mapping; - }; - - void C3dLutColorChart::GenerateDefault() - { - m_mapping.reserve(ePS_NumColors); - - for (int b = 0; b < ePS_Blue; ++b) - { - for (int g = 0; g < ePS_Green; ++g) - { - for (int r = 0; r < ePS_Red; ++r) - { - SColor col; - col.r = static_cast(255 * r / (ePS_Red)); - col.g = static_cast(255 * g / (ePS_Green)); - col.b = static_cast(255 * b / (ePS_Blue)); - int l = 255 - (col.r * 3 + col.g * 6 + col.b) / 10; - col.r = col.g = col.b = (unsigned char)l; - m_mapping.push_back(col); - } - } - } - } - - //find color chart location in a image - bool C3dLutColorChart::FindColorChart(const IImageObjectPtr pImg, AZ::u32& outLocX, AZ::u32& outLocY) - { - const AZ::u32 width = pImg->GetWidth(0); - const AZ::u32 height = pImg->GetHeight(0); - - //the origin image is too small to have a color chart - if (width < COLORCHART_IMAGE_WIDTH || height < COLORCHART_IMAGE_HEIGHT) - { - return false; - } - - AZ::u8* pData; - AZ::u32 pitch; - pImg->GetImagePointer(0, pData, pitch); - - //check all the posible start location on whether there might be a color chart - for (AZ::u32 y = 0; y <= height - COLORCHART_IMAGE_HEIGHT; ++y) - { - for (AZ::u32 x = 0; x <= width - COLORCHART_IMAGE_WIDTH; ++x) - { - if (IsColorChartAt(x, y, pData, pitch)) - { - outLocX = x; - outLocY = y; - return true; - } - } - } - - return false; - } - - bool C3dLutColorChart::GenerateFromInput(IImageObjectPtr image) - { - AZ::u32 outLocX, outLocY; - if (FindColorChart(image, outLocX, outLocY)) - { - ExtractFromImageAt(image, outLocX, outLocY); - return true; - } - return false; - } - - IImageObjectPtr C3dLutColorChart::GenerateChartImage() - { - IImageObjectPtr image(IImageObject::CreateImage(ePS_Red* ePS_Blue, ePS_Green, 1, ePixelFormat_R8G8B8A8)); - - { - AZ::u8* pData; - AZ::u32 pitch; - image->GetImagePointer(0, pData, pitch); - - size_t nSlicePitch = (pitch / ePS_Blue); - AZ::u32 src = 0; - for (int b = 0; b < ePS_Blue; ++b) - { - for (int g = 0; g < ePS_Green; ++g) - { - AZ::u8* p = pData + g * pitch + b * nSlicePitch; - for (int r = 0; r < ePS_Red; ++r) - { - const SColor& c = m_mapping[src]; - p[0] = c.r; - p[1] = c.g; - p[2] = c.b; - p[3] = 255; - ++src; - p += 4; - } - } - } - } - - return image; - } - - void C3dLutColorChart::ExtractFromImageAt(IImageObjectPtr image, AZ::u32 x, AZ::u32 y) - { - int ox = x + 1; - int oy = y + 1; - - AZ::u8* pData; - AZ::u32 pitch; - image->GetImagePointer(0, pData, pitch); - - m_mapping.reserve(ePS_NumColors); - - for (int b = 0; b < ePS_Blue; ++b) - { - int px = ox + ePS_Red * (b % 4); - int py = oy + ePS_Green * (b / 4); - - for (int g = 0; g < ePS_Green; ++g) - { - for (int r = 0; r < ePS_Red; ++r) - { - AZ::u8* p = pData + pitch * (py + g) + (px + r) * 4; - - SColor col; - col.r = p[0]; - col.g = p[1]; - col.b = p[2]; - m_mapping.push_back(col); - } - } - } - } - - //check if image data at location x and y could be a color chart - //based on if the boarder is dash lines with two pixel each segement - //the idea and implementation are both coming from CryEngine. - bool C3dLutColorChart::IsColorChartAt(AZ::u32 x, AZ::u32 y, void* pData, AZ::u32 pitch) - { - struct Color - { - private: - int c[3]; - - public: - Color(AZ::u32 x, AZ::u32 y, void* pPixels, AZ::u32 pitch) - { - const uint8* p = (const uint8*)pPixels + pitch * y + x * 4; - c[0] = p[0]; - c[1] = p[1]; - c[2] = p[2]; - } - - bool isSimilar(const Color& a, int maxDiff) const - { - return - abs(a.c[0] - c[0]) <= maxDiff && - abs(a.c[1] - c[1]) <= maxDiff && - abs(a.c[2] - c[2]) <= maxDiff; - } - }; - - const Color colorRef[2] = - { - Color(x, y, pData, pitch), - Color(x + 2, y, pData, pitch) - }; - - // We require two colors of the border to be at least a bit different - if (colorRef[0].isSimilar(colorRef[1], 15)) - { - return false; - } - - static const int kMaxDiff = 3; - - int refIdx = 0; - //rectangle's top - for (int i = 0; i < COLORCHART_IMAGE_WIDTH; i += 2) - { - if (!colorRef[refIdx].isSimilar(Color(x + i, y, pData, pitch), kMaxDiff) || - !colorRef[refIdx].isSimilar(Color(x + i + 1, y, pData, pitch), kMaxDiff)) - { - return false; - } - refIdx ^= 1; - } - - refIdx = 0; - //left - for (int i = 0; i < COLORCHART_IMAGE_HEIGHT; i += 2) - { - if (!colorRef[refIdx].isSimilar(Color(x, y + i, pData, pitch), kMaxDiff) || - !colorRef[refIdx].isSimilar(Color(x, y + i + 1, pData, pitch), kMaxDiff)) - { - return false; - } - refIdx ^= 1; - } - - refIdx = 0; - //right - for (int i = 0; i < COLORCHART_IMAGE_HEIGHT; i += 2) - { - if (!colorRef[refIdx].isSimilar(Color(x + COLORCHART_IMAGE_WIDTH - 1, y + i, pData, pitch), kMaxDiff) || - !colorRef[refIdx].isSimilar(Color(x + COLORCHART_IMAGE_WIDTH - 1, y + i + 1, pData, pitch), kMaxDiff)) - { - return false; - } - refIdx ^= 1; - } - - refIdx = 0; - //bottom - for (int i = 0; i < COLORCHART_IMAGE_WIDTH; i += 2) - { - if (!colorRef[refIdx].isSimilar(Color(x + i, y + COLORCHART_IMAGE_HEIGHT - 1, pData, pitch), kMaxDiff) || - !colorRef[refIdx].isSimilar(Color(x + i + 1, y + COLORCHART_IMAGE_HEIGHT - 1, pData, pitch), kMaxDiff)) - { - return false; - } - refIdx ^= 1; - } - - return true; - } - - - void ImageToProcess::CreateColorChart() - { - C3dLutColorChart colorChart; - - //get color chart data from source image. - if (!colorChart.GenerateFromInput(m_img)) - { - //if load from image failed then generate default color data - colorChart.GenerateDefault(); - } - - //save color chart data to an image and save as current - m_img = colorChart.GenerateChartImage(); - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp index 4f13c6f9bf..d373f399e1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp @@ -547,7 +547,7 @@ namespace ImageProcessingAtom } //generate box filtered source image mip chain - IImageObjectPtr mippedSourceImage(IImageObject::CreateImage(outWidth, outHeight, maxMipCount, ePixelFormat_R32G32B32A32F)); + IImageObjectPtr mippedSourceImage(IImageObject::CreateImage(outWidth, outHeight, maxMipCount, srcPixelFormat)); mippedSourceImage->CopyPropertiesFrom(m_image->Get()); for (int iSide = 0; iSide < 6; ++iSide) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/HighPass.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/HighPass.cpp deleted file mode 100644 index e2071fb586..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/HighPass.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include -#include -#include -#include -#include -#include - -namespace ImageProcessingAtom -{ - // higher mip level is subtracted by lower mip level when applying the [cheap] high pass filter - void ImageToProcess::CreateHighPass(AZ::u32 dwMipDown) - { - //no need to convert if mip go down 0 - if (dwMipDown == 0) - { - return; - } - - const EPixelFormat ePixelFormat = m_img->GetPixelFormat(); - - if (ePixelFormat != ePixelFormat_R32G32B32A32F) - { - AZ_Assert(false, "You need convert the orginal image to ePixelFormat_R32G32B32A32F before call this function"); - return; - } - - - AZ::u32 dwWidth, dwHeight, dwMips; - dwWidth = m_img->GetWidth(0); - dwHeight = m_img->GetHeight(0); - dwMips = m_img->GetMipCount(); - - if (dwMipDown >= dwMips) - { - AZ_Warning("Image Processing", false, "CreateHighPass can't go down %i MIP levels for high pass as there are not\ - enough MIP levels available, going down by %i instead", dwMipDown, dwMips - 1); - dwMipDown = dwMips - 1; - } - - IImageObjectPtr newImage(IImageObject::CreateImage(dwWidth, dwHeight, dwMips, ePixelFormat)); - newImage->CopyPropertiesFrom(m_img); - - IPixelOperationPtr pixelOp = CreatePixelOperation(ePixelFormat); - AZ::u32 pixelBytes = CPixelFormats::GetInstance().GetPixelFormatInfo(ePixelFormat)->bitsPerBlock / 8; - - AZ::u32 dstMips = newImage->GetMipCount(); - for (AZ::u32 dstMip = 0; dstMip < dwMipDown; ++dstMip) - { - // linear interpolation - FilterImage(MipGenType::triangle, MipGenEvalType::sum, 0.0f, 0.0f, m_img, dwMipDown, newImage, dstMip, NULL, NULL); - - //substraction - AZ::u8* srcPixelBuf; - AZ::u32 srcPitch; - m_img->GetImagePointer(dstMip, srcPixelBuf, srcPitch); - AZ::u8* dstPixelBuf; - AZ::u32 dstPitch; - newImage->GetImagePointer(dstMip, dstPixelBuf, dstPitch); - const AZ::u32 pixelCount = newImage->GetPixelCount(dstMip); - - for (AZ::u32 i = 0; i < pixelCount; ++i, srcPixelBuf += pixelBytes, dstPixelBuf += pixelBytes) - { - float r1, g1, b1, a1, r2, g2, b2, a2; - pixelOp->GetRGBA(srcPixelBuf, r1, g1, b1, a1); - pixelOp->GetRGBA(dstPixelBuf, r2, g2, b2, a2); - - r2 = AZ::GetClamp(r1 - r2 + 0.5f, 0.0f, 1.0f); - g2 = AZ::GetClamp(g1 - g2 + 0.5f, 0.0f, 1.0f); - b2 = AZ::GetClamp(b1 - b2 + 0.5f, 0.0f, 1.0f); - a2 = AZ::GetClamp(a1 - a2 + 0.5f, 0.0f, 1.0f); - pixelOp->SetRGBA(dstPixelBuf, r2, g2, b2, a2); - } - } - - // mips below the chosen highpass mip are grey - for (AZ::u32 dstMip = dwMipDown; dstMip < dstMips; ++dstMip) - { - AZ::u8* dstPixelBuf; - AZ::u32 dstPitch; - newImage->GetImagePointer(dstMip, dstPixelBuf, dstPitch); - const AZ::u32 pixelCount = newImage->GetPixelCount(dstMip); - - for (AZ::u32 i = 0; i < pixelCount; ++i, dstPixelBuf += pixelBytes) - { - pixelOp->SetRGBA(dstPixelBuf, 0.5f, 0.5f, 0.5f, 1.0f); - } - } - - m_img = newImage; - } -} // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp index a5b942fa58..fe5703ceb6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp @@ -82,10 +82,7 @@ namespace ImageProcessingAtomEditor presetInfoText += "\n"; presetInfoText += QString("Suppress Engine Reduce: %1\n").arg(presetSettings->m_suppressEngineReduce ? "True" : "False"); presetInfoText += QString("Discard Alpha: %1\n").arg(presetSettings->m_discardAlpha ? "True" : "False"); - presetInfoText += QString("Is Color Chart: %1\n").arg(presetSettings->m_isColorChart ? "True" : "False"); - presetInfoText += QString("High Pass Mip: %1\n").arg(presetSettings->m_highPassMip); presetInfoText += QString("Gloss From Normal: %1\n").arg(presetSettings->m_glossFromNormals); - presetInfoText += QString("Use Legacy Gloss: %1\n").arg(presetSettings->m_isLegacyGloss ? "True" : "False"); presetInfoText += QString("Mip Re-normalize: %1\n").arg(presetSettings->m_isMipRenormalize ? "True" : "False"); presetInfoText += QString("Resident Mips Number: %1\n").arg(presetSettings->m_numResidentMips); presetInfoText += QString("Swizzle: %1\n").arg(presetSettings->m_swizzle.c_str()); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp index a489c8da5e..90d45ae65a 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp @@ -74,7 +74,7 @@ namespace ImageProcessingAtom builderDescriptor.m_busId = azrtti_typeid(); builderDescriptor.m_createJobFunction = AZStd::bind(&ImageBuilderWorker::CreateJobs, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); builderDescriptor.m_processJobFunction = AZStd::bind(&ImageBuilderWorker::ProcessJob, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_version = 25; // [ATOM-16575] + builderDescriptor.m_version = 26; // [ATOM-15086] builderDescriptor.m_analysisFingerprint = ImageProcessingAtom::BuilderSettingManager::Instance()->GetAnalysisFingerprint(); m_imageBuilder.BusConnect(builderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp index 977359e4f6..5b23009cff 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp @@ -46,7 +46,6 @@ namespace ImageProcessingAtom enum ConvertStep { StepValidateInput = 0, - StepGenerateColorChart, StepConvertToLinear, StepSwizzle, StepCubemapLayout, @@ -55,9 +54,7 @@ namespace ImageProcessingAtom StepMipmap, StepGlossFromNormal, StepPostNormalize, - StepCreateHighPass, StepConvertOutputColorSpace, - StepAlphaImage, StepConvertPixelFormat, StepSaveToFile, StepAll @@ -66,7 +63,6 @@ namespace ImageProcessingAtom [[maybe_unused]] const char ProcessStepNames[StepAll][64] = { "ValidateInput", - "GenerateColorChart", "ConvertToLinear", "Swizzle", "CubemapLayout", @@ -75,9 +71,7 @@ namespace ImageProcessingAtom "Mipmap", "GlossFromNormal", "PostNormalize", - "CreateHighPass", "ConvertOutputColorSpace", - "AlphaImage", "ConvertPixelFormat", "SaveToFile", }; @@ -94,11 +88,6 @@ namespace ImageProcessingAtom return nullptr; } - IImageObjectPtr ImageConvertProcess::GetOutputAlphaImage() - { - return m_alphaImage; - } - IImageObjectPtr ImageConvertProcess::GetOutputIBLSpecularCubemap() { return m_iblSpecularCubemapImage; @@ -180,6 +169,58 @@ namespace ImageProcessingAtom m_image = new ImageToProcess(IImageObjectPtr(m_input->m_inputImage->Clone(mipsToClone))); } + break; + case StepConvertToLinear: + // convert to linear space and the output image pixel format should be rgba32f + ConvertToLinear(); + break; + case StepSwizzle: + { + // swizzle if swizzle was set or decard alpha + bool swizzleWasSet = m_input->m_presetSetting.m_swizzle.size() >= 4; + if (swizzleWasSet || m_input->m_presetSetting.m_discardAlpha) + { + AZStd::string swizzle = "rgba"; + if (swizzleWasSet) + { + swizzle = m_input->m_presetSetting.m_swizzle.substr(0, 4); + } + + if (m_input->m_presetSetting.m_discardAlpha) + { + swizzle[3] = '1'; + } + + m_image->Get()->Swizzle(swizzle.c_str()); + if (!m_input->m_presetSetting.m_discardAlpha) + { + m_alphaContent = EAlphaContent::eAlphaContent_Absent; + } + else + { + m_alphaContent = m_image->Get()->GetAlphaContent(); + } + } + } + break; + case StepCubemapLayout: + // convert cubemap image's layout to vertical strip used in game. + if (IsConvertToCubemap()) + { + if (!m_image->ConvertCubemapLayout(CubemapLayoutVertical)) + { + m_image->Set(nullptr); + } + } + break; + case StepPreNormalize: + // normalize base image before mipmap generation if glossfromnormals is enabled and require normalize + if (m_input->m_presetSetting.m_isMipRenormalize && m_input->m_presetSetting.m_glossFromNormals) + { + // Normalize the base mip map. This has to be done explicitly because we need to disable mip renormalization to + // preserve the normal length when deriving the normal variance + m_image->Get()->NormalizeVectors(0, 1); + } break; case StepGenerateIBL: if (IsConvertToCubemap()) @@ -204,56 +245,6 @@ namespace ImageProcessingAtom m_isFinished = true; } break; - case StepGenerateColorChart: - // GenerateColorChart. - if (m_input->m_presetSetting.m_isColorChart) - { - // Convert to uncompressed format if it's compressed format. For example, loaded from DDS file. - if (!CPixelFormats::GetInstance().IsPixelFormatUncompressed(m_image->Get()->GetPixelFormat())) - { - m_image->ConvertFormat(ePixelFormat_R32G32B32A32F); - } - - m_image->CreateColorChart(); - } - break; - case StepConvertToLinear: - // convert to linear space and the output image pixel format should be rgba32f - ConvertToLinear(); - break; - case StepSwizzle: - // convert texture format. - if (m_input->m_presetSetting.m_swizzle.size() >= 4) - { - m_image->Get()->Swizzle(m_input->m_presetSetting.m_swizzle.substr(0, 4).c_str()); - m_alphaContent = m_image->Get()->GetAlphaContent(); - } - - // convert gloss map (alhpa channel) from legacy distribution to new one - if (m_input->m_presetSetting.m_isLegacyGloss) - { - m_image->Get()->ConvertLegacyGloss(); - } - break; - case StepCubemapLayout: - // convert cubemap image's layout to vertical strip used in game. - if (IsConvertToCubemap()) - { - if (!m_image->ConvertCubemapLayout(CubemapLayoutVertical)) - { - m_image->Set(nullptr); - } - } - break; - case StepPreNormalize: - // normalize base image before mipmap generation if glossfromnormals is enabled and require normalize - if (m_input->m_presetSetting.m_isMipRenormalize && m_input->m_presetSetting.m_glossFromNormals) - { - // Normalize the base mip map. This has to be done explicitly because we need to disable mip renormalization to - // preserve the normal length when deriving the normal variance - m_image->Get()->NormalizeVectors(0, 1); - } - break; case StepMipmap: // generate mipmaps if (IsConvertToCubemap()) @@ -304,20 +295,10 @@ namespace ImageProcessingAtom m_image->Get()->AddImageFlags(EIF_RenormalizedTexture); } break; - case StepCreateHighPass: - if (m_input->m_presetSetting.m_highPassMip > 0) - { - m_image->CreateHighPass(m_input->m_presetSetting.m_highPassMip); - } - break; case StepConvertOutputColorSpace: // convert image from linear space to desired output color space ConvertToOuputColorSpace(); break; - case StepAlphaImage: - // save alpha channel to separate image if it's needed - CreateAlphaImage(); - break; case StepConvertPixelFormat: // convert pixel format ConvertPixelformat(); @@ -411,12 +392,6 @@ namespace ImageProcessingAtom return; } - // don't do any reduce for color chart - if (presetSettings->m_isColorChart) - { - return; - } - // get suitable size for dest pixel format CPixelFormats::GetInstance().GetSuitableImageSize(presetSettings->m_pixelFormat, inputWidth, inputHeight, outWidth, outHeight); @@ -510,52 +485,6 @@ namespace ImageProcessingAtom return true; } - void ImageConvertProcess::CreateAlphaImage() - { - // if alpha content doesn't have alpha or we need to discard alpha, skip - // we won't create alpha image for cubemap too - if (m_alphaContent == EAlphaContent::eAlphaContent_Absent - || m_alphaContent == EAlphaContent::eAlphaContent_OnlyWhite - || m_input->m_presetSetting.m_discardAlpha || IsConvertToCubemap()) - { - return; - } - - // if dest format could save alpha, skip too - if (!CPixelFormats::GetInstance().IsPixelFormatWithoutAlpha(m_input->m_presetSetting.m_pixelFormat)) - { - return; - } - - // now create alpha image - ImageToProcess alphaImage(m_image->Get()); - alphaImage.ConvertFormat(ePixelFormat_A8); - - // validate pixelformatalpha - if (CPixelFormats::GetInstance().IsFormatSingleChannel(m_input->m_presetSetting.m_pixelFormatAlpha)) - { - alphaImage.ConvertFormat(m_input->m_presetSetting.m_pixelFormatAlpha); - } - else - { - //For ASTC compression we need to clear out the alpha to get accurate rgb compression. - if (IsASTCFormat(m_input->m_presetSetting.m_pixelFormat)) - { - alphaImage.ConvertFormat(ePixelFormat_R8G8B8X8); - alphaImage.ConvertFormat(m_input->m_presetSetting.m_pixelFormatAlpha); - } - else - { - AZ_Assert(false, "PixelFormatAlpha only supports single channel pixel formats or ASTC formats"); - } - } - - // get final result and save it to member variable for later use - m_alphaImage = alphaImage.Get(); - - m_image->Get()->AddImageFlags(EIF_AttachedAlpha); - } - // pixel format conversion bool ImageConvertProcess::ConvertPixelformat() { @@ -575,12 +504,6 @@ namespace ImageProcessingAtom m_image->GetCompressOption().rgbWeight = m_input->m_presetSetting.GetColorWeight(); m_image->GetCompressOption().discardAlpha = m_input->m_presetSetting.m_discardAlpha; - //For ASTC compression we need to clear out the alpha to get accurate rgb compression. - if(m_alphaImage && IsASTCFormat(m_input->m_presetSetting.m_pixelFormat)) - { - m_image->GetCompressOption().discardAlpha = true; - } - m_image->ConvertFormat(m_input->m_presetSetting.m_pixelFormat); return true; @@ -762,7 +685,6 @@ namespace ImageProcessingAtom if (ImageProcess##PrivateName::DoesSupport(m_input->m_platform)) \ { \ ImageProcess##PrivateName::PrepareImageForExport(m_image->Get()); \ - ImageProcess##PrivateName::PrepareImageForExport(m_alphaImage); \ } AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS #undef AZ_RESTRICTED_PLATFORM_EXPANSION diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h index eaf05c3280..fe57b1a89f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h @@ -115,7 +115,6 @@ namespace ImageProcessingAtom //get output images IImageObjectPtr GetOutputImage(); - IImageObjectPtr GetOutputAlphaImage(); IImageObjectPtr GetOutputIBLSpecularCubemap(); IImageObjectPtr GetOutputIBLDiffuseCubemap(); @@ -131,8 +130,6 @@ namespace ImageProcessingAtom //for alpha //to indicate the current alpha channel content EAlphaContent m_alphaContent; - //An image object to hold alpha channel in a separate image - IImageObjectPtr m_alphaImage; //output results of IBL cubemap generation, used in unit tests IImageObjectPtr m_iblSpecularCubemapImage; @@ -171,9 +168,6 @@ namespace ImageProcessingAtom //convert to output color space before compression bool ConvertToOuputColorSpace(); - //create alpha image if it's needed - void CreateAlphaImage(); - //pixel format convertion/compression bool ConvertPixelformat(); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.cpp index 1465e7993f..0e4521ab24 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.cpp @@ -108,17 +108,14 @@ namespace ImageProcessingAtom } IImageObjectPtr outputImage = m_process->GetOutputImage(); - IImageObjectPtr outputImageAlpha = m_process->GetOutputAlphaImage(); m_output->SetOutputImage(outputImage, ImageConvertOutput::Base); - m_output->SetOutputImage(outputImageAlpha, ImageConvertOutput::Alpha); if (!IsJobCancelled()) { // For preview, combine image output with alpha if any m_output->SetProgress(1.0f / static_cast(m_previewProcessStep)); - IImageObjectPtr combinedImage = MergeOutputImageForPreview(outputImage, outputImageAlpha); - m_output->SetOutputImage(combinedImage, ImageConvertOutput::Preview); + m_output->SetOutputImage(outputImage, ImageConvertOutput::Preview); } m_output->SetReady(true); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h index 99e752c90a..d25533cccd 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h @@ -20,7 +20,7 @@ namespace ImageProcessingAtom const static AZ::u32 EIF_Greyscale = 0x8; // hint for the engine (e.g. greyscale light beams can be applied to shadow mask), can be for DXT1 because compression artfacts don't count as color const static AZ::u32 EIF_SupressEngineReduce = 0x10; // info for the engine: don't reduce texture resolution on this texture const static AZ::u32 EIF_UNUSED_BIT = 0x40; // Free to use - const static AZ::u32 EIF_AttachedAlpha = 0x400; // info for the engine: it's a texture with attached alpha channel + const static AZ::u32 EIF_AttachedAlpha = 0x400; // deprecated: info for the engine: it's a texture with attached alpha channel const static AZ::u32 EIF_SRGBRead = 0x800; // info for the engine: if gamma corrected rendering is on, this texture requires SRGBRead (it's not stored in linear) const static AZ::u32 EIF_DontResize = 0x8000; // info for the engine: for dds textures that shouldn't be resized const static AZ::u32 EIF_RenormalizedTexture = 0x10000; // info for the engine: for dds textures that have renormalized color range diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.cpp index 8504f5e074..465d992ef6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.cpp @@ -316,130 +316,6 @@ namespace ImageProcessingAtom m_mips.clear(); } - //note: there are some unreasonable parts of the save files formats for cry textures. We might need to rethink about - // it for new renderer - bool CImageObject::SaveImage(const char* filename, IImageObjectPtr alphaImage, AZStd::vector& outFilePaths) const - { - AZ::IO::SystemFile file; - file.Open(filename, AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY); - - AZ::IO::SystemFileStream fileSaveStream(&file, true); - if (!fileSaveStream.IsOpen()) - { - AZ_Warning("Image Processing", false, "%s: failed to create file %s", __FUNCTION__, filename); - return false; - } - - if (alphaImage) - { - AZ_Assert(HasImageFlags(EIF_AttachedAlpha), "attached alpha image flag wasn't set"); - AZ_Assert(!alphaImage->HasImageFlags(EIF_AttachedAlpha), "alpha image shouldn't have attached alpha image flag"); - - // inherit cubemap and decal image flags to attached alpha image - alphaImage->AddImageFlags(GetImageFlags() & (EIF_Cubemap - | EIF_Decal | EIF_Splitted)); - alphaImage->SetNumPersistentMips(m_numPersistentMips); - } - - bool bOk = SaveImage(fileSaveStream); - bool hasSplitFlag = HasImageFlags(EIF_Splitted); - - //append alpha image data in the end if there is no split - if (bOk && alphaImage && !hasSplitFlag) - { - //4 bytes extension tag, 4 bytes attached alpha tag, then 4 bytes of chunk size - fileSaveStream.Write(sizeof(FOURCC_CExt), &FOURCC_CExt); // marker for the start of O3DE Extended data - fileSaveStream.Write(sizeof(FOURCC_AttC), &FOURCC_AttC); // Attached Channel chunk - - uint32_t size = 0; - uint32_t sizeBytes = sizeof(size); - fileSaveStream.Write(sizeBytes, &size); //size of attached chunk - - //save alpha image and get the size - AZ::IO::SizeType startPos = fileSaveStream.GetCurPos(); - bOk = alphaImage->SaveImage(fileSaveStream); - AZ::IO::SizeType endPos = fileSaveStream.GetCurPos(); - size = static_cast(endPos - startPos); - - //move back to beginning of chunk and write chunk size then move back to end - fileSaveStream.Seek(startPos - sizeBytes, AZ::IO::GenericStream::ST_SEEK_BEGIN); - fileSaveStream.Write(sizeBytes, &size); - fileSaveStream.Seek(endPos, AZ::IO::GenericStream::ST_SEEK_BEGIN); - - // marker for the end of O3DE Extended data - fileSaveStream.Write(sizeof(FOURCC_CEnd), &FOURCC_CEnd); - } - - if (!bOk) - { - AZ::IO::SystemFile::Delete(filename); - return false; - } - - // It's important to maintain the product output sequence. Asset Database/Browser will use the first product to determine the source type! - outFilePaths.push_back(filename); - - // save stand alone products - if (hasSplitFlag) - { - // alpha - if (alphaImage) - { - AZStd::string alphaFile = AZStd::string::format("%s.a", filename); - - AZ::IO::SystemFile outAlphaFile; - outAlphaFile.Open(alphaFile.c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY); - - AZ::IO::SystemFileStream alphaFileSaveStream(&outAlphaFile, true); - - if (alphaFileSaveStream.IsOpen()) - { - alphaImage->SaveImage(alphaFileSaveStream); - outFilePaths.push_back(alphaFile); - } - else - { - AZ_Warning("Image Processing", false, "%s: failed to create file %s", __FUNCTION__, alphaFile.c_str()); - } - } - - // mips - AZ::u32 numStreamable = GetMipCount() - m_numPersistentMips; - for (AZ::u32 mip = 0; mip < numStreamable; mip++) - { - AZ::u32 nameIdx = numStreamable - mip; - AZStd::string mipFileName = AZStd::string::format("%s.%d", filename, nameIdx); - SaveMipToFile(mip, mipFileName); - outFilePaths.push_back(mipFileName); - if (alphaImage) - { - AZStd::string mipAlphaFileName = mipFileName + "a"; - alphaImage->SaveMipToFile(mip, mipAlphaFileName); - outFilePaths.push_back(mipAlphaFileName); - } - } - } - - return bOk; - } - - bool CImageObject::SaveMipToFile(AZ::u32 mip, const AZStd::string& filename) const - { - AZ::IO::SystemFile saveFile; - saveFile.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY); - - AZ::IO::SystemFileStream saveFileStream(&saveFile, true); - - if (!saveFileStream.IsOpen()) - { - AZ_Warning("Image Processing", false, "%s: failed to create file %s", __FUNCTION__, filename.c_str()); - return false; - } - - saveFileStream.Write(GetMipBufSize(mip), m_mips[mip]->m_pData); - return true; - } - float CImageObject::CalculateAverageBrightness() const { //if it's compressed format, return a default value @@ -642,63 +518,6 @@ namespace ImageProcessingAtom return true; } - bool CImageObject::SaveImage(AZ::IO::SystemFileStream& saveFileStream) const - { - DDS_FILE_DESC_LEGACY desc; - DDS_HEADER_DXT10 exthead; - - desc.dwMagic = FOURCC_DDS; - - if (!BuildSurfaceHeader(desc.header)) - { - return false; - } - - if (desc.header.IsDX10Ext() && !BuildSurfaceExtendedHeader(exthead)) - { - return false; - } - - saveFileStream.Write(sizeof(desc), &desc); - - if (desc.header.IsDX10Ext()) - { - saveFileStream.Write(sizeof(exthead), &exthead); - } - - AZ::u32 faces = 1; - - //for cubemap. export each face and its mipmap - if (HasImageFlags(EIF_Cubemap)) - { - faces = 6; - } - - AZ::u32 mipStart = 0; - if (HasImageFlags(EIF_Splitted)) - { - if (m_numPersistentMips < m_mips.size()) - { - mipStart = (AZ::u32)m_mips.size() - m_numPersistentMips; - } - else - { - AZ_Assert(false, "numPersistentMips wasn't setup correctly"); - } - } - - for (AZ::u32 face = 0; face < faces; face++) - { - for (AZ::u32 mip = mipStart; mip < m_mips.size(); ++mip) - { - const MipLevel& level = *m_mips[mip]; - AZ::u32 faceBufSize = level.m_pitch * level.m_rowCount / faces; - saveFileStream.Write(faceBufSize, level.m_pData + faceBufSize * face); - } - } - return true; - } - void CImageObject::GetExtent(AZ::u32& width, AZ::u32& height, AZ::u32& mipCount) const { mipCount = (AZ::u32)m_mips.size(); @@ -953,35 +772,4 @@ namespace ImageProcessingAtom } } } - - void CImageObject::ConvertLegacyGloss() - { - if (!(CPixelFormats::GetInstance().IsPixelFormatUncompressed(m_pixelFormat))) - { - AZ_Assert(false, "%s function only works with uncompressed pixel format", __FUNCTION__); - return; - } - - //create pixel operation function - IPixelOperationPtr pixelOp = CreatePixelOperation(m_pixelFormat); - - //get count of bytes per pixel - AZ::u32 pixelBytes = CPixelFormats::GetInstance().GetPixelFormatInfo(m_pixelFormat)->bitsPerBlock / 8; - - const AZ::u32 mips = (AZ::u32)m_mips.size(); - float color[4]; - for (AZ::u32 mip = 0; mip < mips; ++mip) - { - AZ::u8* pixelBuf = m_mips[mip]->m_pData; - const AZ::u32 pixelCount = GetPixelCount(mip); - - for (AZ::u32 i = 0; i < pixelCount; ++i, pixelBuf += pixelBytes) - { - pixelOp->GetRGBA(pixelBuf, color[0], color[1], color[2], color[3]); - // Convert from (1 - s * 0.7)^6 to (1 - s)^2 - color[3] = 1 - pow(1.0f - color[3] * 0.7f, 3.0f); - pixelOp->SetRGBA(pixelBuf, color[0], color[1], color[2], color[3]); - } - } - } } // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.h index c8b8ced496..7fa02f464e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageObjectImpl.h @@ -57,10 +57,6 @@ namespace ImageProcessingAtom bool CompareImage(const IImageObjectPtr otherImage) const override; - bool SaveImage(const char* filename, IImageObjectPtr alphaImage, AZStd::vector& outFilePaths) const override; - bool SaveImage(AZ::IO::SystemFileStream& out) const override; - bool SaveMipToFile(AZ::u32 mip, const AZStd::string& filename) const override; - uint32_t GetTextureMemory() const override; EAlphaContent GetAlphaContent() const override; @@ -79,7 +75,6 @@ namespace ImageProcessingAtom void SetNumPersistentMips(AZ::u32 nMips) override; void GlossFromNormals(bool hasAuthoredGloss) override; - void ConvertLegacyGloss() override; void ClearColor(float r, float g, float b, float a) override; //end virtual functions from IImageObject diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageToProcess.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageToProcess.h index e6fe6ce142..ed0b21b56c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageToProcess.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageToProcess.h @@ -66,13 +66,6 @@ namespace ImageProcessingAtom bool GammaToLinearRGBA32F(bool bDeGamma); void LinearToGamma(); - // --------------------------------------------------------------------------------- - // Tools for A32B32G32R32F - - void CreateHighPass(uint32 dwMipDown); - - void CreateColorChart(); - //convert various original cubemap layouts to new layout bool ConvertCubemapLayout(CubemapLayoutType newLayout); }; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index 3e0bbd89eb..d5b795a1fa 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -988,7 +988,6 @@ namespace UnitTest ASSERT_TRUE(process->IsSucceed()); SaveImageToFile(process->GetOutputImage(), "rgb", 10); - SaveImageToFile(process->GetOutputAlphaImage(), "alpha", 10); process->GetAppendOutputProducts(outProducts); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake index aad400518d..a6fe09bfa6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake @@ -103,8 +103,6 @@ set(FILES Source/Converters/ConvertPixelFormat.cpp Source/Converters/Cubemap.h Source/Converters/Cubemap.cpp - Source/Converters/ColorChart.cpp - Source/Converters/HighPass.cpp Source/Converters/Histogram.cpp Source/Converters/Histogram.h ../External/CubeMapGen/CBBoxInt32.cpp diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index c232d4bba7..84fc58718c 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -272,6 +272,7 @@ namespace AZ // Create and register a scene with all available feature processors RPI::SceneDescriptor sceneDesc; + sceneDesc.m_nameId = AZ::Name("Main"); AZ::RPI::ScenePtr atomScene = RPI::Scene::CreateScene(sceneDesc); atomScene->EnableAllFeatureProcessors(); atomScene->Activate(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index a53dab7a01..8f58c6dd33 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -153,7 +153,7 @@ struct StandardMaterialInputs float2 m_vertexUv[UvSetCount]; float3x3 m_uvMatrix; - float m_normal; + float3 m_normal; float3 m_tangents[UvSetCount]; float3 m_bitangents[UvSetCount]; diff --git a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreTexture.cpp b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreTexture.cpp index aa906a06f7..1fd8f0d91c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreTexture.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreTexture.cpp @@ -32,7 +32,7 @@ namespace AZ { if (m_rtPipeline) { - AZ::RPI::RPISystemInterface::Get()->GetDefaultScene()->RemoveRenderPipeline(m_rtPipeline->GetId()); + m_rtPipeline->RemoveFromScene(); m_rtPipeline = nullptr; } @@ -111,8 +111,12 @@ namespace AZ parentPass->SetSourceTexture(m_texture, RHI::Format::R8G8B8A8_UNORM); break; } - - AZ::RPI::RPISystemInterface::Get()->GetDefaultScene()->AddRenderPipeline(m_rtPipeline); + + const auto mainScene = AZ::RPI::RPISystemInterface::Get()->GetSceneByName(AZ::Name("RPI")); + if (mainScene) + { + mainScene->AddRenderPipeline(m_rtPipeline); + } } bool LuxCoreTexture::IsIBLTexture() diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h index 4914e4b6fe..92370c5a82 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h @@ -70,7 +70,8 @@ namespace AZ void InitializeSystemAssets() override; void RegisterScene(ScenePtr scene) override; void UnregisterScene(ScenePtr scene) override; - ScenePtr GetScene(const SceneId& sceneId) const override; + Scene* GetScene(const SceneId& sceneId) const override; + Scene* GetSceneByName(const AZ::Name& name) const override; ScenePtr GetDefaultScene() const override; RenderPipelinePtr GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle) override; Data::Asset GetCommonShaderAssetForSrgs() const override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h index fe81596bd7..3f30d498cf 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h @@ -13,6 +13,7 @@ #include +#include #include namespace AZ @@ -46,11 +47,14 @@ namespace AZ //! Unregister a scene from RPISystem. The scene won't be simulated or rendered. virtual void UnregisterScene(ScenePtr scene) = 0; - // [GFX TODO] to be removed when we have scene setup in AZ Core - virtual ScenePtr GetDefaultScene() const = 0; - + //! Deprecated. Use GetSceneByName(name), GetSceneForEntityContextId(entityContextId) or Scene::GetSceneForEntityId(AZ::EntityId entityId) instead + AZ_DEPRECATED(virtual ScenePtr GetDefaultScene() const = 0;, "This method has been deprecated. Please use GetSceneByName(name), GetSceneForEntityContextId(entityContextId) or Scene::GetSceneForEntityId(AZ::EntityId entityId) instead."); + //! Get scene by using scene id. - virtual ScenePtr GetScene(const SceneId& sceneId) const = 0; + virtual Scene* GetScene(const SceneId& sceneId) const = 0; + + //! Get scene by using scene name. + virtual Scene* GetSceneByName(const AZ::Name& name) const = 0; //! Get the render pipeline created for a window virtual RenderPipelinePtr GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle) = 0; 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 fc81368331..f86383101a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -80,6 +80,9 @@ namespace AZ //! Gets the RPI::Scene for a given entityContextId. //! May return nullptr if there is no RPI::Scene created for that entityContext. static Scene* GetSceneForEntityContextId(AzFramework::EntityContextId entityContextId); + + //! Gets the RPI::Scene for a given entityId. + static Scene* GetSceneForEntityId(AZ::EntityId entityId); ~Scene(); @@ -135,6 +138,8 @@ namespace AZ const SceneId& GetId() const; + AZ::Name GetName() const; + //! Set default pipeline by render pipeline ID. //! It returns true if the default render pipeline was set from the input ID. //! If the specified render pipeline doesn't exist in this scene then it won't do anything and returns false. @@ -245,6 +250,9 @@ namespace AZ // The uuid to identify this scene. SceneId m_id; + // Scene's name which is set at initialization. Can be empty + AZ::Name m_name; + bool m_activated = false; bool m_taskGraphActive = false; // update during tick, to ensure it only changes on frame boundaries @@ -286,13 +294,10 @@ namespace AZ template FeatureProcessorType* Scene::GetFeatureProcessorForEntity(AZ::EntityId entityId) { - // Find the entity context for the entity ID. - AzFramework::EntityContextId entityContextId = AzFramework::EntityContextId::CreateNull(); - AzFramework::EntityIdContextQueryBus::EventResult(entityContextId, entityId, &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId); - - if (!entityContextId.IsNull()) + RPI::Scene* renderScene = GetSceneForEntityId(entityId); + if (renderScene) { - return GetFeatureProcessorForEntityContextId(entityContextId); + return renderScene->GetFeatureProcessor(); } return nullptr; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/System/SceneDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/System/SceneDescriptor.h index 2072568d59..eb7a2b6cb7 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/System/SceneDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/System/SceneDescriptor.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -25,6 +26,9 @@ namespace AZ //! List of feature processors which the scene will initially enable. AZStd::vector m_featureProcessorNames; + + //! A name used as scene id. It can be used to search a registered scene via RPISystemInterface::GetScene() + AZ::Name m_nameId; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index 348f0aa57a..ac6b10694e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -699,9 +699,7 @@ namespace AZ 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)); + AZ::Name visSceneName(AZStd::string::format("RenderCullScene[%s]", m_parentScene->GetName().GetCStr())); m_visScene = AZ::Interface::Get()->CreateVisibilityScene(visSceneName); #ifdef AZ_CULL_DEBUG_ENABLED diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index eb74a81e3e..943966c13b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -159,6 +159,11 @@ namespace AZ AZ_Assert(false, "Scene was already registered"); return; } + else if (!scene->GetName().IsEmpty() && scene->GetName() == sceneItem->GetName()) + { + // only report a warning if there is a scene with duplicated name + AZ_Warning("RPISystem", false, "There is a registered scene with same name [%s]", scene->GetName().GetCStr()); + } } m_scenes.push_back(scene); @@ -177,11 +182,35 @@ namespace AZ AZ_Assert(false, "Can't unregister scene which wasn't registered"); } - ScenePtr RPISystem::GetScene(const SceneId& sceneId) const + Scene* RPISystem::GetScene(const SceneId& sceneId) const { for (const auto& scene : m_scenes) { if (scene->GetId() == sceneId) + { + return scene.get(); + } + } + return nullptr; + } + + Scene* RPISystem::GetSceneByName(const AZ::Name& name) const + { + for (const auto& scene : m_scenes) + { + if (scene->GetName() == name) + { + return scene.get(); + } + } + return nullptr; + } + + ScenePtr RPISystem::GetDefaultScene() const + { + for (const auto& scene : m_scenes) + { + if (scene->GetName() == AZ::Name("Main")) { return scene; } @@ -189,16 +218,6 @@ namespace AZ return nullptr; } - ScenePtr RPISystem::GetDefaultScene() const - { - if (m_scenes.size() > 0) - { - return m_scenes[0]; - } - return nullptr; - } - - RenderPipelinePtr RPISystem::GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle) { RenderPipelinePtr renderPipeline; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index c5d82c6f29..41fefda656 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -45,7 +45,9 @@ namespace AZ auto shaderAsset = RPISystemInterface::Get()->GetCommonShaderAssetForSrgs(); scene->m_srg = ShaderResourceGroup::Create(shaderAsset, sceneSrgLayout->GetName()); } - + + scene->m_name = sceneDescriptor.m_nameId; + return ScenePtr(scene); } @@ -83,10 +85,23 @@ namespace AZ return nullptr; } + Scene* Scene::GetSceneForEntityId(AZ::EntityId entityId) + { + // Find the entity context for the entity ID. + AzFramework::EntityContextId entityContextId = AzFramework::EntityContextId::CreateNull(); + AzFramework::EntityIdContextQueryBus::EventResult(entityContextId, entityId, &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId); + + if (!entityContextId.IsNull()) + { + return GetSceneForEntityContextId(entityContextId); + } + return nullptr; + } + Scene::Scene() { - m_id = Uuid::CreateRandom(); + m_id = AZ::Uuid::CreateRandom(); m_cullingScene = aznew CullingScene(); SceneRequestBus::Handler::BusConnect(m_id); m_drawFilterTagRegistry = RHI::DrawFilterTagRegistry::Create(); @@ -299,7 +314,6 @@ namespace AZ // Force to update the lookup table since adding render pipeline would effect any pipeline states created before pass system tick RebuildPipelineStatesLookup(); - AZ_Assert(!m_id.IsNull(), "RPI::Scene needs to have a valid uuid."); SceneNotificationBus::Event(m_id, &SceneNotification::OnRenderPipelineAdded, pipeline); } @@ -785,6 +799,11 @@ namespace AZ { return m_id; } + + AZ::Name Scene::GetName() const + { + return m_name; + } bool Scene::SetDefaultRenderPipeline(const RenderPipelineId& pipelineId) { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp index 2b39a87623..27d468e64b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp @@ -43,6 +43,7 @@ namespace AtomToolsFramework &PreviewerFeatureProcessorProviderBus::Handler::GetRequiredFeatureProcessors, featureProcessors); AZ::RPI::SceneDescriptor sceneDesc; + sceneDesc.m_nameId = AZ::Name("PreviewRenderer"); sceneDesc.m_featureProcessorNames.assign(featureProcessors.begin(), featureProcessors.end()); m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); 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 932e2e7436..1784405ffa 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp @@ -279,9 +279,9 @@ namespace MaterialEditor // reset environment AZ::Transform iblTransform = AZ::Transform::CreateIdentity(); AZ::TransformBus::Event(m_iblEntityId, &AZ::TransformBus::Events::SetLocalTM, iblTransform); + const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity(); - AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); - auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); + auto skyBoxFeatureProcessorInterface = AZ::RPI::Scene::GetFeatureProcessorForEntity(m_iblEntityId); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); if (m_behavior) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/RotateEnvironmentBehavior.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/RotateEnvironmentBehavior.cpp index 21d7dee51b..17fb3f3e52 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/RotateEnvironmentBehavior.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/RotateEnvironmentBehavior.cpp @@ -25,8 +25,7 @@ namespace MaterialEditor m_iblEntityId, &MaterialEditorViewportInputControllerRequestBus::Handler::GetIblEntityId); AZ_Assert(m_iblEntityId.IsValid(), "Failed to find m_iblEntityId"); - AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); - m_skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); + m_skyBoxFeatureProcessorInterface = AZ::RPI::Scene::GetFeatureProcessorForEntity(m_iblEntityId); } void RotateEnvironmentBehavior::TickInternal(float x, float y, float z) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 6d6fd377e3..4ad87492e3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -67,6 +67,7 @@ namespace MaterialEditor // Create and register a scene with all available feature processors AZ::RPI::SceneDescriptor sceneDesc; + sceneDesc.m_nameId = AZ::Name("MaterialViewport"); m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); m_scene->EnableAllFeatureProcessors(); diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp index b439ac475c..d822b16486 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp @@ -108,7 +108,7 @@ namespace AZ { m_dynamicDrawManager.reset(); AZ::RPI::ViewportContextManagerNotificationsBus::Handler::BusDisconnect(); - RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); + RPI::Scene* scene = AZ::RPI::Scene::GetSceneForEntityContextId(m_entityContextId); // Check if scene is emptry since scene might be released already when running AtomSampleViewer if (scene) { @@ -157,9 +157,9 @@ namespace AZ void AtomBridgeSystemComponent::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) { - AZ_UNUSED(bootstrapScene); // Make default AtomDebugDisplayViewportInterface - AZStd::shared_ptr mainEntityDebugDisplay = AZStd::make_shared(AzFramework::g_defaultSceneEntityDebugDisplayId); + AZStd::shared_ptr mainEntityDebugDisplay = + AZStd::make_shared(AzFramework::g_defaultSceneEntityDebugDisplayId, bootstrapScene); m_activeViewportsList[AzFramework::g_defaultSceneEntityDebugDisplayId] = mainEntityDebugDisplay; } diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index 39d8933863..12e4ccd8ad 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -256,12 +256,11 @@ namespace AZ::AtomBridge viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler); } - AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress) + AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress, RPI::Scene* scene) { ResetRenderState(); m_viewportId = defaultInstanceAddress; m_defaultInstance = true; - RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); InitInternal(scene, nullptr); } @@ -800,7 +799,8 @@ namespace AZ::AtomBridge const float startAngle = DegToRad(startAngleDegrees); const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); - AZ::Vector3 radiusV3 = AZ::Vector3(radius); + float aspectRadius = radius / GetAspectRatio(); + AZ::Vector3 radiusV3 = AZ::Vector3(aspectRadius, radius, radius); AZ::Vector3 pos = AZ::Vector3(center.GetX(), center.GetY(), z); CreateAxisAlignedArc( lines, diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h index 07f4efdf50..5f902c5884 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h @@ -124,7 +124,7 @@ namespace AZ::AtomBridge AZ_RTTI(AtomDebugDisplayViewportInterface, "{09AF6A46-0100-4FBF-8F94-E6B221322D14}", AzFramework::DebugDisplayRequestBus::Handler); explicit AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr); - explicit AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress); + explicit AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress, RPI::Scene* scene); ~AtomDebugDisplayViewportInterface(); void ResetRenderState(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 2cc8a67cfa..ff6ad7c151 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -133,18 +133,6 @@ namespace AZ typedef std::vector FontEffects; typedef FontEffects::iterator FontEffectsIterator; - struct FontPipelineStateMapKey - { - AZ::RPI::SceneId m_sceneId; // which scene pipeline state is attached to (via Render Pipeline) - AZ::RHI::DrawListTag m_drawListTag; // which render pass this pipeline draws in by default - - bool operator<(const FontPipelineStateMapKey& other) const - { - return m_sceneId < other.m_sceneId - || (m_sceneId == other.m_sceneId && m_drawListTag < other.m_drawListTag); - } - }; - struct FontShaderData { AZ::RHI::ShaderInputNameIndex m_imageInputIndex = "m_texture"; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentController.cpp index ee322c8afd..e844219811 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentController.cpp @@ -48,11 +48,7 @@ namespace AZ void DiffuseGlobalIlluminationComponentController::Activate(EntityId entityId) { - AZ_UNUSED(entityId); - - const RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - m_featureProcessor = scene->GetFeatureProcessor(); - + m_featureProcessor = AZ::RPI::Scene::GetFeatureProcessorForEntity(entityId); OnConfigChanged(); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp index b4131894f4..2611021359 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp @@ -79,7 +79,7 @@ namespace AZ m_entityId = entityId; m_dirty = true; - RPI::ScenePtr scene = RPI::RPISystemInterface::Get()->GetDefaultScene(); + RPI::Scene* scene = RPI::Scene::GetSceneForEntityId(m_entityId); if (scene) { AZ::RPI::SceneNotificationBus::Handler::BusConnect(scene->GetId()); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp index e86c909121..a0577c6240 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp @@ -357,8 +357,7 @@ namespace AZ void DisplayMapperComponentController::OnConfigChanged() { // Register the configuration with the AcesDisplayMapperFeatureProcessor for this scene. - const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - DisplayMapperFeatureProcessorInterface* fp = scene->GetFeatureProcessor(); + DisplayMapperFeatureProcessorInterface* fp = AZ::RPI::Scene::GetFeatureProcessorForEntity(m_entityId); DisplayMapperConfigurationDescriptor desc; desc.m_operationType = m_configuration.m_displayMapperOperation; desc.m_ldrGradingLutEnabled = m_configuration.m_ldrColorGradingLutEnabled; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.h index e789b6dc80..5b060198dc 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkinnedMesh/SkinnedMeshDebugDisplay.h @@ -48,7 +48,7 @@ namespace AZ // CVar for toggling the display of the scene stats int r_skinnedMeshDisplaySceneStats = 0; // SceneId to query for the stats - RPI::SceneId m_sceneId = RPI::SceneId::CreateNull(); + RPI::SceneId m_sceneId; }; }// namespace Render }// namespace AZ diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index faa033956a..eb99b8171a 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -60,6 +60,7 @@ namespace EMStudio // Create and register a scene with all available feature processors AZ::RPI::SceneDescriptor sceneDesc; + sceneDesc.m_nameId = AZ::Name("AnimViewport"); m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); m_scene->EnableAllFeatureProcessors(); @@ -213,8 +214,7 @@ namespace EMStudio AZ::TransformBus::Event(m_iblEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, iblTransform); const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity(); - AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); - auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); + auto skyBoxFeatureProcessorInterface = m_scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); } diff --git a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp index 00629eb65d..4c0f15463a 100644 --- a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp +++ b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp @@ -255,19 +255,22 @@ namespace Blast BlastFamilyComponentRequestBus::Broadcast( &BlastFamilyComponentRequests::FillDebugRenderBuffer, buffer, m_debugRenderMode); - // This is a system component, and thus is not associated with a specific scene, so use the default scene + // This is a system component, and thus is not associated with a specific scene, so use the bootstrap scene // for the debug drawing - const auto defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); - auto drawQueue = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(defaultScene); - - for (DebugLine& line : buffer.m_lines) + const auto mainScene = AZ::RPI::RPISystemInterface::Get()->GetSceneByName(AZ::Name("Main")); + if (mainScene) { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArguments; - drawArguments.m_verts = &line.m_p0; - drawArguments.m_vertCount = 2; - drawArguments.m_colors = &line.m_color; - drawArguments.m_colorCount = 1; - drawQueue->DrawLines(drawArguments); + auto drawQueue = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(mainScene); + + for (DebugLine& line : buffer.m_lines) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArguments; + drawArguments.m_verts = &line.m_p0; + drawArguments.m_vertCount = 2; + drawArguments.m_colors = &line.m_color; + drawArguments.m_colorCount = 1; + drawQueue->DrawLines(drawArguments); + } } } } diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index b0539900e2..3476c530b2 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -65,7 +65,7 @@ CDraw2d::~CDraw2d() } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) +void CDraw2d::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) { // At this point the RPI is ready for use @@ -74,16 +74,16 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc AZ::Data::Instance shader = AZ::RPI::LoadCriticalShader(shaderFilepath); // Set scene to be associated with the dynamic draw context - AZ::RPI::ScenePtr scene; + AZ::RPI::Scene* scene = nullptr; if (m_viewportContext) { // Use scene associated with the specified viewport context - scene = m_viewportContext->GetRenderScene(); + scene = m_viewportContext->GetRenderScene().get(); } else { - // No viewport context specified, use default scene - scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); + // No viewport context specified, use main scene + scene = bootstrapScene; } AZ_Assert(scene != nullptr, "Attempting to create a DynamicDrawContext for a viewport context that has not been associated with a scene yet."); @@ -113,7 +113,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc else { // Render target support is disabled - m_dynamicDraw->SetOutputScope(scene.get()); + m_dynamicDraw->SetOutputScope(scene); } m_dynamicDraw->EndInit(); diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index 2cee4e92eb..19c6e4281e 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -653,12 +653,12 @@ void CLyShine::OnRenderTick() } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CLyShine::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) +void CLyShine::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) { // Load cursor if its path was set before RPI was initialized LoadUiCursor(); - LyShinePassDataRequestBus::Handler::BusConnect(AZ::RPI::RPISystemInterface::Get()->GetDefaultScene()->GetId()); + LyShinePassDataRequestBus::Handler::BusConnect(bootstrapScene->GetId()); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 3111f31615..98b376ec8b 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -52,7 +52,7 @@ bool UiRenderer::IsReady() return m_isRPIReady; } -void UiRenderer::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) +void UiRenderer::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) { // At this point the RPI is ready for use @@ -64,16 +64,17 @@ void UiRenderer::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstra if (m_viewportContext) { // Create a new scene based on the user specified viewport context - m_scene = CreateScene(m_viewportContext); + m_ownedScene = CreateScene(m_viewportContext); + m_scene = m_ownedScene.get(); } else { // No viewport context specified, use default scene - m_scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); + m_scene = bootstrapScene; } // Create a dynamic draw context for UI Canvas drawing for the scene - m_dynamicDraw = CreateDynamicDrawContext(m_scene, uiShader); + m_dynamicDraw = CreateDynamicDrawContext(uiShader); if (m_dynamicDraw) { @@ -93,6 +94,7 @@ AZ::RPI::ScenePtr UiRenderer::CreateScene(AZStd::shared_ptrEnableAllFeatureProcessors(); // LYSHINE_ATOM_TODO - have a UI pipeline and enable only needed fps @@ -116,7 +118,6 @@ AZ::RPI::ScenePtr UiRenderer::CreateScene(AZStd::shared_ptr UiRenderer::CreateDynamicDrawContext( - AZ::RPI::ScenePtr scene, AZ::Data::Instance uiShader) { // Find the pass that renders the UI canvases after the rtt passes @@ -144,7 +145,7 @@ AZ::RHI::Ptr UiRenderer::CreateDynamicDrawContext( else { // Render target support is disabled - dynamicDraw->SetOutputScope(m_scene.get()); + dynamicDraw->SetOutputScope(m_scene); } dynamicDraw->EndInit(); diff --git a/Gems/LyShine/Code/Source/UiRenderer.h b/Gems/LyShine/Code/Source/UiRenderer.h index 3be3c832d3..0e15d41907 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.h +++ b/Gems/LyShine/Code/Source/UiRenderer.h @@ -152,7 +152,6 @@ private: // member functions //! Create a dynamic draw context for this renderer AZ::RHI::Ptr CreateDynamicDrawContext( - AZ::RPI::ScenePtr scene, AZ::Data::Instance uiShader); //! Bind the global white texture for all the texture units we use @@ -175,7 +174,8 @@ protected: // attributes // Set by user when viewport context is not the main/default viewport AZStd::shared_ptr m_viewportContext; - AZ::RPI::ScenePtr m_scene; + AZ::RPI::ScenePtr m_ownedScene; + AZ::RPI::Scene* m_scene = nullptr; #ifndef _RELEASE int m_debugTextureDataRecordLevel = 0; diff --git a/Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_blinds.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Blinds.fbx.assetinfo similarity index 100% rename from Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_blinds.fbx.assetinfo rename to Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Blinds.fbx.assetinfo diff --git a/Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_blinds_broken.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Blinds_Broken.fbx.assetinfo similarity index 100% rename from Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_blinds_broken.fbx.assetinfo rename to Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Blinds_Broken.fbx.assetinfo diff --git a/Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_corners_four.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Corners_Four.fbx.assetinfo similarity index 100% rename from Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_corners_four.fbx.assetinfo rename to Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Corners_Four.fbx.assetinfo diff --git a/Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_corners_two.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Corners_Two.fbx.assetinfo similarity index 100% rename from Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_corners_two.fbx.assetinfo rename to Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Corners_Two.fbx.assetinfo diff --git a/Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_edge.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Edge.fbx.assetinfo similarity index 100% rename from Gems/NvCloth/Assets/Objects/cloth/Environment/cloth_locked_edge.fbx.assetinfo rename to Gems/NvCloth/Assets/Objects/cloth/Environment/Cloth_Locked_Edge.fbx.assetinfo diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp index d33b453c01..2ed05b4dfe 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp @@ -102,7 +102,9 @@ namespace UnitTest prefabBuilderComponent.Activate(); AZStd::vector jobProducts; - auto&& prefabDom = prefabSystemComponentInterface->FindTemplateDom(parentInstance->GetTemplateId()); + // Make a copy of the template DOM, as the prefab system still owns the existing template + AzToolsFramework::Prefab::PrefabDom prefabDom; + prefabDom.CopyFrom(prefabSystemComponentInterface->FindTemplateDom(parentInstance->GetTemplateId()), prefabDom.GetAllocator(), false); ASSERT_TRUE(prefabBuilderComponent.ProcessPrefab({AZ::Crc32("pc")}, "parent.prefab", "unused", AZ::Uuid(), prefabDom, jobProducts)); diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli index 72c1af953c..cd680f721a 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli @@ -218,9 +218,10 @@ float4x4 GetObject_WorldMatrix() float GetHeight(float2 origUv) { - float2 uv = clamp(origUv + (ObjectSrg::m_terrainData.m_uvStep * 0.5f), 0.0f, 1.0f); - float height = 0.0f; + float2 halfStep = ObjectSrg::m_terrainData.m_uvStep * 0.5; + float2 uv = origUv * (1.0 - ObjectSrg::m_terrainData.m_uvStep) + halfStep; + float height = 0.0f; if (o_useTerrainSmoothing) { float2 textureSize; diff --git a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp index 06b7320a06..e9c9874af5 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp @@ -164,14 +164,17 @@ namespace Terrain // could just make this list a prioritized list from top to bottom for any points that overlap. for (auto& gradientId : m_configuration.m_gradientEntities) { - // If gradients ever provide bounds, or if we add a value threshold in this component, it would be possible for terrain - // to *not* exist at a specific point. - terrainExists = true; + if (gradientId.IsValid()) + { + // If gradients ever provide bounds, or if we add a value threshold in this component, it would be possible for terrain + // to *not* exist at a specific point. + terrainExists = true; - float sample = 0.0f; - GradientSignal::GradientRequestBus::EventResult( - sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params); - maxSample = AZ::GetMax(maxSample, sample); + float sample = 0.0f; + GradientSignal::GradientRequestBus::EventResult( + sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params); + maxSample = AZ::GetMax(maxSample, sample); + } } m_isRequestInProgress = false; } diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index e140129563..79fd5509f2 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -218,6 +218,12 @@ namespace Terrain AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution); + // Take the dirty region and adjust the Z values to the world min/max so that even if the dirty region falls outside the current + // world bounds, we still update the wireframe accordingly. + AZ::Aabb dirtyRegion2D = AZ::Aabb::CreateFromMinMaxValues( + dirtyRegion.GetMin().GetX(), dirtyRegion.GetMin().GetY(), worldBounds.GetMin().GetZ(), + dirtyRegion.GetMax().GetX(), dirtyRegion.GetMax().GetY(), worldBounds.GetMax().GetZ()); + // Calculate the world size of each sector. Note that this size actually ends at the last point, not the last square. // So for example, the sector size for 3 points will go from (*--*--*) even though it will be used to draw (*--*--*--). const float xSectorSize = (queryResolution.GetX() * SectorSizeInGridPoints); @@ -230,7 +236,7 @@ namespace Terrain // If we haven't cached anything before, or if the world bounds has changed, clear our cache structure and repopulate it // with WireframeSector entries with the proper AABB sizes. - if (!m_wireframeBounds.IsValid() || !dirtyRegion.IsValid() || !m_wireframeBounds.IsClose(worldBounds)) + if (!m_wireframeBounds.IsValid() || !dirtyRegion2D.IsValid() || !m_wireframeBounds.IsClose(worldBounds)) { m_wireframeBounds = worldBounds; @@ -266,7 +272,7 @@ namespace Terrain // For each sector, if it overlaps with the dirty region, clear it out and recache the wireframe line data. for (auto& sector : m_wireframeSectors) { - if (dirtyRegion.IsValid() && !dirtyRegion.Overlaps(sector.m_aabb)) + if (dirtyRegion2D.IsValid() && !dirtyRegion2D.Overlaps(sector.m_aabb)) { continue; } diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldRendererComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldRendererComponent.cpp index 9cd9ce9fb2..5afaedc517 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldRendererComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldRendererComponent.cpp @@ -46,6 +46,7 @@ namespace Terrain ->EnumAttribute(TerrainWorldRendererConfig::WorldSize::_4096Meters, "4 Kilometers") ->EnumAttribute(TerrainWorldRendererConfig::WorldSize::_8192Meters, "8 Kilometers") ->EnumAttribute(TerrainWorldRendererConfig::WorldSize::_16384Meters, "16 Kilometers") + ->Attribute(AZ::Edit::Attributes::Visibility, false) // Keeping invisible until it's hooked up under the hood ; } } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 73f1c3967c..55713e696a 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -417,10 +417,10 @@ namespace Terrain m_areaData.m_rebuildSectors = false; m_sectorData.clear(); - const float xFirstPatchStart = terrainBounds.GetMin().GetX() - fmod(terrainBounds.GetMin().GetX(), GridMeters); - const float xLastPatchStart = terrainBounds.GetMax().GetX() - fmod(terrainBounds.GetMax().GetX(), GridMeters); - const float yFirstPatchStart = terrainBounds.GetMin().GetY() - fmod(terrainBounds.GetMin().GetY(), GridMeters); - const float yLastPatchStart = terrainBounds.GetMax().GetY() - fmod(terrainBounds.GetMax().GetY(), GridMeters); + const float xFirstPatchStart = AZStd::floorf(terrainBounds.GetMin().GetX() / GridMeters) * GridMeters; + const float xLastPatchStart = AZStd::floorf(terrainBounds.GetMax().GetX() / GridMeters) * GridMeters; + const float yFirstPatchStart = AZStd::floorf(terrainBounds.GetMin().GetY() / GridMeters) * GridMeters; + const float yLastPatchStart = AZStd::floorf(terrainBounds.GetMax().GetY() / GridMeters) * GridMeters; const auto& materialAsset = m_materialInstance->GetAsset(); const auto& shaderAsset = materialAsset->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg(); @@ -603,7 +603,7 @@ namespace Terrain // For every distance doubling beyond a minDistanceForLod0, we only need half the mesh density. Each LOD // is exactly half the resolution of the last. - const float lodForCamera = floorf(AZ::GetMax(0.0f, log2f(sectorDistance / minDistanceForLod0))); + const float lodForCamera = AZStd::floorf(AZ::GetMax(0.0f, log2f(sectorDistance / minDistanceForLod0))); // All cameras should render the same LOD so effects like shadows are consistent. lodChoice = AZ::GetMin(lodChoice, aznumeric_cast(lodForCamera)); diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 8d39340b06..20041e2fc8 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -222,20 +222,31 @@ float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, boo float TerrainSystem::GetTerrainAreaHeight(float x, float y, bool& terrainExists) const { - AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); - float height = m_currentSettings.m_worldBounds.GetMin().GetZ(); + const float worldMin = m_currentSettings.m_worldBounds.GetMin().GetZ(); + AZ::Vector3 inPosition(x, y, worldMin); + float height = worldMin; + terrainExists = false; AZStd::shared_lock lock(m_areaMutex); - for (auto& [areaId, areaBounds] : m_registeredAreas) + for (auto& [areaId, areaData] : m_registeredAreas) { - inPosition.SetZ(areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) + const float areaMin = areaData.m_areaBounds.GetMin().GetZ(); + inPosition.SetZ(areaMin); + if (areaData.m_areaBounds.Contains(inPosition)) { AZ::Vector3 outPosition; Terrain::TerrainAreaHeightRequestBus::Event( areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, terrainExists); height = outPosition.GetZ(); + if (!terrainExists) + { + // If the terrain height provider doesn't have any data, then check the area's "use ground plane" setting. + // If it's set, then create a default ground plane by saying terrain exists at the minimum height for the area. + // Otherwise, we'll set the height at the terrain world minimum and say it doesn't exist. + terrainExists = areaData.m_useGroundPlane; + height = areaData.m_useGroundPlane ? areaMin : worldMin; + } break; } } @@ -395,12 +406,12 @@ AZ::EntityId TerrainSystem::FindBestAreaEntityAtPosition(float x, float y, AZ::A AZStd::shared_lock lock(m_areaMutex); // The areas are sorted into priority order: the first area that contains inPosition is the most suitable. - for (const auto& [areaId, areaBounds] : m_registeredAreas) + for (const auto& [areaId, areaData] : m_registeredAreas) { - inPosition.SetZ(areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) + inPosition.SetZ(areaData.m_areaBounds.GetMin().GetZ()); + if (areaData.m_areaBounds.Contains(inPosition)) { - bounds = areaBounds; + bounds = areaData.m_areaBounds; return areaId; } } @@ -548,7 +559,12 @@ void TerrainSystem::RegisterArea(AZ::EntityId areaId) AZStd::unique_lock lock(m_areaMutex); AZ::Aabb aabb = AZ::Aabb::CreateNull(); LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); - m_registeredAreas[areaId] = aabb; + + // Cache off whether or not this layer spawner should have a default ground plane when no other terrain height data exists. + bool useGroundPlane = false; + Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, areaId, &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + + m_registeredAreas[areaId] = { aabb, useGroundPlane }; m_dirtyRegion.AddAabb(aabb); m_terrainHeightDirty = true; m_terrainSurfacesDirty = true; @@ -565,10 +581,10 @@ void TerrainSystem::UnregisterArea(AZ::EntityId areaId) m_registeredAreas, [areaId, this](const auto& item) { - auto const& [entityId, aabb] = item; + auto const& [entityId, areaData] = item; if (areaId == entityId) { - m_dirtyRegion.AddAabb(aabb); + m_dirtyRegion.AddAabb(areaData.m_areaBounds); m_terrainHeightDirty = true; m_terrainSurfacesDirty = true; return true; @@ -585,10 +601,10 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId, AzFramework::Terrain::Terra auto areaAabb = m_registeredAreas.find(areaId); - AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second : AZ::Aabb::CreateNull(); + AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second.m_areaBounds : AZ::Aabb::CreateNull(); AZ::Aabb newAabb = AZ::Aabb::CreateNull(); LmbrCentral::ShapeComponentRequestsBus::EventResult(newAabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); - m_registeredAreas[areaId] = newAabb; + m_registeredAreas[areaId].m_areaBounds = newAabb; AZ::Aabb expandedAabb = oldAabb; expandedAabb.AddAabb(newAabb); diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index 022cd218cc..c6bd19fdda 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -168,7 +168,14 @@ namespace Terrain bool m_terrainSurfacesDirty = false; AZ::Aabb m_dirtyRegion; + // Cached data for each terrain area to use when looking up terrain data. + struct TerrainAreaData + { + AZ::Aabb m_areaBounds{ AZ::Aabb::CreateNull() }; + bool m_useGroundPlane{ false }; + }; + mutable AZStd::shared_mutex m_areaMutex; - AZStd::map m_registeredAreas; + AZStd::map m_registeredAreas; }; } // namespace Terrain