From a8d97cf8aa39f515c2f801e7959fdf163edcb866 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Fri, 21 Jan 2022 12:02:20 -0800 Subject: [PATCH] Fix hi-res display issues in UI Editor (#6912) * Fix dpi scaling issues in UI Editor Signed-off-by: abrmich * Remove older method for getting dpi scaling factor Signed-off-by: abrmich * Remove direct call to devicePixelRatioF() Signed-off-by: abrmich * Use existing convenience function Signed-off-by: abrmich * Fix one more text size Signed-off-by: abrmich * Fix compile warning Signed-off-by: abrmich * Remove unnecessary typecast Signed-off-by: abrmich --- Gems/LyShine/Code/Editor/GuideHelpers.cpp | 5 +- Gems/LyShine/Code/Editor/QtHelpers.cpp | 14 ---- Gems/LyShine/Code/Editor/QtHelpers.h | 5 -- Gems/LyShine/Code/Editor/RulerWidget.cpp | 17 ++++- Gems/LyShine/Code/Editor/ViewportHelpers.cpp | 6 +- Gems/LyShine/Code/Editor/ViewportIcon.cpp | 2 +- .../Code/Editor/ViewportInteraction.cpp | 39 +++++----- .../LyShine/Code/Editor/ViewportInteraction.h | 2 +- Gems/LyShine/Code/Editor/ViewportWidget.cpp | 71 ++++++++++++------- Gems/LyShine/Code/Editor/ViewportWidget.h | 13 ++-- 10 files changed, 97 insertions(+), 77 deletions(-) diff --git a/Gems/LyShine/Code/Editor/GuideHelpers.cpp b/Gems/LyShine/Code/Editor/GuideHelpers.cpp index b6d7acc57a..0713782063 100644 --- a/Gems/LyShine/Code/Editor/GuideHelpers.cpp +++ b/Gems/LyShine/Code/Editor/GuideHelpers.cpp @@ -134,7 +134,7 @@ namespace GuideHelpers AZ::Matrix4x4 transform; EBUS_EVENT_ID_RESULT(transform, canvasEntityId, UiCanvasBus, GetCanvasToViewportMatrix); - AZ::Vector2 viewportSize(aznumeric_cast(viewport->size().width()), aznumeric_cast(viewport->size().height())); + AZ::Vector2 viewportSize = viewport->GetRenderViewportSize(); AZ::Color guideColor; EBUS_EVENT_ID_RESULT(guideColor, canvasEntityId, UiEditorCanvasBus, GetGuideColor); @@ -167,8 +167,7 @@ namespace GuideHelpers void DrawGhostGuideLine(Draw2dHelper& draw2d, AZ::EntityId canvasEntityId, bool guideIsVertical, ViewportWidget* viewport, const AZ::Vector2& canvasPoint) { AZ::Vector2 viewportPoint = CanvasHelpers::GetViewportPoint(canvasEntityId, canvasPoint); - - AZ::Vector2 viewportSize(aznumeric_cast(viewport->size().width()), aznumeric_cast(viewport->size().height())); + AZ::Vector2 viewportSize = viewport->GetRenderViewportSize(); // the line is drawn as the inverse of the background color AZ::Color guideColor(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/Gems/LyShine/Code/Editor/QtHelpers.cpp b/Gems/LyShine/Code/Editor/QtHelpers.cpp index d9147463ed..3b38894016 100644 --- a/Gems/LyShine/Code/Editor/QtHelpers.cpp +++ b/Gems/LyShine/Code/Editor/QtHelpers.cpp @@ -29,18 +29,4 @@ namespace QtHelpers bool inWidget = (localPos.x() >= 0 && localPos.x() < size.width() && localPos.y() >= 0 && localPos.y() < size.height()); return inWidget; } - - float GetHighDpiScaleFactor(const QWidget& widget) - { - return static_cast(QHighDpiScaling::factor(widget.windowHandle()->screen())); - } - - QSize GetDpiScaledViewportSize(const QWidget& widget) - { - float dpiScale = GetHighDpiScaleFactor(widget); - float width = ceilf(widget.size().width() * dpiScale); - float height = ceilf(widget.size().height() * dpiScale); - return QSize(static_cast(width), static_cast(height)); - } - } // namespace QtHelpers diff --git a/Gems/LyShine/Code/Editor/QtHelpers.h b/Gems/LyShine/Code/Editor/QtHelpers.h index 4a9e7091ff..1b5f561871 100644 --- a/Gems/LyShine/Code/Editor/QtHelpers.h +++ b/Gems/LyShine/Code/Editor/QtHelpers.h @@ -16,9 +16,4 @@ namespace QtHelpers AZ::Vector2 MapGlobalPosToLocalVector2(const QWidget* widget, const QPoint& pos); bool IsGlobalPosInWidget(const QWidget* widget, const QPoint& pos); - - float GetHighDpiScaleFactor(const QWidget& widget); - - QSize GetDpiScaledViewportSize(const QWidget& widget); - } // namespace QtHelpers diff --git a/Gems/LyShine/Code/Editor/RulerWidget.cpp b/Gems/LyShine/Code/Editor/RulerWidget.cpp index 0a9209ba38..c82a64ac14 100644 --- a/Gems/LyShine/Code/Editor/RulerWidget.cpp +++ b/Gems/LyShine/Code/Editor/RulerWidget.cpp @@ -61,6 +61,14 @@ void RulerWidget::paintEvent([[maybe_unused]] QPaintEvent* event) float scale = translationAndScale.scale; float translation = (m_orientation == Orientation::Horizontal) ? translationAndScale.translation.GetX() : translationAndScale.translation.GetY(); + // Convert back to qt widget coords for painting + float dpiScaleFactor = m_editorWindow->GetViewport()->WidgetToViewportFactor(); + if (dpiScaleFactor != 0.0f) + { + scale /= dpiScaleFactor; + translation /= dpiScaleFactor; + } + // If the viewport is really small then scale can be zero (or very close) which would cause a divide by zero in later math so we just don't paint anything const float epsilon = 0.00001f; if (scale < epsilon) @@ -87,7 +95,9 @@ void RulerWidget::paintEvent([[maybe_unused]] QPaintEvent* event) void RulerWidget::mousePressEvent(QMouseEvent* ev) { // start a drag interaction to create a guide - AZ::Vector2 viewportMousePos = QtHelpers::MapGlobalPosToLocalVector2(m_editorWindow->GetViewport(), ev->globalPos()); + AZ::Vector2 localMousePos = QtHelpers::MapGlobalPosToLocalVector2(m_editorWindow->GetViewport(), ev->globalPos()); + float dpiScaleFactor = m_editorWindow->GetViewport()->WidgetToViewportFactor(); + AZ::Vector2 viewportMousePos = localMousePos * dpiScaleFactor; bool isVertical = m_orientation == Orientation::Vertical; m_dragInteraction = new ViewportAddGuideInteraction(m_editorWindow, m_editorWindow->GetCanvas(), isVertical, viewportMousePos); } @@ -98,7 +108,10 @@ void RulerWidget::mouseMoveEvent(QMouseEvent* ev) // We only get the events if the mouse is pressed down. So we only get here when adding a ruler. if (m_dragInteraction) { - AZ::Vector2 viewportMousePos = QtHelpers::MapGlobalPosToLocalVector2(m_editorWindow->GetViewport(), ev->globalPos()); + AZ::Vector2 localMousePos = QtHelpers::MapGlobalPosToLocalVector2(m_editorWindow->GetViewport(), ev->globalPos()); + float dpiScaleFactor = m_editorWindow->GetViewport()->WidgetToViewportFactor(); + AZ::Vector2 viewportMousePos = localMousePos * dpiScaleFactor; + m_dragInteraction->Update(viewportMousePos); } diff --git a/Gems/LyShine/Code/Editor/ViewportHelpers.cpp b/Gems/LyShine/Code/Editor/ViewportHelpers.cpp index 7d81a12477..ee89b213ef 100644 --- a/Gems/LyShine/Code/Editor/ViewportHelpers.cpp +++ b/Gems/LyShine/Code/Editor/ViewportHelpers.cpp @@ -336,7 +336,7 @@ namespace ViewportHelpers draw2d.SetTextAlignment(IDraw2d::HAlign::Center, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(0.0f); - draw2d.DrawText(rotationString.toUtf8().data(), rotationStringPos, GetDpiScaledSize(16.0f), 1.0f); + draw2d.DrawText(rotationString.toUtf8().data(), rotationStringPos, 8.0f, 1.0f); } } @@ -347,9 +347,11 @@ namespace ViewportHelpers const AZ::Vector2 textLabelOffset(10.0f, -10.0f); QPoint viewportCursorPos = viewport->mapFromGlobal(QCursor::pos()); AZ::Vector2 textPos = AZ::Vector2(aznumeric_cast(viewportCursorPos.x()), aznumeric_cast(viewportCursorPos.y())) + textLabelOffset; + float dpiScale = viewport->WidgetToViewportFactor(); + textPos *= dpiScale; draw2d.SetTextAlignment(IDraw2d::HAlign::Left, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(0.0f); - draw2d.DrawText(textLabel.c_str(), textPos, GetDpiScaledSize(16.0f), 1.0f); + draw2d.DrawText(textLabel.c_str(), textPos, 8.0f, 1.0f); } } // namespace ViewportHelpers diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index 33f2f40ffe..bdbad6afb2 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -296,7 +296,7 @@ void ViewportIcon::DrawDistanceLine(Draw2dHelper& draw2d, AZ::Vector2 start, AZ: draw2d.SetTextAlignment(IDraw2d::HAlign::Center, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(rotation); - draw2d.DrawText(textBuf, textPos, 16.0f * ViewportIcon::GetDpiScaleFactor(), 1.0f); + draw2d.DrawText(textBuf, textPos, 8.0f, 1.0f); } void ViewportIcon::DrawAnchorLinesSplit(Draw2dHelper& draw2d, AZ::Vector2 anchorPos1, AZ::Vector2 anchorPos2, diff --git a/Gems/LyShine/Code/Editor/ViewportInteraction.cpp b/Gems/LyShine/Code/Editor/ViewportInteraction.cpp index a39a7b9cac..7bd55be4bc 100644 --- a/Gems/LyShine/Code/Editor/ViewportInteraction.cpp +++ b/Gems/LyShine/Code/Editor/ViewportInteraction.cpp @@ -674,13 +674,13 @@ void ViewportInteraction::MouseReleaseEvent(QMouseEvent* ev, { // test to see if the mouse position is inside the viewport on each axis const QPoint& pos = ev->pos(); - const QSize& size = m_editorWindow->GetViewport()->size(); + const AZ::Vector2 size = m_editorWindow->GetViewport()->GetRenderViewportSize(); ViewportDragInteraction::EndState inWidget; - if (pos.x() >= 0 && pos.x() < size.width()) - inWidget = pos.y() >= 0 && pos.y() < size.height() ? ViewportDragInteraction::EndState::Inside : ViewportDragInteraction::EndState::OutsideY; + if (pos.x() >= 0 && pos.x() < size.GetX()) + inWidget = pos.y() >= 0 && pos.y() < size.GetY() ? ViewportDragInteraction::EndState::Inside : ViewportDragInteraction::EndState::OutsideY; else - inWidget = pos.y() >= 0 && pos.y() < size.height() ? ViewportDragInteraction::EndState::OutsideX : ViewportDragInteraction::EndState::OutsideXY; + inWidget = pos.y() >= 0 && pos.y() < size.GetY() ? ViewportDragInteraction::EndState::OutsideX : ViewportDragInteraction::EndState::OutsideXY; // Some interactions end differently depending on whether the mouse was released inside or outside the viewport m_dragInteraction->EndInteraction(inWidget); @@ -709,12 +709,12 @@ void ViewportInteraction::MouseReleaseEvent(QMouseEvent* ev, UpdateCursor(); } -void ViewportInteraction::MouseWheelEvent(QWheelEvent* ev) +bool ViewportInteraction::MouseWheelEvent(QWheelEvent* ev) { if (m_leftButtonIsActive || m_middleButtonIsActive) { // Ignore event. - return; + return false; } const QPoint numDegrees(ev->angleDelta()); @@ -735,6 +735,8 @@ void ViewportInteraction::MouseWheelEvent(QWheelEvent* ev) SetCanvasToViewportScale(QuantizeZoomScale(newScale), &pivotPoint); } + + return true; } bool ViewportInteraction::KeyPressEvent(QKeyEvent* ev) @@ -921,27 +923,27 @@ void ViewportInteraction::GetScaleToFitTransformProps(const AZ::Vector2* newCanv EBUS_EVENT_ID_RESULT(canvasSize, m_editorWindow->GetCanvas(), UiCanvasBus, GetCanvasSize); } - QSize viewportSize = QtHelpers::GetDpiScaledViewportSize(*m_editorWindow->GetViewport()); - const int viewportWidth = viewportSize.width(); - const int viewportHeight = viewportSize.height(); + AZ::Vector2 viewportSize = m_editorWindow->GetViewport()->GetRenderViewportSize(); + const float viewportWidth = viewportSize.GetX(); + const float viewportHeight = viewportSize.GetY(); // We pad the edges of the viewport to allow the user to easily see the borders of // the canvas edges, which is especially helpful if there are anchors sitting on // the edges of the canvas. static const int canvasBorderPaddingInPixels = 32; AZ::Vector2 viewportPaddedSize( - aznumeric_cast(viewportWidth - canvasBorderPaddingInPixels), - aznumeric_cast(viewportHeight - canvasBorderPaddingInPixels)); + viewportWidth - canvasBorderPaddingInPixels, + viewportHeight - canvasBorderPaddingInPixels); // Guard against very small viewports if (viewportPaddedSize.GetX() <= 0.0f) { - viewportPaddedSize.SetX(aznumeric_cast(viewportWidth)); + viewportPaddedSize.SetX(viewportWidth); } if (viewportPaddedSize.GetY() <= 0.0f) { - viewportPaddedSize.SetY(aznumeric_cast(viewportHeight)); + viewportPaddedSize.SetY(viewportHeight); } // Use a "scale to fit" approach @@ -949,8 +951,8 @@ void ViewportInteraction::GetScaleToFitTransformProps(const AZ::Vector2* newCanv viewportPaddedSize.GetX() / canvasSize.GetX(), viewportPaddedSize.GetY() / canvasSize.GetY()); - const int scaledCanvasWidth = static_cast(canvasSize.GetX() * canvasToViewportScale); - const int scaledCanvasHeight = static_cast(canvasSize.GetY() * canvasToViewportScale); + const float scaledCanvasWidth = canvasSize.GetX() * canvasToViewportScale; + const float scaledCanvasHeight = canvasSize.GetY() * canvasToViewportScale; // Centers the canvas within the viewport propsOut.translation = AZ::Vector3( @@ -1008,9 +1010,12 @@ void ViewportInteraction::SetCanvasToViewportScale(float newScale, Vec2i* option } else { + AZ::Vector2 viewportSize = m_editorWindow->GetViewport()->GetRenderViewportSize(); + const float viewportWidth = viewportSize.GetX(); + const float viewportHeight = viewportSize.GetY(); pivotPoint = Vec2i( - static_cast(m_editorWindow->GetViewport()->size().width() * 0.5f), - static_cast(m_editorWindow->GetViewport()->size().height() * 0.5f)); + static_cast(viewportWidth * 0.5f), + static_cast(viewportHeight * 0.5f)); } // Get the distance between our pivot point and the upper-left corner of the diff --git a/Gems/LyShine/Code/Editor/ViewportInteraction.h b/Gems/LyShine/Code/Editor/ViewportInteraction.h index a104d87634..b6417977ab 100644 --- a/Gems/LyShine/Code/Editor/ViewportInteraction.h +++ b/Gems/LyShine/Code/Editor/ViewportInteraction.h @@ -77,7 +77,7 @@ public: // member functions const QTreeWidgetItemRawPtrQList& selectedItems); void MouseReleaseEvent(QMouseEvent* ev, const QTreeWidgetItemRawPtrQList& selectedItems); - void MouseWheelEvent(QWheelEvent* ev); + bool MouseWheelEvent(QWheelEvent* ev); bool KeyPressEvent(QKeyEvent* ev); bool KeyReleaseEvent(QKeyEvent* ev); diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.cpp b/Gems/LyShine/Code/Editor/ViewportWidget.cpp index b481e9cbf1..eb5625ac31 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.cpp +++ b/Gems/LyShine/Code/Editor/ViewportWidget.cpp @@ -351,6 +351,17 @@ void ViewportWidget::SetRedrawEnabled(bool enabled) m_canvasRenderIsEnabled = enabled; } +AZ::Vector2 ViewportWidget::GetRenderViewportSize() const +{ + AZ::Vector2 widgetSize(aznumeric_cast(size().width()), aznumeric_cast(size().height())); + return widgetSize * WidgetToViewportFactor(); +} + +float ViewportWidget::WidgetToViewportFactor() const +{ + return GetViewportContext()->GetDpiScalingFactor(); +} + void ViewportWidget::PickItem(AZ::EntityId entityId) { AzToolsFramework::EditorPickModeRequestBus::Broadcast( @@ -496,7 +507,7 @@ void ViewportWidget::OnRenderTick() return; } - const float dpiScale = QtHelpers::GetHighDpiScaleFactor(*this); + const float dpiScale = WidgetToViewportFactor(); ViewportIcon::SetDpiScaleFactor(dpiScale); UiEditorMode editorMode = m_editorWindow->GetEditorMode(); @@ -510,6 +521,12 @@ void ViewportWidget::OnRenderTick() } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +void ViewportWidget::OnViewportDpiScalingChanged(float dpiScale) +{ + ViewportIcon::SetDpiScaleFactor(dpiScale); +} + void ViewportWidget::RefreshTick() { #ifdef LYSHINE_EDITOR_TODO // still need this? @@ -640,27 +657,34 @@ void ViewportWidget::mouseReleaseEvent(QMouseEvent* ev) void ViewportWidget::wheelEvent(QWheelEvent* ev) { + bool handled = false; UiEditorMode editorMode = m_editorWindow->GetEditorMode(); - QWheelEvent scaledEvent( - WidgetToViewport(ev->position()), - ev->globalPosition(), - ev->pixelDelta(), - ev->angleDelta(), - ev->buttons(), - ev->modifiers(), - ev->phase(), - ev->inverted() - ); - if (editorMode == UiEditorMode::Edit) { + QWheelEvent scaledEvent( + WidgetToViewport(ev->position()), + ev->globalPosition(), + ev->pixelDelta(), + ev->angleDelta(), + ev->buttons(), + ev->modifiers(), + ev->phase(), + ev->inverted() + ); + // in Edit mode just send input to ViewportInteraction - m_viewportInteraction->MouseWheelEvent(&scaledEvent); + handled = m_viewportInteraction->MouseWheelEvent(&scaledEvent); } - RenderViewportWidget::wheelEvent(ev); - - Refresh(); + if (handled) + { + ev->accept(); + Refresh(); + } + else + { + RenderViewportWidget::wheelEvent(ev); + } } bool ViewportWidget::eventFilter([[maybe_unused]] QObject* watched, QEvent* event) @@ -975,8 +999,7 @@ void ViewportWidget::RenderEditMode() EBUS_EVENT_ID(canvasEntityId, UiCanvasBus, SetTargetCanvasSize, false, canvasSize); // Render this canvas - QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); + AZ::Vector2 viewportSize = GetRenderViewportSize(); EBUS_EVENT_ID(canvasEntityId, UiEditorCanvasBus, RenderCanvasInEditorViewport, false, viewportSize); m_draw2d->SetSortKey(topLayerKey); @@ -1085,15 +1108,12 @@ void ViewportWidget::UpdatePreviewMode(float deltaTime) if (canvasEntityId.IsValid()) { - QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); - // Get the canvas size AZ::Vector2 canvasSize = m_editorWindow->GetPreviewCanvasSize(); if (canvasSize.GetX() == 0.0f && canvasSize.GetY() == 0.0f) { // special value of (0,0) means use the viewport size - canvasSize = viewportSize; + canvasSize = GetRenderViewportSize();; } // Set the target size of the canvas @@ -1127,8 +1147,7 @@ void ViewportWidget::RenderPreviewMode() if (canvasEntityId.IsValid()) { - QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); + AZ::Vector2 viewportSize = GetRenderViewportSize(); // Get the canvas size AZ::Vector2 canvasSize = m_editorWindow->GetPreviewCanvasSize(); @@ -1208,13 +1227,13 @@ void ViewportWidget::RenderPreviewMode() void ViewportWidget::RenderViewportBackground() { - QSize viewportSize = QtHelpers::GetDpiScaledViewportSize(*this); + AZ::Vector2 viewportSize = GetRenderViewportSize(); AZ::Color backgroundColor = ViewportHelpers::backgroundColorDark; const AZ::Data::Instance& image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); Draw2dHelper draw2d(m_draw2d.get()); draw2d.SetImageColor(backgroundColor.GetAsVector3()); - draw2d.DrawImage(image, AZ::Vector2(0.0f, 0.0f), AZ::Vector2(static_cast(viewportSize.width()), static_cast(viewportSize.height()))); + draw2d.DrawImage(image, AZ::Vector2(0.0f, 0.0f), viewportSize); } void ViewportWidget::SetupShortcuts() diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.h b/Gems/LyShine/Code/Editor/ViewportWidget.h index 722335aa93..c285e0d969 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.h +++ b/Gems/LyShine/Code/Editor/ViewportWidget.h @@ -72,6 +72,12 @@ public: // member functions //! Used by ViewportInteraction for drawing ViewportHighlight* GetViewportHighlight() { return m_viewportHighlight.get(); } + //! Get the size of the RPI render viewport + AZ::Vector2 GetRenderViewportSize() const; + + //! Get the widget to viewport scale factor + float WidgetToViewportFactor() const; + bool IsInObjectPickMode() { return m_inObjectPickMode; } void PickItem(AZ::EntityId entityId); @@ -156,6 +162,7 @@ private: // member functions // AZ::RPI::ViewportContextNotificationBus::Handler overrides... void OnRenderTick() override; + void OnViewportDpiScalingChanged(float dpiScale) override; //! Update UI canvases when in edit mode void UpdateEditMode(float deltaTime); @@ -187,12 +194,6 @@ private: // data bool AcceptsMimeData(const QMimeData* mimeData); - double WidgetToViewportFactor() const - { - // Needed for high DPI mode on windows - return devicePixelRatioF(); - } - QPointF WidgetToViewport(const QPointF &point) const; EditorWindow* m_editorWindow;