From 3c315df36f5bc086806efda05b8cdec0131ecbd6 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 5 May 2021 16:47:44 -0700 Subject: [PATCH 01/17] Fix Camera transform property notifications. Moves transform notification logic from CComponentEntityObject::InvalidateTM (which will eventually go away) to AzToolsFramework::TransformComponent::OnTransformChanged. We also specifically make sure PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged fires, which is used by Track View to detect camera position changes. --- .../ToolsComponents/TransformComponent.cpp | 19 ++++++++++++++++++- .../Objects/ComponentEntityObject.cpp | 8 -------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index f8d02b6581..6ce797c3ee 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -253,7 +253,7 @@ namespace AzToolsFramework m_localTransformDirty = true; m_worldTransformDirty = true; - if (GetEntity()) + if (const AZ::Entity* entity = GetEntity()) { SetDirty(); @@ -265,6 +265,23 @@ namespace AzToolsFramework AZ::TransformNotificationBus::Event( GetEntityId(), &TransformNotification::OnTransformChanged, localTM, worldTM); + + // Fire a property changed notification for this component + if (const AZ::Component* component = entity->FindComponent()) + { + PropertyEditorEntityChangeNotificationBus::Event( + GetEntityId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged, component->GetId()); + } + + // Refresh the property editor if we're selected + bool selected = false; + ToolsApplicationRequestBus::BroadcastResult( + selected, &AzToolsFramework::ToolsApplicationRequests::IsSelected, GetEntityId()); + if (selected) + { + ToolsApplicationEvents::Bus::Broadcast( + &ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values); + } } } diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index c85ed1248f..20ae0a74cd 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -609,14 +609,6 @@ void CComponentEntityObject::InvalidateTM(int nWhyFlags) { Matrix34 worldTransform = GetWorldTM(); EBUS_EVENT_ID(m_entityId, AZ::TransformBus, SetWorldTM, LYTransformToAZTransform(worldTransform)); - - // When transformed via the editor, make sure the entity is marked dirty for undo capture. - EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, AddDirtyEntity, m_entityId); - - if (CheckFlags(OBJFLAG_SELECTED)) - { - EBUS_EVENT(AzToolsFramework::ToolsApplicationEvents::Bus, InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values); - } } } } From dca2294b362538a03f4566dd9e4d76634d16c9b1 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 5 May 2021 16:51:49 -0700 Subject: [PATCH 02/17] Move GetCameraTransform into RPI::View. --- Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h | 2 ++ Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp | 9 +++++++++ Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp | 7 +------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h index d6146d3760..aad099dc23 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h @@ -91,6 +91,8 @@ namespace AZ const AZ::Matrix4x4& GetViewToWorldMatrix() const; const AZ::Matrix4x4& GetViewToClipMatrix() const; const AZ::Matrix4x4& GetWorldToClipMatrix() const; + //! Get the camera's world transform, converted from the viewToWorld matrix's native y-up to z-up + AZ::Transform GetCameraTransform() const; //! Finalize draw lists in this view. This function should only be called when all //! draw packets for current frame are added. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index e3f41cbda9..85216707a8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -110,6 +110,15 @@ namespace AZ InvalidateSrg(); } + AZ::Transform View::GetCameraTransform() const + { + const Quaternion zUpToYUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi); + return AZ::Transform::CreateFromQuaternionAndTranslation( + Quaternion::CreateFromMatrix4x4(m_worldToViewMatrix) * zUpToYUp, + m_worldToViewMatrix.GetTranslation() + ).GetOrthogonalized(); + } + void View::SetCameraTransform(const AZ::Matrix3x4& cameraTransform) { m_position = cameraTransform.GetTranslation(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index b5d3f815fe..b2f9acb855 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -192,12 +192,7 @@ namespace AZ AZ::Transform ViewportContext::GetCameraTransform() const { - const Matrix4x4& worldToViewMatrix = GetDefaultView()->GetViewToWorldMatrix(); - const Quaternion zUpToYUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi); - return AZ::Transform::CreateFromQuaternionAndTranslation( - Quaternion::CreateFromMatrix4x4(worldToViewMatrix) * zUpToYUp, - worldToViewMatrix.GetTranslation() - ).GetOrthogonalized(); + return GetDefaultView()->GetCameraTransform(); } void ViewportContext::SetCameraTransform(const AZ::Transform& transform) From 5d9c99436a81cabeff5758a22f86522acfc63265 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 5 May 2021 16:54:31 -0700 Subject: [PATCH 03/17] Ensure CameraComponentController entities get synced with Atom camera changes. This ensures the camera entity's transform gets correctly set if the RPI::View (or ViewportContext) is directly used instead of adjusting the entity transform, for e.g. camera controllers. --- .../Code/Source/CameraComponentController.cpp | 18 ++++++++++++++++++ .../Code/Source/CameraComponentController.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index 2799d897d6..3dcee68169 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -160,6 +160,17 @@ namespace Camera incompatible.push_back(AZ_CRC("CameraService", 0x1dd1caa4)); } + void CameraComponentController::Init() + { + m_onViewMatrixChanged = AZ::Event::Handler([this](const AZ::Matrix4x4&) + { + if (!m_updatingTransformFromEntity) + { + AZ::TransformBus::Event(m_entityId, &AZ::TransformInterface::SetWorldTM, m_atomCamera->GetCameraTransform()); + } + }); + } + void CameraComponentController::Activate(AZ::EntityId entityId) { m_entityId = entityId; @@ -218,6 +229,8 @@ namespace Camera } } AZ::RPI::ViewProviderBus::Handler::BusConnect(m_entityId); + + m_atomCamera->ConnectWorldToViewMatrixChangedHandler(m_onViewMatrixChanged); } UpdateCamera(); @@ -258,6 +271,7 @@ namespace Camera if (atomViewportRequests) { AZ::RPI::ViewProviderBus::Handler::BusDisconnect(m_entityId); + m_onViewMatrixChanged.Disconnect(); } DeactivateAtomView(); @@ -376,7 +390,9 @@ namespace Camera if (m_atomCamera) { + m_updatingTransformFromEntity = true; m_atomCamera->SetCameraTransform(AZ::Matrix3x4::CreateFromTransform(world.GetOrthogonalized())); + m_updatingTransformFromEntity = false; } } @@ -425,7 +441,9 @@ namespace Camera m_config.m_nearClipDistance, m_config.m_farClipDistance, true); + m_updatingTransformFromEntity = true; m_atomCamera->SetViewToClipMatrix(viewToClipMatrix); + m_updatingTransformFromEntity = false; } } diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 92e1354f17..cae6ad4663 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -77,6 +77,7 @@ namespace Camera static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + void Init(); void Activate(AZ::EntityId entityId); void Deactivate(); void SetConfiguration(const CameraComponentConfig& config); @@ -121,6 +122,8 @@ namespace Camera // Atom integration AZ::RPI::ViewPtr m_atomCamera; AZ::RPI::AuxGeomDrawPtr m_atomAuxGeom; + AZ::Event::Handler m_onViewMatrixChanged; + bool m_updatingTransformFromEntity = false; // Cry view integration IView* m_view = nullptr; From 64d53d1fabc4aa9d2fcad9c7506ce9dc78b26ec8 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Mon, 10 May 2021 15:53:11 -0700 Subject: [PATCH 04/17] Fix View::GetCameraTransform --- Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index 85216707a8..21a46693d5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -112,10 +112,10 @@ namespace AZ AZ::Transform View::GetCameraTransform() const { - const Quaternion zUpToYUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi); + static const Quaternion yUpToZUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi); return AZ::Transform::CreateFromQuaternionAndTranslation( - Quaternion::CreateFromMatrix4x4(m_worldToViewMatrix) * zUpToYUp, - m_worldToViewMatrix.GetTranslation() + Quaternion::CreateFromMatrix4x4(m_viewToWorldMatrix) * yUpToZUp, + m_viewToWorldMatrix.GetTranslation() ).GetOrthogonalized(); } @@ -127,7 +127,7 @@ namespace AZ // is in a Z-up world and an identity matrix means that it faces along the positive-Y axis and Z is up. // An identity view matrix on the other hand looks along the negative Z-axis. // So we adjust for this by rotating the camera world matrix by 90 degrees around the X axis. - AZ::Matrix3x4 zUpToYUp = AZ::Matrix3x4::CreateRotationX(AZ::Constants::HalfPi); + static AZ::Matrix3x4 zUpToYUp = AZ::Matrix3x4::CreateRotationX(AZ::Constants::HalfPi); AZ::Matrix3x4 yUpWorld = cameraTransform * zUpToYUp; float viewToWorldMatrixRaw[16] = { From 7ff5c0e10526a1297e5248f8819c8e5f61604c9d Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 11 May 2021 12:18:04 -0700 Subject: [PATCH 05/17] Add multiline spacing and GetTextSize to Atom Font --- Code/CryEngine/CryCommon/IFont.h | 4 + .../AzFramework/Font/FontInterface.h | 4 + .../AtomLyIntegration/AtomFont/FFont.h | 14 +++ .../AtomFont/Code/Source/FFont.cpp | 93 ++++++++++++------- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/Code/CryEngine/CryCommon/IFont.h b/Code/CryEngine/CryCommon/IFont.h index c8634fa854..7d573308aa 100644 --- a/Code/CryEngine/CryCommon/IFont.h +++ b/Code/CryEngine/CryCommon/IFont.h @@ -150,6 +150,7 @@ struct STextDrawContext Vec2 m_size; Vec2i m_requestSize; float m_widthScale; + float m_lineSpacing; float m_clipX; float m_clipY; @@ -180,6 +181,7 @@ struct STextDrawContext , m_size(16.0f, 16.0f) , m_requestSize(static_cast(m_size.x), static_cast(m_size.y)) , m_widthScale(1.0f) + , m_lineSpacing(0.f) , m_clipX(0) , m_clipY(0) , m_clipWidth(0) @@ -214,11 +216,13 @@ struct STextDrawContext void SetTransform(const Matrix34& transform) { m_transform = transform; } void SetBaseState(int baseState) { m_baseState = baseState; } void SetOverrideViewProjMatrices(bool overrideViewProjMatrices) { m_overrideViewProjMatrices = overrideViewProjMatrices; } + void SetLineSpacing(float lineSpacing) { m_lineSpacing = lineSpacing; } float GetCharWidth() const { return m_size.x; } float GetCharHeight() const { return m_size.y; } float GetCharWidthScale() const { return m_widthScale; } int GetFlags() const { return m_drawTextFlags; } + float GetLineSpacing() const { return m_lineSpacing; } bool IsColorOverridden() const { return m_colorOverride.a != 0; } }; diff --git a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h index 7c5bcce6d6..48fa5bc2d2 100644 --- a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h @@ -44,6 +44,7 @@ namespace AzFramework AZ::Vector3 m_position; //! world space position for 3d draws, screen space x,y,depth for 2d. AZ::Color m_color = AZ::Colors::White; //! Color to draw the text AZ::Vector2 m_scale = AZ::Vector2(1.0f); //! font scale + float m_lineSpacing; //! Spacing between new lines, as a percentage of m_scale. TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //! Horizontal text alignment TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //! Vertical text alignment bool m_monospace = false; //! disable character proportional spacing @@ -67,6 +68,9 @@ namespace AzFramework virtual void DrawScreenAlignedText3d( const TextDrawParameters& params, const AZStd::string_view& string) = 0; + virtual AZ::Vector2 GetTextSize( + const TextDrawParameters& params, + const AZStd::string_view& string) = 0; }; class FontQueryInterface diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index fd66534197..83273633be 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -213,6 +213,10 @@ namespace AZ const AzFramework::TextDrawParameters& params, const AZStd::string_view& string) override; + AZ::Vector2 GetTextSize( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) override; + public: FFont(AtomFont* atomFont, const char* fontName); @@ -282,6 +286,16 @@ namespace AZ RPI::WindowContextSharedPtr GetDefaultWindowContext() const; RPI::ViewportContextPtr GetDefaultViewportContext() const; + struct DrawParameters + { + TextDrawContext m_ctx; + AZ::Vector2 m_position; + AZ::Vector2 m_size; + AZ::RPI::ViewportContext* m_viewportContext; + const AZ::RHI::Viewport* m_viewport; + }; + DrawParameters ExtractDrawParameters(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string, bool forceCalculateSize); + private: static constexpr uint32_t NumBuffers = 2; static constexpr float WindowScaleWidth = 800.0f; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 40684640d6..48d24f0473 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -505,7 +505,7 @@ Vec2 AZ::FFont::GetTextSizeUInternal( } charX = offset.x; - charY += size.y; + charY += size.y * (1.f + ctx.GetLineSpacing()); if (charY > maxH) { @@ -944,7 +944,7 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float case '\n': { charX = baseXY.x + offset.x; - charY += size.y; + charY += size.y * (1.f + ctx.GetLineSpacing()); continue; } break; @@ -1674,47 +1674,47 @@ static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::T } } -void AZ::FFont::DrawScreenAlignedText2d( - const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) +AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string, bool forceCalculateSize) { + DrawParameters internalParams; if (params.m_drawViewportId == AzFramework::InvalidViewportId || string.empty()) { - return; + return internalParams; } //Code mostly duplicated from CRenderer::Draw2dTextWithDepth float posX = params.m_position.GetX(); float posY = params.m_position.GetY(); - AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); - const AZ::RHI::Viewport& viewport = viewportContext->GetWindowContext()->GetViewport(); + internalParams.m_viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + const AZ::RHI::Viewport& viewport = internalParams.m_viewportContext->GetWindowContext()->GetViewport(); + internalParams.m_viewport = &viewport; if (params.m_virtual800x600ScreenSize) { posX *= WindowScaleWidth / (viewport.m_maxX - viewport.m_minX); posY *= WindowScaleHeight / (viewport.m_maxY - viewport.m_minY); } - TextDrawContext ctx; - ctx.SetBaseState(GS_NODEPTHTEST); - ctx.SetColor(AZColorToLYColorF(params.m_color)); - ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f); - ctx.EnableFrame(false); - ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow); - ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize); - ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale)); + internalParams.m_ctx.SetBaseState(GS_NODEPTHTEST); + internalParams.m_ctx.SetColor(AZColorToLYColorF(params.m_color)); + internalParams.m_ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f); + internalParams.m_ctx.EnableFrame(false); + internalParams.m_ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow); + internalParams.m_ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize); + internalParams.m_ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale)); + internalParams.m_ctx.SetLineSpacing(params.m_lineSpacing); if (params.m_monospace || !params.m_scaleWithWindow) { ScaleCoord(viewport, posX, posY); } if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left || - params.m_vAlign != AzFramework::TextVerticalAlignment::Top) + params.m_vAlign != AzFramework::TextVerticalAlignment::Top || + forceCalculateSize) { - Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, ctx); - + Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, internalParams.m_ctx); // If we're using virtual 800x600 coordinates, convert the text size from // pixels to that before using it as an offset. - if (ctx.m_sizeIn800x600) + if (internalParams.m_ctx.m_sizeIn800x600) { float width = 1.0f; float height = 1.0f; @@ -1740,19 +1740,33 @@ void AZ::FFont::DrawScreenAlignedText2d( { posY -= textSize.y; } + internalParams.m_size = AZ::Vector2{textSize.x, textSize.y}; + } + SetCommonContextFlags(internalParams.m_ctx, params); + internalParams.m_ctx.m_drawTextFlags |= eDrawText_2D; + internalParams.m_position = AZ::Vector2{posX, posY}; + return internalParams; +} + +void AZ::FFont::DrawScreenAlignedText2d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) +{ + DrawParameters internalParams = ExtractDrawParameters(params, string, false); + if (!internalParams.m_viewportContext) + { + return; } - SetCommonContextFlags(ctx, params); - ctx.m_drawTextFlags |= eDrawText_2D; DrawStringUInternal( - viewport, - viewportContext, - posX, - posY, + *internalParams.m_viewport, + internalParams.m_viewportContext, + internalParams.m_position.GetX(), + internalParams.m_position.GetY(), params.m_position.GetZ(), // Z string.data(), params.m_multiline, - ctx + internalParams.m_ctx ); } @@ -1760,13 +1774,12 @@ void AZ::FFont::DrawScreenAlignedText3d( const AzFramework::TextDrawParameters& params, const AZStd::string_view& string) { - if (params.m_drawViewportId == AzFramework::InvalidViewportId || - string.empty()) + DrawParameters internalParams = ExtractDrawParameters(params, string, false); + if (!internalParams.m_viewportContext) { return; } - AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); - AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView(); + AZ::RPI::ViewPtr currentView = internalParams.m_viewportContext->GetDefaultView(); if (!currentView) { return; @@ -1778,7 +1791,23 @@ void AZ::FFont::DrawScreenAlignedText3d( ); AzFramework::TextDrawParameters param2d = params; param2d.m_position = positionNDC; - DrawScreenAlignedText2d(param2d, string); + + DrawStringUInternal( + *internalParams.m_viewport, + internalParams.m_viewportContext, + internalParams.m_position.GetX(), + internalParams.m_position.GetY(), + params.m_position.GetZ(), // Z + string.data(), + params.m_multiline, + internalParams.m_ctx + ); +} + +AZ::Vector2 AZ::FFont::GetTextSize(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string) +{ + DrawParameters sizeParams = ExtractDrawParameters(params, string, true); + return sizeParams.m_size; } #endif //USE_NULLFONT_ALWAYS From fe2931829338c9e6805050533056417a2f2d2686 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 11 May 2021 12:18:49 -0700 Subject: [PATCH 06/17] Make ScriptTimePoint::Get const correct --- Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h b/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h index 7cb81829ef..08c997de2d 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h +++ b/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h @@ -43,7 +43,7 @@ namespace AZ return AZStd::string::format("Time %llu", m_timePoint.time_since_epoch().count()); } - const AZStd::chrono::system_clock::time_point& Get() { return m_timePoint; } + const AZStd::chrono::system_clock::time_point& Get() const { return m_timePoint; } // Returns the time point in seconds double GetSeconds() const From 3c5659668a0cd4343b7b7f86f56a3092328a4714 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 11 May 2021 12:19:56 -0700 Subject: [PATCH 07/17] Add AZ::RPI::ViewportContextRequests alias for the full interface --- Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h index bc7e5a4b1d..377c1d5c4e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h @@ -92,6 +92,8 @@ namespace AZ virtual ViewPtr GetCurrentView(const Name& contextName) const = 0; }; + using ViewportContextRequests = AZ::Interface; + class ViewportContextManagerNotifications : public AZ::EBusTraits { From cdca18ca2590ddd46217398a3d63c5a5ffac7328 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 11 May 2021 18:26:05 -0700 Subject: [PATCH 08/17] Use a smart viewport context pointer in AtomFont to avoid a crash --- .../Code/Include/AtomLyIntegration/AtomFont/FFont.h | 4 ++-- Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 83273633be..84d53a5446 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -237,7 +237,7 @@ namespace AZ void Prepare(const char* str, bool updateTexture, const AtomFont::GlyphSize& glyphSize = AtomFont::defaultGlyphSize); void DrawStringUInternal( const RHI::Viewport& viewport, - RPI::ViewportContext* viewportContext, + RPI::ViewportContextPtr viewportContext, float x, float y, float z, @@ -291,7 +291,7 @@ namespace AZ TextDrawContext m_ctx; AZ::Vector2 m_position; AZ::Vector2 m_size; - AZ::RPI::ViewportContext* m_viewportContext; + AZ::RPI::ViewportContextPtr m_viewportContext; const AZ::RHI::Viewport* m_viewport; }; DrawParameters ExtractDrawParameters(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string, bool forceCalculateSize); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 48d24f0473..faeed52fb0 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -280,7 +280,7 @@ void AZ::FFont::DrawString(float x, float y, const char* str, const bool asciiMu return; } - DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext().get(), x, y, 1.0f, str, asciiMultiLine, ctx); + DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext(), x, y, 1.0f, str, asciiMultiLine, ctx); } void AZ::FFont::DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) @@ -290,12 +290,12 @@ void AZ::FFont::DrawString(float x, float y, float z, const char* str, const boo return; } - DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext().get(), x, y, z, str, asciiMultiLine, ctx); + DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext(), x, y, z, str, asciiMultiLine, ctx); } void AZ::FFont::DrawStringUInternal( const RHI::Viewport& viewport, - RPI::ViewportContext* viewportContext, + RPI::ViewportContextPtr viewportContext, float x, float y, float z, @@ -1686,7 +1686,7 @@ AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::Te //Code mostly duplicated from CRenderer::Draw2dTextWithDepth float posX = params.m_position.GetX(); float posY = params.m_position.GetY(); - internalParams.m_viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + internalParams.m_viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId); const AZ::RHI::Viewport& viewport = internalParams.m_viewportContext->GetWindowContext()->GetViewport(); internalParams.m_viewport = &viewport; if (params.m_virtual800x600ScreenSize) From 6fcd5c7817a3a78172c8f98058056be710a52eb6 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Tue, 11 May 2021 18:27:47 -0700 Subject: [PATCH 09/17] Restore Viewport debug text Adds the AtomViewportDisplayInfo Gem which renders debug text to the default viewport context depending on the value of r_DisplayInfo. The gem is flagged as a dependency of AtomBridge, so all Atom projects will consume it by default. --- .../AtomBridge/Code/CMakeLists.txt | 4 + .../AtomViewportDisplayInfo/CMakeLists.txt | 12 + .../Code/CMakeLists.txt | 50 +++ ...AtomViewportDisplayInfoSystemComponent.cpp | 289 ++++++++++++++++++ .../AtomViewportDisplayInfoSystemComponent.h | 79 +++++ .../Code/Source/Module.cpp | 51 ++++ .../Code/Source/Tests/test_Main.cpp | 20 ++ .../Code/atomviewportdisplayinfo_files.cmake | 16 + .../atomviewportdisplayinfo_test_files.cmake | 14 + .../AtomViewportDisplayInfo/gem.json | 32 ++ Gems/AtomLyIntegration/CMakeLists.txt | 1 + 11 files changed, 568 insertions(+) create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/CMakeLists.txt create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Module.cpp create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Tests/test_Main.cpp create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_files.cmake create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_test_files.cmake create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt index b684e445b3..885f0d1a25 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt @@ -29,6 +29,8 @@ ly_add_target( Gem::Atom_RPI.Public Gem::Atom_Bootstrap.Headers Legacy::CryCommon + RUNTIME_DEPENDENCIES + Gem::AtomViewportDisplayInfo ) ly_add_target( @@ -68,5 +70,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AssetBuilderSDK Gem::Atom_Utils.Static Gem::Atom_AtomBridge.Static + RUNTIME_DEPENDENCIES + Gem::AtomViewportDisplayInfo ) endif() diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/CMakeLists.txt new file mode 100644 index 0000000000..20a680bce9 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +add_subdirectory(Code) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt new file mode 100644 index 0000000000..395cc22d47 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +ly_add_target( + NAME AtomViewportDisplayInfo GEM_MODULE + NAMESPACE Gem + FILES_CMAKE + atomviewportdisplayinfo_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AtomCore + Legacy::CryCommon + Gem::Atom_RHI.Reflect + Gem::Atom_RPI.Public +) + +################################################################################ +# Tests +################################################################################ +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME AtomViewportDisplayInfo.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + atomviewportdisplayinfo_test_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Include + Tests + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + ) + ly_add_googletest( + NAME Gem::AtomViewportDisplayInfo.Tests + ) +endif() + diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp new file mode 100644 index 0000000000..394923071e --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -0,0 +1,289 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include "AtomViewportDisplayInfoSystemComponent.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +AZ_CVAR(float, r_fpsInterval, 1.0f, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The time period over which to calculate the framerate for r_displayInfo"); + +namespace AZ::Render +{ + static constexpr int DisplayInfoLevelNone = 0; + static constexpr int DisplayInfoLevelNormal = 1; + static constexpr int DisplayInfoLevelFull = 2; + static constexpr int DisplayInfoLevelCompact = 3; + + void AtomViewportDisplayInfoSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0) + ; + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class("Viewport Display Info", "Manages debug viewport information through r_DisplayInfo") + ->ClassElement(Edit::ClassElements::EditorData, "") + ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(Edit::Attributes::AutoExpand, true) + ; + } + } + } + + void AtomViewportDisplayInfoSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("ViewportDisplayInfoService")); + } + + void AtomViewportDisplayInfoSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("ViewportDisplayInfoService")); + } + + void AtomViewportDisplayInfoSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + } + + void AtomViewportDisplayInfoSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + } + + void AtomViewportDisplayInfoSystemComponent::Activate() + { + AZ::Name apiName = AZ::RHI::Factory::Get().GetName(); + if (!apiName.IsEmpty()) + { + m_rendererDescription = AZStd::string::format("Atom using %s RHI", apiName.GetCStr()); + } + + CrySystemEventBus::Handler::BusConnect(); + AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect( + AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContextName()); + } + + void AtomViewportDisplayInfoSystemComponent::Deactivate() + { + AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect(); + CrySystemEventBus::Handler::BusDisconnect(); + } + + AZ::RPI::ViewportContextPtr AtomViewportDisplayInfoSystemComponent::GetViewportContext() const + { + return AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContext(); + } + + void AtomViewportDisplayInfoSystemComponent::DrawLine(AZStd::string_view line, AZ::Color color) + { + m_drawParams.m_color = color; + AzFramework::FontDrawInterface* fontDrawInterface = + AZ::Interface::Get()->GetDefaultFontDrawInterface(); + AZ::Vector2 textSize = fontDrawInterface->GetTextSize(m_drawParams, line); + fontDrawInterface->DrawScreenAlignedText2d(m_drawParams, line); + m_drawParams.m_position.SetY(m_drawParams.m_position.GetY() + textSize.GetY() + m_lineSpacing); + } + + void AtomViewportDisplayInfoSystemComponent::OnRenderTick() + { + AzFramework::FontDrawInterface* fontDrawInterface = + AZ::Interface::Get()->GetDefaultFontDrawInterface(); + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + + if (!fontDrawInterface || !viewportContext || !viewportContext->GetRenderScene()) + { + return; + } + + m_fpsInterval = AZStd::chrono::seconds(r_fpsInterval); + + UpdateFramerate(); + + if (!m_displayInfoCVar) + { + return; + } + int displayLevel = m_displayInfoCVar->GetIVal(); + if (displayLevel == DisplayInfoLevelNone) + { + return; + } + + m_drawParams.m_drawViewportId = viewportContext->GetId(); + auto viewportSize = viewportContext->GetViewportSize(); + m_drawParams.m_position = AZ::Vector3(viewportSize.m_width, 0.f, 1.f); + m_drawParams.m_color = AZ::Colors::White; + m_drawParams.m_scale = AZ::Vector2(0.7f); + m_drawParams.m_hAlign = AzFramework::TextHorizontalAlignment::Right; + m_drawParams.m_monospace = false; + m_drawParams.m_depthTest = false; + m_drawParams.m_virtual800x600ScreenSize = true; + m_drawParams.m_scaleWithWindow = false; + m_drawParams.m_multiline = true; + m_drawParams.m_lineSpacing = 0.5f; + + // Calculate line spacing based on the font's actual line height + const float lineHeight = fontDrawInterface->GetTextSize(m_drawParams, " ").GetY(); + m_lineSpacing = lineHeight * m_drawParams.m_lineSpacing; + + DrawRendererInfo(); + if (displayLevel != DisplayInfoLevelCompact) + { + DrawCameraInfo(); + DrawMemoryInfo(); + } + DrawFramerate(); + } + + void AtomViewportDisplayInfoSystemComponent::OnCrySystemInitialized(ISystem& system, [[maybe_unused]]const SSystemInitParams& initParams) + { + m_displayInfoCVar = system.GetGlobalEnvironment()->pConsole->GetCVar("r_DisplayInfo"); + } + + void AtomViewportDisplayInfoSystemComponent::OnCrySystemShutdown([[maybe_unused]]ISystem& system) + { + m_displayInfoCVar = nullptr; + } + + void AtomViewportDisplayInfoSystemComponent::DrawRendererInfo() + { + DrawLine(m_rendererDescription, AZ::Colors::Yellow); + } + + void AtomViewportDisplayInfoSystemComponent::DrawCameraInfo() + { + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView(); + if (currentView == nullptr) + { + return; + } + + auto viewportSize = viewportContext->GetViewportSize(); + AzFramework::CameraState cameraState; + AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, currentView->GetViewToClipMatrix()); + const AZ::Transform transform = currentView->GetCameraTransform(); + const AZ::Vector3 translation = transform.GetTranslation(); + const AZ::Vector3 rotation = transform.GetEulerDegrees(); + DrawLine(AZStd::string::format( + "CamPos=%.2f %.2f %.2f Angl=%3.0f %3.0f %4.0f ZN=%.2f ZF=%.0f", + translation.GetX(), translation.GetY(), translation.GetZ(), + rotation.GetX(), rotation.GetY(), rotation.GetZ(), + cameraState.m_nearClip, cameraState.m_farClip + )); + } + + void AtomViewportDisplayInfoSystemComponent::DrawMemoryInfo() + { + static IMemoryManager::SProcessMemInfo processMemInfo; + + // Throttle memory usage updates to avoid potentially expensive memory usage API calls every tick. + constexpr AZStd::chrono::duration memoryUpdateInterval = AZStd::chrono::seconds(0.5); + AZStd::chrono::time_point currentTime = m_fpsHistory.back().Get(); + if (m_lastMemoryUpdate.has_value()) + { + if (currentTime - m_lastMemoryUpdate.value() > memoryUpdateInterval) + { + if (auto memoryManager = GetISystem()->GetIMemoryManager()) + { + memoryManager->GetProcessMemInfo(processMemInfo); + } + } + } + m_lastMemoryUpdate = currentTime; + + + int peakUsageMB = aznumeric_cast(processMemInfo.PeakPagefileUsage >> 20); + int currentUsageMB = aznumeric_cast(processMemInfo.PagefileUsage >> 20); + DrawLine(AZStd::string::format("Mem=%d Peak=%d", currentUsageMB, peakUsageMB)); + } + + void AtomViewportDisplayInfoSystemComponent::UpdateFramerate() + { + if (!m_tickRequests) + { + m_tickRequests = AZ::TickRequestBus::FindFirstHandler(); + } + if (!m_tickRequests) + { + return; + } + + AZ::ScriptTimePoint currentTime = m_tickRequests->GetTimeAtCurrentTick(); + // Only keep as much sampling data is is required by our FPS history. + while (!m_fpsHistory.empty() && (currentTime.Get() - m_fpsHistory.front().Get() > m_fpsInterval)) + { + m_fpsHistory.pop_front(); + } + m_fpsHistory.push_back(currentTime); + } + + void AtomViewportDisplayInfoSystemComponent::DrawFramerate() + { + AZStd::chrono::duration actualInterval = AZStd::chrono::seconds(0); + AZStd::optional lastTime; + AZStd::optional minFPS; + AZStd::optional maxFPS; + for (const AZ::ScriptTimePoint& time : m_fpsHistory) + { + if (lastTime.has_value()) + { + AZStd::chrono::duration deltaTime = time.Get() - lastTime.value().Get(); + if (deltaTime.count() == 0.0) + { + continue; + } + double fps = AZStd::chrono::seconds(1) / deltaTime; + if (!minFPS.has_value()) + { + minFPS = fps; + maxFPS = fps; + } + else + { + minFPS = AZStd::min(minFPS.value(), fps); + maxFPS = AZStd::max(maxFPS.value(), fps); + } + actualInterval += deltaTime; + } + lastTime = time; + } + + const double averageFPS = aznumeric_cast(m_fpsHistory.size()) / actualInterval.count(); + const double frameIntervalSeconds = m_fpsInterval.count(); + + DrawLine( + AZStd::string::format( + "FPS %.1f [%.0f..%.0f], frame avg over %.1fs", + averageFPS, + minFPS.value_or(0.0), + maxFPS.value_or(0.0), + frameIntervalSeconds), + AZ::Colors::Yellow); + } +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h new file mode 100644 index 0000000000..5cb6ed3308 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -0,0 +1,79 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +struct ICVar; + +namespace AZ +{ + class TickRequests; + + namespace Render + { + class AtomViewportDisplayInfoSystemComponent + : public AZ::Component + , public AZ::RPI::ViewportContextNotificationBus::Handler + , public CrySystemEventBus::Handler + { + public: + AZ_COMPONENT(AtomViewportDisplayInfoSystemComponent, "{AC32F173-E7E2-4943-8E6C-7C3091978221}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + protected: + // AZ::Component overrides... + void Activate() override; + void Deactivate() override; + + // AZ::RPI::ViewportContextNotificationBus::Handler overrides... + void OnRenderTick() override; + + // CrySystemEventBus::Handler overrides... + void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams) override; + void OnCrySystemShutdown(ISystem& system) override; + + private: + AZ::RPI::ViewportContextPtr GetViewportContext() const; + void DrawLine(AZStd::string_view line, AZ::Color color = AZ::Colors::White); + + void UpdateFramerate(); + + void DrawRendererInfo(); + void DrawCameraInfo(); + void DrawMemoryInfo(); + void DrawFramerate(); + + AZStd::string m_rendererDescription; + AzFramework::TextDrawParameters m_drawParams; + float m_lineSpacing; + AZStd::chrono::duration m_fpsInterval = AZStd::chrono::seconds(1); + AZStd::deque m_fpsHistory; + AZStd::optional m_lastMemoryUpdate; + AZ::TickRequests* m_tickRequests = nullptr; + ICVar* m_displayInfoCVar = nullptr; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Module.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Module.cpp new file mode 100644 index 0000000000..f67e1bd1f5 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Module.cpp @@ -0,0 +1,51 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include + +#include "AtomViewportDisplayInfoSystemComponent.h" + +namespace AZ +{ + namespace Render + { + class AtomViewportDisplayInfoModule + : public AZ::Module + { + public: + AZ_RTTI(AtomViewportDisplayInfoModule, "{B10C0E55-03A1-4A46-AE3E-D3615AEAA659}", AZ::Module); + AZ_CLASS_ALLOCATOR(AtomViewportDisplayInfoModule, AZ::SystemAllocator, 0); + + AtomViewportDisplayInfoModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + AtomViewportDisplayInfoSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{ + azrtti_typeid(), + }; + } + }; + } // namespace Render +} // namespace AZ + +// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM +// The first parameter should be GemName_GemIdLower +// The second should be the fully qualified name of the class above +AZ_DECLARE_MODULE_CLASS(Gem_AtomViewportDisplayInfo, AZ::Render::AtomViewportDisplayInfoModule) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Tests/test_Main.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Tests/test_Main.cpp new file mode 100644 index 0000000000..b533221bbe --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/Tests/test_Main.cpp @@ -0,0 +1,20 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + +TEST(AtomViewportDisplayInfoSanityTest, Sanity) +{ + EXPECT_EQ(1, 1); +} diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_files.cmake b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_files.cmake new file mode 100644 index 0000000000..561971453b --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_files.cmake @@ -0,0 +1,16 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Source/AtomViewportDisplayInfoSystemComponent.cpp + Source/AtomViewportDisplayInfoSystemComponent.h + Source/Module.cpp +) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_test_files.cmake b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_test_files.cmake new file mode 100644 index 0000000000..0bc1ee3a50 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/atomviewportdisplayinfo_test_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Source/Tests/test_Main.cpp +) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json new file mode 100644 index 0000000000..a54dc188a7 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json @@ -0,0 +1,32 @@ +{ + "gem_name": "AtomLyIntegration_AtomViewportDisplayInfo", + "Dependencies": [ + { + "Uuid": "a218db9eb2114477b46600fea4441a6c", + "VersionConstraints": [ + "~>0.1.0" + ], + "_comment": "Atom RPI" + }, + { + "Uuid": "c7ff89ad6e8b4b45b2fadef2bcf12d6e", + "VersionConstraints": [ + "~>0.1.0" + ], + "_comment": "Atom_Bootstrap" + } + ], + "GemFormatVersion": 4, + "Uuid": "7c255c884bae4046b0640abe3c88cc4c", + "Name": "AtomLyIntegration_AtomViewportDisplayInfo", + "DisplayName": "Atom.AtomViewportDisplayInfo", + "Version": "0.1.0", + "Summary": "Provides a diagnostic viewport overlay for the default O3DE Atom viewport.", + "Tags": ["Atom"], + "IconPath": "preview.png", + "Modules": [ + { + "Type": "GameModule" + } + ] +} diff --git a/Gems/AtomLyIntegration/CMakeLists.txt b/Gems/AtomLyIntegration/CMakeLists.txt index 57bb860a9e..35022e643b 100644 --- a/Gems/AtomLyIntegration/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CMakeLists.txt @@ -16,3 +16,4 @@ add_subdirectory(EMotionFXAtom) add_subdirectory(AtomFont) add_subdirectory(TechnicalArt) add_subdirectory(AtomBridge) +add_subdirectory(AtomViewportDisplayInfo) From 84216f04793e17c923b744e2531c3e7d0feca27d Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 12 May 2021 15:58:28 -0700 Subject: [PATCH 10/17] Add API for ViewportInfoDisplayState, add some minor RHI integration --- .../Code/CMakeLists.txt | 2 + .../AtomViewportInfoDisplayBus.h | 61 ++++++++++ ...AtomViewportDisplayInfoSystemComponent.cpp | 107 +++++++++++++----- .../AtomViewportDisplayInfoSystemComponent.h | 14 +-- 4 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Include/AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt index 395cc22d47..de4ee9b4b5 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt @@ -17,6 +17,8 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE Source + PUBLIC + Include BUILD_DEPENDENCIES PRIVATE AZ::AzCore diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Include/AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Include/AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h new file mode 100644 index 0000000000..ae9359d9d3 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Include/AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h @@ -0,0 +1,61 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once +#include +#include + +namespace AZ +{ + namespace AtomBridge + { + //! The level of information to display in the viewport info display overlay. + enum class ViewportInfoDisplayState : int + { + NoInfo = 0, + NormalInfo = 1, + FullInfo = 2, + CompactInfo = 3, + Invalid + }; + + //! This bus is used to request changes to the viewport info display overlay. + class AtomViewportInfoDisplayRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single; + + //! Gets the current viewport info overlay state. + virtual ViewportInfoDisplayState GetDisplayState() const = 0; + //! Sets the current viewport info overlay state. + //! The overlay will be drawn to the default viewport context every frame, if enabled. + virtual void SetDisplayState(ViewportInfoDisplayState state) = 0; + }; + + using AtomViewportInfoDisplayRequestBus = AZ::EBus; + + //! This bus is used to listen for state changes in the viewport info display overlay. + class AtomViewportInfoDisplayNotifications + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple; + static const AZ::EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single; + + //! Called when the ViewportInfoDisplayState (via the r_displayInfo CVar) has changed. + virtual void OnViewportInfoDisplayStateChanged([[maybe_unused]]ViewportInfoDisplayState state){} + }; + + using AtomViewportInfoDisplayNotificationBus = AZ::EBus; + } +} diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 394923071e..c9128c001f 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -21,21 +21,30 @@ #include #include #include +#include #include #include #include #include -AZ_CVAR(float, r_fpsInterval, 1.0f, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, - "The time period over which to calculate the framerate for r_displayInfo"); - namespace AZ::Render { - static constexpr int DisplayInfoLevelNone = 0; - static constexpr int DisplayInfoLevelNormal = 1; - static constexpr int DisplayInfoLevelFull = 2; - static constexpr int DisplayInfoLevelCompact = 3; + AZ_CVAR(int, r_displayInfo, 1, [](const int& newDisplayInfoVal)->void + { + // Forward this event to the system component so it can update accordingly. + // This callback only gets triggered by console commands, so this will not recurse. + AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( + &AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, + static_cast(newDisplayInfoVal) + ); + }, AZ::ConsoleFunctorFlags::DontReplicate, + "Toggles debugging information display.\n" + "Usage: r_displayInfo [0=off/1=show/2=enhanced/3=compact]" + ); + AZ_CVAR(float, r_fpsCalcInterval, 1.0f, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The time period over which to calculate the framerate for r_displayInfo." + ); void AtomViewportDisplayInfoSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -47,7 +56,7 @@ namespace AZ::Render if (AZ::EditContext* ec = serialize->GetEditContext()) { - ec->Class("Viewport Display Info", "Manages debug viewport information through r_DisplayInfo") + ec->Class("Viewport Display Info", "Manages debug viewport information through r_displayInfo") ->ClassElement(Edit::ClassElements::EditorData, "") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) ->Attribute(Edit::Attributes::AutoExpand, true) @@ -83,15 +92,15 @@ namespace AZ::Render m_rendererDescription = AZStd::string::format("Atom using %s RHI", apiName.GetCStr()); } - CrySystemEventBus::Handler::BusConnect(); AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect( AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContextName()); + AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler::BusConnect(); } void AtomViewportDisplayInfoSystemComponent::Deactivate() { + AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler::BusDisconnect(); AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect(); - CrySystemEventBus::Handler::BusDisconnect(); } AZ::RPI::ViewportContextPtr AtomViewportDisplayInfoSystemComponent::GetViewportContext() const @@ -111,8 +120,13 @@ namespace AZ::Render void AtomViewportDisplayInfoSystemComponent::OnRenderTick() { + auto fontQueryInterface = AZ::Interface::Get(); + if (!fontQueryInterface) + { + return; + } AzFramework::FontDrawInterface* fontDrawInterface = - AZ::Interface::Get()->GetDefaultFontDrawInterface(); + fontQueryInterface->GetDefaultFontDrawInterface(); AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); if (!fontDrawInterface || !viewportContext || !viewportContext->GetRenderScene()) @@ -120,18 +134,23 @@ namespace AZ::Render return; } - m_fpsInterval = AZStd::chrono::seconds(r_fpsInterval); + m_fpsInterval = AZStd::chrono::seconds(r_fpsCalcInterval); UpdateFramerate(); - if (!m_displayInfoCVar) + const AtomBridge::ViewportInfoDisplayState displayLevel = GetDisplayState(); + if (displayLevel == AtomBridge::ViewportInfoDisplayState::NoInfo) { return; } - int displayLevel = m_displayInfoCVar->GetIVal(); - if (displayLevel == DisplayInfoLevelNone) + + if (m_updateRootPassQuery) { - return; + if (auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass()) + { + rootPass->SetPipelineStatisticsQueryEnabled(displayLevel == AtomBridge::ViewportInfoDisplayState::FullInfo); + m_updateRootPassQuery = false; + } } m_drawParams.m_drawViewportId = viewportContext->GetId(); @@ -152,22 +171,30 @@ namespace AZ::Render m_lineSpacing = lineHeight * m_drawParams.m_lineSpacing; DrawRendererInfo(); - if (displayLevel != DisplayInfoLevelCompact) + if (displayLevel == AtomBridge::ViewportInfoDisplayState::FullInfo) { DrawCameraInfo(); + DrawPassInfo(); + } + if (displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo) + { DrawMemoryInfo(); } DrawFramerate(); } - void AtomViewportDisplayInfoSystemComponent::OnCrySystemInitialized(ISystem& system, [[maybe_unused]]const SSystemInitParams& initParams) + AtomBridge::ViewportInfoDisplayState AtomViewportDisplayInfoSystemComponent::GetDisplayState() const { - m_displayInfoCVar = system.GetGlobalEnvironment()->pConsole->GetCVar("r_DisplayInfo"); + return static_cast(r_displayInfo.operator int()); } - void AtomViewportDisplayInfoSystemComponent::OnCrySystemShutdown([[maybe_unused]]ISystem& system) + void AtomViewportDisplayInfoSystemComponent::SetDisplayState(AtomBridge::ViewportInfoDisplayState state) { - m_displayInfoCVar = nullptr; + r_displayInfo = static_cast(state); + AtomBridge::AtomViewportInfoDisplayNotificationBus::Broadcast( + &AtomBridge::AtomViewportInfoDisplayNotificationBus::Events::OnViewportInfoDisplayStateChanged, + state); + m_updateRootPassQuery = true; } void AtomViewportDisplayInfoSystemComponent::DrawRendererInfo() @@ -198,6 +225,31 @@ namespace AZ::Render )); } + void AtomViewportDisplayInfoSystemComponent::DrawPassInfo() + { + auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass(); + const RPI::PipelineStatisticsResult stats = rootPass->GetLatestPipelineStatisticsResult(); + AZStd::function)> containingPassCount = [&containingPassCount](const AZ::RPI::Ptr pass) + { + int count = 1; + if (auto passAsParent = pass->AsParent()) + { + for (const auto child : passAsParent->GetChildren()) + { + count += containingPassCount(child); + } + } + return count; + }; + const int numPasses = containingPassCount(rootPass); + DrawLine(AZStd::string::format( + "Total Passes: %d Vertex Count: %d Primitive Count: %d", + numPasses, + stats.m_vertexCount, + stats.m_primitiveCount + )); + } + void AtomViewportDisplayInfoSystemComponent::DrawMemoryInfo() { static IMemoryManager::SProcessMemInfo processMemInfo; @@ -236,11 +288,16 @@ namespace AZ::Render AZ::ScriptTimePoint currentTime = m_tickRequests->GetTimeAtCurrentTick(); // Only keep as much sampling data is is required by our FPS history. - while (!m_fpsHistory.empty() && (currentTime.Get() - m_fpsHistory.front().Get() > m_fpsInterval)) + while (!m_fpsHistory.empty() && (currentTime.Get() - m_fpsHistory.front().Get()) > m_fpsInterval) { m_fpsHistory.pop_front(); } - m_fpsHistory.push_back(currentTime); + + // Discard entries with a zero time-delta (can happen when we don't have window focus). + if (m_fpsHistory.empty() || (currentTime.Get() - m_fpsHistory.back().Get()) != AZStd::chrono::seconds(0)) + { + m_fpsHistory.push_back(currentTime); + } } void AtomViewportDisplayInfoSystemComponent::DrawFramerate() @@ -254,10 +311,6 @@ namespace AZ::Render if (lastTime.has_value()) { AZStd::chrono::duration deltaTime = time.Get() - lastTime.value().Get(); - if (deltaTime.count() == 0.0) - { - continue; - } double fps = AZStd::chrono::seconds(1) / deltaTime; if (!minFPS.has_value()) { diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h index 5cb6ed3308..ac6c2bab65 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -19,8 +19,7 @@ #include #include #include - -struct ICVar; +#include namespace AZ { @@ -31,7 +30,7 @@ namespace AZ class AtomViewportDisplayInfoSystemComponent : public AZ::Component , public AZ::RPI::ViewportContextNotificationBus::Handler - , public CrySystemEventBus::Handler + , public AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler { public: AZ_COMPONENT(AtomViewportDisplayInfoSystemComponent, "{AC32F173-E7E2-4943-8E6C-7C3091978221}"); @@ -51,9 +50,9 @@ namespace AZ // AZ::RPI::ViewportContextNotificationBus::Handler overrides... void OnRenderTick() override; - // CrySystemEventBus::Handler overrides... - void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams) override; - void OnCrySystemShutdown(ISystem& system) override; + // AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler overrides... + AtomBridge::ViewportInfoDisplayState GetDisplayState() const override; + void SetDisplayState(AtomBridge::ViewportInfoDisplayState state) override; private: AZ::RPI::ViewportContextPtr GetViewportContext() const; @@ -63,6 +62,7 @@ namespace AZ void DrawRendererInfo(); void DrawCameraInfo(); + void DrawPassInfo(); void DrawMemoryInfo(); void DrawFramerate(); @@ -73,7 +73,7 @@ namespace AZ AZStd::deque m_fpsHistory; AZStd::optional m_lastMemoryUpdate; AZ::TickRequests* m_tickRequests = nullptr; - ICVar* m_displayInfoCVar = nullptr; + bool m_updateRootPassQuery = true; }; } // namespace Render } // namespace AZ From cb09d542d1207e437dfca27b68cd2133776c78f9 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 12 May 2021 15:59:21 -0700 Subject: [PATCH 11/17] Use the new Atom API instead of the removed r_displayInfo for ViewportTitleDlg --- Code/Sandbox/Editor/CMakeLists.txt | 1 + Code/Sandbox/Editor/ViewportTitleDlg.cpp | 75 ++++++++++++++++++++---- Code/Sandbox/Editor/ViewportTitleDlg.h | 4 +- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/Code/Sandbox/Editor/CMakeLists.txt b/Code/Sandbox/Editor/CMakeLists.txt index 7d89717391..2be48777d3 100644 --- a/Code/Sandbox/Editor/CMakeLists.txt +++ b/Code/Sandbox/Editor/CMakeLists.txt @@ -124,6 +124,7 @@ ly_add_target( Gem::Atom_RPI.Public Gem::Atom_Feature_Common.Static Gem::AtomToolsFramework.Static + Gem::AtomViewportDisplayInfo ${additional_dependencies} PUBLIC 3rdParty::AWSNativeSDK::Core diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.cpp b/Code/Sandbox/Editor/ViewportTitleDlg.cpp index 95531e117c..159fccfd64 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.cpp +++ b/Code/Sandbox/Editor/ViewportTitleDlg.cpp @@ -13,7 +13,7 @@ // Description : CViewportTitleDlg implementation file - +#if !defined(Q_MOC_RUN) #include "EditorDefs.h" #include "ViewportTitleDlg.h" @@ -36,10 +36,13 @@ #include "UsedResources.h" #include "Include/IObjectManager.h" +#include + AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include "ui_ViewportTitleDlg.h" AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING +#endif //!defined(Q_MOC_RUN) // CViewportTitleDlg dialog @@ -63,6 +66,32 @@ inline namespace Helpers } } +namespace +{ + class CViewportTitleDlgDisplayInfoHelper + : public QObject + , public AZ::AtomBridge::AtomViewportInfoDisplayNotificationBus::Handler + { + Q_OBJECT + + public: + CViewportTitleDlgDisplayInfoHelper(CViewportTitleDlg* parent) + : QObject(parent) + { + AZ::AtomBridge::AtomViewportInfoDisplayNotificationBus::Handler::BusConnect(); + } + + signals: + void ViewportInfoStatusUpdated(int newIndex); + + private: + void OnViewportInfoDisplayStateChanged(AZ::AtomBridge::ViewportInfoDisplayState state) + { + emit ViewportInfoStatusUpdated(static_cast(state)); + } + }; +} //end anonymous namespace + CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent) : QWidget(pParent) , m_ui(new Ui::ViewportTitleDlg) @@ -115,14 +144,11 @@ void CViewportTitleDlg::OnInitDialog() m_ui->m_toggleHelpersBtn->setChecked(GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()); - ICVar* pDisplayInfo(gEnv->pConsole->GetCVar("r_displayInfo")); - if (pDisplayInfo) - { - SFunctor oFunctor; - oFunctor.Set(OnChangedDisplayInfo, pDisplayInfo, m_ui->m_toggleDisplayInfoBtn); - m_displayInfoCallbackIndex = pDisplayInfo->AddOnChangeFunctor(oFunctor); - OnChangedDisplayInfo(pDisplayInfo, m_ui->m_toggleDisplayInfoBtn); - } + + // Add a child parented to us that listens for r_displayInfo changes. + auto displayInfoHelper = new CViewportTitleDlgDisplayInfoHelper(this); + connect(displayInfoHelper, &CViewportTitleDlgDisplayInfoHelper::ViewportInfoStatusUpdated, this, &CViewportTitleDlg::UpdateDisplayInfo); + UpdateDisplayInfo(); connect(m_ui->m_toggleHelpersBtn, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleHelpers); connect(m_ui->m_toggleDisplayInfoBtn, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleDisplayInfo); @@ -156,6 +182,32 @@ void CViewportTitleDlg::OnToggleHelpers() ////////////////////////////////////////////////////////////////////////// void CViewportTitleDlg::OnToggleDisplayInfo() { + AZ::AtomBridge::ViewportInfoDisplayState state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo; + AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult( + state, + &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState + ); + state = static_cast(static_cast(state)+1); + if (state == AZ::AtomBridge::ViewportInfoDisplayState::Invalid) + { + state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo; + } + // SetDisplayState will fire OnViewportInfoDisplayStateChanged and notify us, no need to call UpdateDisplayInfo. + AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( + &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, + state + ); +} + +////////////////////////////////////////////////////////////////////////// +void CViewportTitleDlg::UpdateDisplayInfo() +{ + AZ::AtomBridge::ViewportInfoDisplayState state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo; + AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult( + state, + &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState + ); + m_ui->m_toggleDisplayInfoBtn->setChecked(state != AZ::AtomBridge::ViewportInfoDisplayState::NoInfo); } ////////////////////////////////////////////////////////////////////////// @@ -544,10 +596,6 @@ void CViewportTitleDlg::UpdateCustomPresets(const QString& text, QStringList& cu } } -void CViewportTitleDlg::OnChangedDisplayInfo([[maybe_unused]] ICVar* pDisplayInfo, [[maybe_unused]] QAbstractButton* pDisplayInfoButton) -{ -} - bool CViewportTitleDlg::eventFilter(QObject* object, QEvent* event) { bool consumeEvent = false; @@ -609,4 +657,5 @@ namespace AzToolsFramework } } +#include "ViewportTitleDlg.moc" #include diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.h b/Code/Sandbox/Editor/ViewportTitleDlg.h index 55741636b3..ce2f116d97 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.h +++ b/Code/Sandbox/Editor/ViewportTitleDlg.h @@ -60,7 +60,6 @@ public: static void LoadCustomPresets(const QString& section, const QString& keyName, QStringList& outCustompresets); static void SaveCustomPresets(const QString& section, const QString& keyName, const QStringList& custompresets); static void UpdateCustomPresets(const QString& text, QStringList& custompresets); - static void OnChangedDisplayInfo(ICVar* pDisplayInfo, QAbstractButton* pDisplayInfoButton); bool eventFilter(QObject* object, QEvent* event) override; @@ -77,6 +76,7 @@ protected: void OnMaximize(); void OnToggleHelpers(); void OnToggleDisplayInfo(); + void UpdateDisplayInfo(); QString m_title; @@ -87,8 +87,6 @@ protected: QStringList m_customFOVPresets; QStringList m_customAspectRatioPresets; - uint64 m_displayInfoCallbackIndex; - void OnMenuFOVCustom(); void CreateFOVMenu(); From 8fd5c30e136e62887842916b26491c691a625e26 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 12 May 2021 17:47:10 -0700 Subject: [PATCH 12/17] Address some build/review feedback --- Code/Sandbox/Editor/ViewportTitleDlg.cpp | 7 ++-- .../AtomFont/Code/Source/FFont.cpp | 1 - ...AtomViewportDisplayInfoSystemComponent.cpp | 32 +++++++++---------- .../AtomViewportDisplayInfoSystemComponent.h | 1 + 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.cpp b/Code/Sandbox/Editor/ViewportTitleDlg.cpp index 159fccfd64..d7c8929540 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.cpp +++ b/Code/Sandbox/Editor/ViewportTitleDlg.cpp @@ -187,11 +187,8 @@ void CViewportTitleDlg::OnToggleDisplayInfo() state, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState ); - state = static_cast(static_cast(state)+1); - if (state == AZ::AtomBridge::ViewportInfoDisplayState::Invalid) - { - state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo; - } + state = static_cast( + (static_cast(state)+1) % static_cast(AZ::AtomBridge::ViewportInfoDisplayState::Invalid)); // SetDisplayState will fire OnViewportInfoDisplayStateChanged and notify us, no need to call UpdateDisplayInfo. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index be0f87100a..cc14014e48 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1684,7 +1684,6 @@ AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::Te return internalParams; } - //Code mostly duplicated from CRenderer::Draw2dTextWithDepth float posX = params.m_position.GetX(); float posY = params.m_position.GetY(); internalParams.m_viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId); diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index c9128c001f..ed6b910b76 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -111,25 +111,26 @@ namespace AZ::Render void AtomViewportDisplayInfoSystemComponent::DrawLine(AZStd::string_view line, AZ::Color color) { m_drawParams.m_color = color; - AzFramework::FontDrawInterface* fontDrawInterface = - AZ::Interface::Get()->GetDefaultFontDrawInterface(); - AZ::Vector2 textSize = fontDrawInterface->GetTextSize(m_drawParams, line); - fontDrawInterface->DrawScreenAlignedText2d(m_drawParams, line); + AZ::Vector2 textSize = m_fontDrawInterface->GetTextSize(m_drawParams, line); + m_fontDrawInterface->DrawScreenAlignedText2d(m_drawParams, line); m_drawParams.m_position.SetY(m_drawParams.m_position.GetY() + textSize.GetY() + m_lineSpacing); } void AtomViewportDisplayInfoSystemComponent::OnRenderTick() { - auto fontQueryInterface = AZ::Interface::Get(); - if (!fontQueryInterface) + if (!m_fontDrawInterface) { - return; + auto fontQueryInterface = AZ::Interface::Get(); + if (!fontQueryInterface) + { + return; + } + m_fontDrawInterface = + fontQueryInterface->GetDefaultFontDrawInterface(); } - AzFramework::FontDrawInterface* fontDrawInterface = - fontQueryInterface->GetDefaultFontDrawInterface(); AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); - if (!fontDrawInterface || !viewportContext || !viewportContext->GetRenderScene()) + if (!m_fontDrawInterface || !viewportContext || !viewportContext->GetRenderScene()) { return; } @@ -167,7 +168,7 @@ namespace AZ::Render m_drawParams.m_lineSpacing = 0.5f; // Calculate line spacing based on the font's actual line height - const float lineHeight = fontDrawInterface->GetTextSize(m_drawParams, " ").GetY(); + const float lineHeight = m_fontDrawInterface->GetTextSize(m_drawParams, " ").GetY(); m_lineSpacing = lineHeight * m_drawParams.m_lineSpacing; DrawRendererInfo(); @@ -234,7 +235,7 @@ namespace AZ::Render int count = 1; if (auto passAsParent = pass->AsParent()) { - for (const auto child : passAsParent->GetChildren()) + for (const auto& child : passAsParent->GetChildren()) { count += containingPassCount(child); } @@ -243,10 +244,10 @@ namespace AZ::Render }; const int numPasses = containingPassCount(rootPass); DrawLine(AZStd::string::format( - "Total Passes: %d Vertex Count: %d Primitive Count: %d", + "Total Passes: %d Vertex Count: %lld Primitive Count: %lld", numPasses, - stats.m_vertexCount, - stats.m_primitiveCount + aznumeric_cast(stats.m_vertexCount), + aznumeric_cast(stats.m_primitiveCount) )); } @@ -269,7 +270,6 @@ namespace AZ::Render } m_lastMemoryUpdate = currentTime; - int peakUsageMB = aznumeric_cast(processMemInfo.PeakPagefileUsage >> 20); int currentUsageMB = aznumeric_cast(processMemInfo.PagefileUsage >> 20); DrawLine(AZStd::string::format("Mem=%d Peak=%d", currentUsageMB, peakUsageMB)); diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h index ac6c2bab65..08bec4a1d2 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -68,6 +68,7 @@ namespace AZ AZStd::string m_rendererDescription; AzFramework::TextDrawParameters m_drawParams; + AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr; float m_lineSpacing; AZStd::chrono::duration m_fpsInterval = AZStd::chrono::seconds(1); AZStd::deque m_fpsHistory; From 58759bddf7f8e009900c17498be12cb7e4250aa3 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Fri, 14 May 2021 12:36:40 -0700 Subject: [PATCH 13/17] Tidy up Script/ScriptTimePoint --- .../AzCore/AzCore/Script/ScriptTimePoint.h | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h b/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h index 08c997de2d..41d80f42a3 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h +++ b/Code/Framework/AzCore/AzCore/Script/ScriptTimePoint.h @@ -24,9 +24,7 @@ namespace AZ AZ_TYPE_INFO_SPECIALIZE(AZStd::chrono::system_clock::time_point, "{5C48FD59-7267-405D-9C06-1EA31379FE82}"); - /** - * Wrapper that reflects a AZStd::chrono::system_clock::time_point to script. - */ + //! Wrapper that reflects a AZStd::chrono::system_clock::time_point to script. class ScriptTimePoint { public: @@ -38,33 +36,45 @@ namespace AZ explicit ScriptTimePoint(AZStd::chrono::system_clock::time_point timePoint) : m_timePoint(timePoint) {} - AZStd::string ToString() const - { - return AZStd::string::format("Time %llu", m_timePoint.time_since_epoch().count()); - } + //! Formats the time point in a string formatted as: "Time ". + AZStd::string ToString() const; - const AZStd::chrono::system_clock::time_point& Get() const { return m_timePoint; } + //! Returns the time point. + const AZStd::chrono::system_clock::time_point& Get() const; - // Returns the time point in seconds - double GetSeconds() const - { - typedef AZStd::chrono::duration double_seconds; - return AZStd::chrono::duration_cast(m_timePoint.time_since_epoch()).count(); - } + //! Returns the time point in seconds + double GetSeconds() const; - // Returns the time point in milliseconds - double GetMilliseconds() const - { - typedef AZStd::chrono::duration double_ms; - return AZStd::chrono::duration_cast(m_timePoint.time_since_epoch()).count(); - } + //! Returns the time point in milliseconds + double GetMilliseconds() const; static void Reflect(ReflectContext* reflection); protected: - AZStd::chrono::system_clock::time_point m_timePoint; }; + + inline AZStd::string ScriptTimePoint::ToString() const + { + return AZStd::string::format("Time %llu", m_timePoint.time_since_epoch().count()); + } + + inline const AZStd::chrono::system_clock::time_point& ScriptTimePoint::Get() const + { + return m_timePoint; + } + + inline double ScriptTimePoint::GetSeconds() const + { + typedef AZStd::chrono::duration double_seconds; + return AZStd::chrono::duration_cast(m_timePoint.time_since_epoch()).count(); + } + + inline double ScriptTimePoint::GetMilliseconds() const + { + typedef AZStd::chrono::duration double_ms; + return AZStd::chrono::duration_cast(m_timePoint.time_since_epoch()).count(); + } } From f7a9b28000d78c509cabc38b103d2f1de1845229 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Fri, 14 May 2021 12:37:35 -0700 Subject: [PATCH 14/17] Make AtomFont's API use copy semantics for string_view --- .../AzFramework/Font/FontInterface.h | 30 +++++++++---------- .../AtomLyIntegration/AtomFont/FFont.h | 8 ++--- .../AtomFont/Code/Source/FFont.cpp | 22 +++++++------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h index 48fa5bc2d2..b64b61e22c 100644 --- a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h @@ -40,18 +40,18 @@ namespace AzFramework //! Standard parameters for drawing text on screen struct TextDrawParameters { - ViewportId m_drawViewportId = InvalidViewportId; //! Viewport to draw into - AZ::Vector3 m_position; //! world space position for 3d draws, screen space x,y,depth for 2d. - AZ::Color m_color = AZ::Colors::White; //! Color to draw the text - AZ::Vector2 m_scale = AZ::Vector2(1.0f); //! font scale - float m_lineSpacing; //! Spacing between new lines, as a percentage of m_scale. - TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //! Horizontal text alignment - TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //! Vertical text alignment - bool m_monospace = false; //! disable character proportional spacing - bool m_depthTest = false; //! Test character against the depth buffer - bool m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution - bool m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger - bool m_multiline = true; //! text respects ascii newline characters + ViewportId m_drawViewportId = InvalidViewportId; //!< Viewport to draw into + AZ::Vector3 m_position; //!< world space position for 3d draws, screen space x,y,depth for 2d. + AZ::Color m_color = AZ::Colors::White; //!< Color to draw the text + AZ::Vector2 m_scale = AZ::Vector2(1.0f); //!< font scale + float m_lineSpacing; //!< Spacing between new lines, as a percentage of m_scale. + TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //!< Horizontal text alignment + TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //!< Vertical text alignment + bool m_monospace = false; //!< disable character proportional spacing + bool m_depthTest = false; //!< Test character against the depth buffer + bool m_virtual800x600ScreenSize = true; //!< Text placement and size are scaled relative to a virtual 800x600 resolution + bool m_scaleWithWindow = false; //!< Font gets bigger as the window gets bigger + bool m_multiline = true; //!< text respects ascii newline characters }; class FontDrawInterface @@ -64,13 +64,13 @@ namespace AzFramework virtual void DrawScreenAlignedText2d( const TextDrawParameters& params, - const AZStd::string_view& string) = 0; + AZStd::string_view text) = 0; virtual void DrawScreenAlignedText3d( const TextDrawParameters& params, - const AZStd::string_view& string) = 0; + AZStd::string_view text) = 0; virtual AZ::Vector2 GetTextSize( const TextDrawParameters& params, - const AZStd::string_view& string) = 0; + AZStd::string_view text) = 0; }; class FontQueryInterface diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 84d53a5446..1e224d6090 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -207,15 +207,15 @@ namespace AZ // AzFramework::FontDrawInterface implementation void DrawScreenAlignedText2d( const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) override; + AZStd::string_view text) override; void DrawScreenAlignedText3d( const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) override; + AZStd::string_view text) override; AZ::Vector2 GetTextSize( const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) override; + AZStd::string_view text) override; public: FFont(AtomFont* atomFont, const char* fontName); @@ -294,7 +294,7 @@ namespace AZ AZ::RPI::ViewportContextPtr m_viewportContext; const AZ::RHI::Viewport* m_viewport; }; - DrawParameters ExtractDrawParameters(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string, bool forceCalculateSize); + DrawParameters ExtractDrawParameters(const AzFramework::TextDrawParameters& params, AZStd::string_view text, bool forceCalculateSize); private: static constexpr uint32_t NumBuffers = 2; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index cc14014e48..21b57e0908 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1675,11 +1675,11 @@ static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::T } } -AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string, bool forceCalculateSize) +AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::TextDrawParameters& params, AZStd::string_view text, bool forceCalculateSize) { DrawParameters internalParams; if (params.m_drawViewportId == AzFramework::InvalidViewportId || - string.empty()) + text.empty()) { return internalParams; } @@ -1711,7 +1711,7 @@ AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::Te params.m_vAlign != AzFramework::TextVerticalAlignment::Top || forceCalculateSize) { - Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, internalParams.m_ctx); + Vec2 textSize = GetTextSizeUInternal(viewport, text.data(), params.m_multiline, internalParams.m_ctx); // If we're using virtual 800x600 coordinates, convert the text size from // pixels to that before using it as an offset. if (internalParams.m_ctx.m_sizeIn800x600) @@ -1750,9 +1750,9 @@ AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::Te void AZ::FFont::DrawScreenAlignedText2d( const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) + AZStd::string_view text) { - DrawParameters internalParams = ExtractDrawParameters(params, string, false); + DrawParameters internalParams = ExtractDrawParameters(params, text, false); if (!internalParams.m_viewportContext) { return; @@ -1764,7 +1764,7 @@ void AZ::FFont::DrawScreenAlignedText2d( internalParams.m_position.GetX(), internalParams.m_position.GetY(), params.m_position.GetZ(), // Z - string.data(), + text.data(), params.m_multiline, internalParams.m_ctx ); @@ -1772,9 +1772,9 @@ void AZ::FFont::DrawScreenAlignedText2d( void AZ::FFont::DrawScreenAlignedText3d( const AzFramework::TextDrawParameters& params, - const AZStd::string_view& string) + AZStd::string_view text) { - DrawParameters internalParams = ExtractDrawParameters(params, string, false); + DrawParameters internalParams = ExtractDrawParameters(params, text, false); if (!internalParams.m_viewportContext) { return; @@ -1798,15 +1798,15 @@ void AZ::FFont::DrawScreenAlignedText3d( internalParams.m_position.GetX(), internalParams.m_position.GetY(), params.m_position.GetZ(), // Z - string.data(), + text.data(), params.m_multiline, internalParams.m_ctx ); } -AZ::Vector2 AZ::FFont::GetTextSize(const AzFramework::TextDrawParameters& params, const AZStd::string_view& string) +AZ::Vector2 AZ::FFont::GetTextSize(const AzFramework::TextDrawParameters& params, AZStd::string_view text) { - DrawParameters sizeParams = ExtractDrawParameters(params, string, true); + DrawParameters sizeParams = ExtractDrawParameters(params, text, true); return sizeParams.m_size; } From 810c63b80e687f9fcfe20c47ee00687db8f973e1 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Fri, 14 May 2021 12:38:01 -0700 Subject: [PATCH 15/17] Streamline AtomLyIntegration/AtomViewportDisplayInfo/gem.json --- .../AtomViewportDisplayInfo/gem.json | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json index a54dc188a7..dd92a99ea9 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json @@ -1,32 +1,12 @@ { "gem_name": "AtomLyIntegration_AtomViewportDisplayInfo", - "Dependencies": [ - { - "Uuid": "a218db9eb2114477b46600fea4441a6c", - "VersionConstraints": [ - "~>0.1.0" - ], - "_comment": "Atom RPI" - }, - { - "Uuid": "c7ff89ad6e8b4b45b2fadef2bcf12d6e", - "VersionConstraints": [ - "~>0.1.0" - ], - "_comment": "Atom_Bootstrap" - } - ], - "GemFormatVersion": 4, - "Uuid": "7c255c884bae4046b0640abe3c88cc4c", - "Name": "AtomLyIntegration_AtomViewportDisplayInfo", - "DisplayName": "Atom.AtomViewportDisplayInfo", - "Version": "0.1.0", - "Summary": "Provides a diagnostic viewport overlay for the default O3DE Atom viewport.", - "Tags": ["Atom"], - "IconPath": "preview.png", - "Modules": [ - { - "Type": "GameModule" - } + "display_name": "Atom Viewport Display Info Overlay", + "summary": "Provides a diagnostic viewport overlay for the default O3DE Atom viewport.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "AtomLyIntegration", + "AtomViewportDisplayInfo" ] -} +} \ No newline at end of file From a8b29bf603922674a9bdc53bb68b438987d2ad32 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Fri, 14 May 2021 12:38:46 -0700 Subject: [PATCH 16/17] Remove memory info from the overlay for now (depended on the now-dead CryMemoryManager) --- ...AtomViewportDisplayInfoSystemComponent.cpp | 32 ++----------------- .../AtomViewportDisplayInfoSystemComponent.h | 1 - 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index ed6b910b76..11c727eeca 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -149,7 +148,7 @@ namespace AZ::Render { if (auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass()) { - rootPass->SetPipelineStatisticsQueryEnabled(displayLevel == AtomBridge::ViewportInfoDisplayState::FullInfo); + rootPass->SetPipelineStatisticsQueryEnabled(displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo); m_updateRootPassQuery = false; } } @@ -175,11 +174,10 @@ namespace AZ::Render if (displayLevel == AtomBridge::ViewportInfoDisplayState::FullInfo) { DrawCameraInfo(); - DrawPassInfo(); } if (displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo) { - DrawMemoryInfo(); + DrawPassInfo(); } DrawFramerate(); } @@ -251,30 +249,6 @@ namespace AZ::Render )); } - void AtomViewportDisplayInfoSystemComponent::DrawMemoryInfo() - { - static IMemoryManager::SProcessMemInfo processMemInfo; - - // Throttle memory usage updates to avoid potentially expensive memory usage API calls every tick. - constexpr AZStd::chrono::duration memoryUpdateInterval = AZStd::chrono::seconds(0.5); - AZStd::chrono::time_point currentTime = m_fpsHistory.back().Get(); - if (m_lastMemoryUpdate.has_value()) - { - if (currentTime - m_lastMemoryUpdate.value() > memoryUpdateInterval) - { - if (auto memoryManager = GetISystem()->GetIMemoryManager()) - { - memoryManager->GetProcessMemInfo(processMemInfo); - } - } - } - m_lastMemoryUpdate = currentTime; - - int peakUsageMB = aznumeric_cast(processMemInfo.PeakPagefileUsage >> 20); - int currentUsageMB = aznumeric_cast(processMemInfo.PagefileUsage >> 20); - DrawLine(AZStd::string::format("Mem=%d Peak=%d", currentUsageMB, peakUsageMB)); - } - void AtomViewportDisplayInfoSystemComponent::UpdateFramerate() { if (!m_tickRequests) @@ -287,7 +261,7 @@ namespace AZ::Render } AZ::ScriptTimePoint currentTime = m_tickRequests->GetTimeAtCurrentTick(); - // Only keep as much sampling data is is required by our FPS history. + // Only keep as much sampling data as is required by our FPS history. while (!m_fpsHistory.empty() && (currentTime.Get() - m_fpsHistory.front().Get()) > m_fpsInterval) { m_fpsHistory.pop_front(); diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h index 08bec4a1d2..135082fd8c 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -63,7 +63,6 @@ namespace AZ void DrawRendererInfo(); void DrawCameraInfo(); void DrawPassInfo(); - void DrawMemoryInfo(); void DrawFramerate(); AZStd::string m_rendererDescription; From 1426052a5f69ff6ba30dba126216d99bb330b159 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Fri, 14 May 2021 13:01:46 -0700 Subject: [PATCH 17/17] Address a bit more review feedback -Use aznumeric_cast for enum <-> int casts -Short circuit logic a bit more nicely --- Code/Sandbox/Editor/ViewportTitleDlg.cpp | 4 ++-- .../AtomViewportDisplayInfoSystemComponent.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.cpp b/Code/Sandbox/Editor/ViewportTitleDlg.cpp index d7c8929540..5ccb83cd5b 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.cpp +++ b/Code/Sandbox/Editor/ViewportTitleDlg.cpp @@ -187,8 +187,8 @@ void CViewportTitleDlg::OnToggleDisplayInfo() state, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState ); - state = static_cast( - (static_cast(state)+1) % static_cast(AZ::AtomBridge::ViewportInfoDisplayState::Invalid)); + state = aznumeric_cast( + (aznumeric_cast(state)+1) % aznumeric_cast(AZ::AtomBridge::ViewportInfoDisplayState::Invalid)); // SetDisplayState will fire OnViewportInfoDisplayStateChanged and notify us, no need to call UpdateDisplayInfo. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 11c727eeca..672c26a9ab 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -35,7 +35,7 @@ namespace AZ::Render // This callback only gets triggered by console commands, so this will not recurse. AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( &AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, - static_cast(newDisplayInfoVal) + aznumeric_cast(newDisplayInfoVal) ); }, AZ::ConsoleFunctorFlags::DontReplicate, "Toggles debugging information display.\n" @@ -184,12 +184,12 @@ namespace AZ::Render AtomBridge::ViewportInfoDisplayState AtomViewportDisplayInfoSystemComponent::GetDisplayState() const { - return static_cast(r_displayInfo.operator int()); + return aznumeric_cast(r_displayInfo.operator int()); } void AtomViewportDisplayInfoSystemComponent::SetDisplayState(AtomBridge::ViewportInfoDisplayState state) { - r_displayInfo = static_cast(state); + r_displayInfo = aznumeric_cast(state); AtomBridge::AtomViewportInfoDisplayNotificationBus::Broadcast( &AtomBridge::AtomViewportInfoDisplayNotificationBus::Events::OnViewportInfoDisplayStateChanged, state); @@ -254,10 +254,10 @@ namespace AZ::Render if (!m_tickRequests) { m_tickRequests = AZ::TickRequestBus::FindFirstHandler(); - } - if (!m_tickRequests) - { - return; + if (!m_tickRequests) + { + return; + } } AZ::ScriptTimePoint currentTime = m_tickRequests->GetTimeAtCurrentTick();