123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "EditorDefs.h"
- #include "Viewport.h"
- // Qt
- #include <QPainter>
- // AzQtComponents
- #include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h>
- #include <AzCore/Math/IntersectSegment.h>
- // AzToolsFramework
- #include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
- #include <AzToolsFramework/Viewport/ViewportMessages.h>
- #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
- // Editor
- #include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h"
- #include "ViewManager.h"
- #include "Include/HitContext.h"
- #include "Util/3DConnexionDriver.h"
- #include "PluginManager.h"
- #include "GameEngine.h"
- #include "Settings.h"
- #include <Editor/EditorViewportSettings.h>
- #ifdef LoadCursor
- #undef LoadCursor
- #endif
- //////////////////////////////////////////////////////////////////////
- // Viewport drag and drop support
- //////////////////////////////////////////////////////////////////////
- void QtViewport::BuildDragDropContext(
- AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point)
- {
- context.m_hitLocation = AzToolsFramework::FindClosestPickIntersection(
- viewportId,
- AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point * devicePixelRatioF()),
- AzToolsFramework::EditorPickRayLength,
- AzToolsFramework::GetDefaultEntityPlacementDistance());
- }
- void QtViewport::dragEnterEvent(QDragEnterEvent* event)
- {
- if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
- {
- return;
- }
- // first use the legacy pathway, which assumes its always okay as long as any callback is installed
- if (m_dropCallback)
- {
- event->setDropAction(Qt::CopyAction);
- event->setAccepted(true);
- }
- else
- {
- // new bus-based way of doing it (install a listener!)
- using namespace AzQtComponents;
- ViewportDragContext context;
- BuildDragDropContext(context, GetViewportId(), event->pos());
- DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context);
- }
- }
- void QtViewport::dragMoveEvent(QDragMoveEvent* event)
- {
- if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
- {
- return;
- }
- // first use the legacy pathway, which assumes its always okay as long as any callback is installed
- if (m_dropCallback)
- {
- event->setDropAction(Qt::CopyAction);
- event->setAccepted(true);
- }
- else
- {
- // new bus-based way of doing it (install a listener!)
- using namespace AzQtComponents;
- ViewportDragContext context;
- BuildDragDropContext(context, GetViewportId(), event->pos());
- DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context);
- }
- }
- void QtViewport::dropEvent(QDropEvent* event)
- {
- using namespace AzQtComponents;
- if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
- {
- return;
- }
- // first use the legacy pathway, which assumes its always okay as long as any callback is installed
- if (m_dropCallback)
- {
- m_dropCallback(this, event->pos().x(), event->pos().y(), m_dropCallbackCustom);
- event->setAccepted(true);
- }
- else
- {
- // new bus-based way of doing it (install a listener!)
- ViewportDragContext context;
- BuildDragDropContext(context, GetViewportId(), event->pos());
- DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context);
- if (event->isAccepted())
- {
- // send focus to whatever window accepted it. Its not necessarily this window, as it might be a child embedded in it.
- QWidget* widget = qApp->widgetAt(event->pos());
- if (widget)
- {
- widget->setFocus(Qt::MouseFocusReason);
- }
- }
- }
- }
- void QtViewport::dragLeaveEvent(QDragLeaveEvent* event)
- {
- using namespace AzQtComponents;
- DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragLeave, event);
- }
- //////////////////////////////////////////////////////////////////////////
- float CViewport::GetFOV() const
- {
- return SandboxEditor::CameraDefaultFovRadians();
- }
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- bool QtViewport::m_bDegradateQuality = false;
- QtViewport::QtViewport(QWidget* parent)
- : QWidget(parent)
- , m_renderOverlay(this)
- {
- m_cViewMenu.addMenu(tr("&View Options"))->addAction(tr("&Fullscreen"));
- //connect(action, &QAction::triggered, );
- m_selectionTolerance = 0;
- m_fGridZoom = 1.0f;
- m_nLastUpdateFrame = 0;
- m_nLastMouseMoveFrame = 0;
- //////////////////////////////////////////////////////////////////////////
- // Init standard cursors.
- //////////////////////////////////////////////////////////////////////////
- m_hCurrCursor = QCursor();
- m_hCursor[STD_CURSOR_DEFAULT] = QCursor(Qt::ArrowCursor);
- m_hCursor[STD_CURSOR_HIT] = CMFCUtils::LoadCursor(IDC_POINTER_OBJHIT);
- m_hCursor[STD_CURSOR_MOVE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_MOVE);
- m_hCursor[STD_CURSOR_ROTATE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_ROTATE);
- m_hCursor[STD_CURSOR_SCALE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_SCALE);
- m_hCursor[STD_CURSOR_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_PLUS);
- m_hCursor[STD_CURSOR_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_MINUS);
- m_hCursor[STD_CURSOR_SUBOBJ_SEL] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT);
- m_hCursor[STD_CURSOR_SUBOBJ_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_PLUS);
- m_hCursor[STD_CURSOR_SUBOBJ_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_MINUS);
- m_activeAxis = AXIS_TERRAIN;
- m_screenTM.SetIdentity();
- m_bAdvancedSelectMode = false;
- GetIEditor()->GetViewManager()->RegisterViewport(this);
- m_nCurViewportID = MAX_NUM_VIEWPORTS - 1;
- m_dropCallback = nullptr; // Leroy@Conffx
- setMouseTracking(true);
- setFocusPolicy(Qt::StrongFocus);
- // Create drop target to handle Qt drop events.
- setAcceptDrops(true);
- m_renderOverlay.setVisible(true);
- m_renderOverlay.setUpdatesEnabled(false);
- m_renderOverlay.setMouseTracking(true);
- m_renderOverlay.setObjectName("renderOverlay");
- m_renderOverlay.winId(); // Force the render overlay to create a backing native window
- m_viewportUi.InitializeViewportUi(this, &m_renderOverlay);
- setAcceptDrops(true);
- }
- //////////////////////////////////////////////////////////////////////////
- QtViewport::~QtViewport()
- {
- GetIEditor()->GetViewManager()->UnregisterViewport(this);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::ScreenToClient(QPoint& pPoint) const
- {
- pPoint = mapFromGlobal(pPoint);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::GetDimensions(int* pWidth, int* pHeight) const
- {
- if (pWidth)
- {
- *pWidth = width();
- }
- if (pHeight)
- {
- *pHeight = height();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::AddPostRenderer(IPostRenderer* pPostRenderer)
- {
- stl::push_back_unique(m_postRenderers, pPostRenderer);
- }
- //////////////////////////////////////////////////////////////////////////
- bool QtViewport::RemovePostRenderer(IPostRenderer* pPostRenderer)
- {
- PostRenderers::iterator itr = m_postRenderers.begin();
- PostRenderers::iterator end = m_postRenderers.end();
- for (; itr != end; ++itr)
- {
- if (*itr == pPostRenderer)
- {
- break;
- }
- }
- if (itr != end)
- {
- m_postRenderers.erase(itr);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::OnMouseWheel([[maybe_unused]] Qt::KeyboardModifiers modifiers, short zDelta, [[maybe_unused]] const QPoint& pt)
- {
- if (zDelta != 0)
- {
- float z = GetZoomFactor() + (zDelta / 120.0f) * 0.5f;
- SetZoomFactor(z);
- GetIEditor()->GetViewManager()->SetZoomFactor(z);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- QString QtViewport::GetName() const
- {
- return windowTitle();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetName(const QString& name)
- {
- setWindowTitle(name);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::resizeEvent(QResizeEvent* event)
- {
- QWidget::resizeEvent(event);
- m_renderOverlay.setGeometry(rect());
- Update();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event)
- {
- QPainter painter(this);
- // Fill the entire client area
- painter.fillRect(rect(), QColor(0xf0, 0xf0, 0xf0));
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::OnActivate()
- {
- ////////////////////////////////////////////////////////////////////////
- // Make this edit window the current one
- ////////////////////////////////////////////////////////////////////////
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::OnDeactivate()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::ResetContent()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::UpdateContent(int flags)
- {
- if (flags & eRedrawViewports)
- {
- update();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::Update()
- {
- m_viewportUi.Update();
- m_bAdvancedSelectMode = false;
- if (CheckVirtualKey(Qt::Key_Space) && !CheckVirtualKey(Qt::Key_Shift) && hasFocus())
- {
- m_bAdvancedSelectMode = true;
- }
- m_nLastUpdateFrame++;
- }
- //////////////////////////////////////////////////////////////////////////
- QPoint QtViewport::WorldToView(const Vec3& wp) const
- {
- return QPoint(static_cast<int>(wp.x), static_cast<int>(wp.y));
- }
- //////////////////////////////////////////////////////////////////////////
- Vec3 QtViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) const
- {
- QPoint p = WorldToView(wp);
- Vec3 out;
- out.x = static_cast<f32>(p.x());
- out.y = static_cast<f32>(p.y());
- out.z = wp.z;
- return out;
- }
- //////////////////////////////////////////////////////////////////////////
- Vec3 QtViewport::ViewToWorld(const QPoint& vp, bool* pCollideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const
- {
- Vec3 wp;
- wp.x = static_cast<f32>(vp.x());
- wp.y = static_cast<f32>(vp.y());
- wp.z = 0;
- if (pCollideWithTerrain)
- {
- *pCollideWithTerrain = true;
- }
- return wp;
- }
- //////////////////////////////////////////////////////////////////////////
- Vec3 QtViewport::ViewToWorldNormal([[maybe_unused]] const QPoint& vp, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bTestRenderMesh)
- {
- return Vec3(0, 0, 0);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::ViewToWorldRay([[maybe_unused]] const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const
- {
- raySrc(0, 0, 0);
- rayDir(0, 0, -1);
- }
- void QtViewport::mousePressEvent(QMouseEvent* event)
- {
- switch (event->button())
- {
- case Qt::LeftButton:
- OnLButtonDown(event->modifiers(), event->pos());
- break;
- case Qt::MiddleButton:
- OnMButtonDown(event->modifiers(), event->pos());
- break;
- case Qt::RightButton:
- OnRButtonDown(event->modifiers(), event->pos());
- break;
- }
- }
- void QtViewport::mouseReleaseEvent(QMouseEvent* event)
- {
- switch (event->button())
- {
- case Qt::LeftButton:
- OnLButtonUp(event->modifiers(), event->pos());
- break;
- case Qt::MiddleButton:
- OnMButtonUp(event->modifiers(), event->pos());
- break;
- case Qt::RightButton:
- OnRButtonUp(event->modifiers(), event->pos());
- break;
- }
- // For MFC compatibility, send a spurious move event after a button release.
- // CryDesigner depends on this behaviour
- mouseMoveEvent(event);
- }
- void QtViewport::mouseDoubleClickEvent(QMouseEvent* event)
- {
- switch (event->button())
- {
- case Qt::LeftButton:
- OnLButtonDblClk(event->modifiers(), event->pos());
- break;
- case Qt::MiddleButton:
- OnMButtonDblClk(event->modifiers(), event->pos());
- break;
- case Qt::RightButton:
- OnRButtonDblClk(event->modifiers(), event->pos());
- break;
- }
- }
- void QtViewport::mouseMoveEvent(QMouseEvent* event)
- {
- OnMouseMove(event->modifiers(), event->buttons(), event->pos());
- OnSetCursor();
- }
- void QtViewport::wheelEvent(QWheelEvent* event)
- {
- OnMouseWheel(event->modifiers(), static_cast<short>(event->angleDelta().y()), event->position().toPoint());
- event->accept();
- }
- void QtViewport::keyPressEvent(QKeyEvent* event)
- {
- int nativeKey = event->nativeVirtualKey();
- #if AZ_TRAIT_OS_PLATFORM_APPLE
- // nativeVirtualKey is always zero on macOS, therefore we
- // need to manually set the nativeKey based on the Qt key
- switch (event->key())
- {
- case Qt::Key_Control:
- nativeKey = VK_CONTROL;
- break;
- case Qt::Key_Alt:
- nativeKey = VK_MENU;
- break;
- case Qt::Key_QuoteLeft:
- nativeKey = VK_OEM_3;
- break;
- case Qt::Key_BracketLeft:
- nativeKey = VK_OEM_4;
- break;
- case Qt::Key_BracketRight:
- nativeKey = VK_OEM_6;
- break;
- case Qt::Key_Comma:
- nativeKey = VK_OEM_COMMA;
- break;
- case Qt::Key_Period:
- nativeKey = VK_OEM_PERIOD;
- break;
- case Qt::Key_Escape:
- nativeKey = VK_ESCAPE;
- break;
- }
- #endif
- OnKeyDown(nativeKey, 1, event->nativeModifiers());
- }
- void QtViewport::keyReleaseEvent(QKeyEvent* event)
- {
- int nativeKey = event->nativeVirtualKey();
- #if AZ_TRAIT_OS_PLATFORM_APPLE
- // nativeVirtualKey is always zero on macOS, therefore we
- // need to manually set the nativeKey based on the Qt key
- switch (event->key())
- {
- case Qt::Key_Control:
- nativeKey = VK_CONTROL;
- break;
- case Qt::Key_Alt:
- nativeKey = VK_MENU;
- break;
- case Qt::Key_QuoteLeft:
- nativeKey = VK_OEM_3;
- break;
- case Qt::Key_BracketLeft:
- nativeKey = VK_OEM_4;
- break;
- case Qt::Key_BracketRight:
- nativeKey = VK_OEM_6;
- break;
- case Qt::Key_Comma:
- nativeKey = VK_OEM_COMMA;
- break;
- case Qt::Key_Period:
- nativeKey = VK_OEM_PERIOD;
- break;
- case Qt::Key_Escape:
- nativeKey = VK_ESCAPE;
- break;
- }
- #endif
- OnKeyUp(nativeKey, 1, event->nativeModifiers());
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::OnSetCursor()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::ResetSelectionRegion()
- {
- AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0));
- m_selectedRect = QRect();
- }
- void QtViewport::SetSelectionRectangle(const QRect& rect)
- {
- m_selectedRect = rect.normalized();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect)
- {
- Vec3 org;
- AABB box;
- box.Reset();
- //adjust QRect bottom and right corner once before extracting bottom/right coordinates
- const QRect correctedRect = rect.adjusted(0, 0, 1, 1);
- Vec3 p1 = ViewToWorld(correctedRect.topLeft());
- Vec3 p2 = ViewToWorld(correctedRect.bottomRight());
- org = p1;
- // Calculate selection volume.
- if (!bNormalizeRect)
- {
- box.Add(p1);
- box.Add(p2);
- }
- else
- {
- const QRect rc = correctedRect.normalized();
- box.Add(ViewToWorld(rc.topLeft()));
- box.Add(ViewToWorld(rc.topRight()));
- box.Add(ViewToWorld(rc.bottomLeft()));
- box.Add(ViewToWorld(rc.bottomRight()));
- }
- box.min.z = -10000;
- box.max.z = 10000;
- // Show marker position in the status bar
- float w = box.max.x - box.min.x;
- float h = box.max.y - box.min.y;
- char szNewStatusText[512];
- sprintf_s(szNewStatusText, "X:%g Y:%g Z:%g W:%g H:%g", org.x, org.y, org.z, w, h);
- GetIEditor()->SetStatusText(szNewStatusText);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString)
- {
- setCursor(hCursor);
- m_cursorStr = cursorString;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetCurrentCursor(EStdCursor stdCursor, const QString& cursorString)
- {
- QCursor hCursor = m_hCursor[stdCursor];
- setCursor(hCursor);
- m_cursorStr = cursorString;
- }
- void QtViewport::SetSupplementaryCursorStr(const QString& str)
- {
- m_cursorSupplementaryStr = str;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetCurrentCursor(EStdCursor stdCursor)
- {
- QCursor hCursor = m_hCursor[stdCursor];
- setCursor(hCursor);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetCursorString(const QString& cursorString)
- {
- m_cursorStr = cursorString;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::ResetCursor()
- {
- SetCurrentCursor(STD_CURSOR_DEFAULT, QString());
- }
- //////////////////////////////////////////////////////////////////////////
- HWND QtViewport::renderOverlayHWND() const
- {
- return reinterpret_cast<HWND>(m_renderOverlay.winId());
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::setRenderOverlayVisible(bool visible)
- {
- m_renderOverlay.setVisible(visible);
- }
- bool QtViewport::isRenderOverlayVisible() const
- {
- return m_renderOverlay.isVisible();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetAxisConstrain(int axis)
- {
- m_activeAxis = axis;
- };
- AzToolsFramework::ViewportInteraction::MouseInteraction QtViewport::BuildMouseInteraction(
- [[maybe_unused]] Qt::MouseButtons buttons, [[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point)
- {
- // Implemented by sub-class
- return AzToolsFramework::ViewportInteraction::MouseInteraction();
- }
- //////////////////////////////////////////////////////////////////////////
- bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
- {
- Vec3 raySrc(0, 0, 0), rayDir(1, 0, 0);
- ViewToWorldRay(point, hitInfo.raySrc, hitInfo.rayDir);
- hitInfo.view = this;
- hitInfo.point2d = point;
- if (m_bAdvancedSelectMode)
- {
- hitInfo.bUseSelectionHelpers = true;
- }
- const int viewportId = GetViewportId();
- AzToolsFramework::EntityIdList visibleEntityIds;
- AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
- viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
- visibleEntityIds);
- // Look through all visible entities to find the closest one to the specified mouse point
- using namespace AzToolsFramework::ViewportInteraction;
- AZ::EntityId entityIdUnderCursor;
- float closestDistance = std::numeric_limits<float>::max();
- MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(),
- QGuiApplication::queryKeyboardModifiers(),
- point);
- for (auto entityId : visibleEntityIds)
- {
- using AzFramework::ViewportInfo;
- // Check if components provide an aabb
- if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId });
- aabb.IsValid())
- {
- // Coarse grain check
- if (AzToolsFramework::AabbIntersectMouseRay(mouseInteraction, aabb))
- {
- // If success, pick against specific component
- if (AzToolsFramework::PickEntity(
- entityId, mouseInteraction,
- closestDistance, viewportId))
- {
- entityIdUnderCursor = entityId;
- }
- }
- }
- }
- // If we hit a valid Entity, then store the distance in the HitContext
- // so that the caller can use this for calculations
- if (entityIdUnderCursor.IsValid())
- {
- hitInfo.dist = closestDistance;
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::SetZoomFactor(float fZoomFactor)
- {
- m_fZoomFactor = fZoomFactor;
- if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
- {
- GetViewManager()->SetZoom2D(fZoomFactor);
- }
- };
- //////////////////////////////////////////////////////////////////////////
- float QtViewport::GetZoomFactor() const
- {
- if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
- {
- m_fZoomFactor = GetViewManager()->GetZoom2D();
- }
- return m_fZoomFactor;
- };
- //////////////////////////////////////////////////////////////////////////
- Vec3 QtViewport::SnapToGrid(const Vec3& vec)
- {
- return vec;
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::BeginUndo()
- {
- DegradateQuality(true);
- GetIEditor()->BeginUndo();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::AcceptUndo(const QString& undoDescription)
- {
- DegradateQuality(false);
- GetIEditor()->AcceptUndo(undoDescription);
- GetIEditor()->UpdateViews(eUpdateObjects);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::CancelUndo()
- {
- DegradateQuality(false);
- GetIEditor()->CancelUndo();
- GetIEditor()->UpdateViews(eUpdateObjects);
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::RestoreUndo()
- {
- GetIEditor()->RestoreUndo();
- }
- //////////////////////////////////////////////////////////////////////////
- bool QtViewport::IsUndoRecording() const
- {
- return GetIEditor()->IsUndoRecording();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::DegradateQuality(bool bEnable)
- {
- m_bDegradateQuality = bEnable;
- }
- //////////////////////////////////////////////////////////////////////////
- QSize QtViewport::GetIdealSize() const
- {
- return QSize(0, 0);
- }
- //////////////////////////////////////////////////////////////////////////
- bool QtViewport::IsBoundsVisible([[maybe_unused]] const AABB& box) const
- {
- // Always visible in standard implementation.
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- float QtViewport::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const
- {
- QPoint p1 = WorldToView(lineP1);
- QPoint p2 = WorldToView(lineP2);
- return AZ::Intersect::PointSegmentDistanceSq(
- AZ::Vector3(static_cast<f32>(point.x()), static_cast<f32>(point.y()), 0.0f),
- AZ::Vector3(static_cast<f32>(p1.x()), static_cast<f32>(p1.y()), 0.0f),
- AZ::Vector3(static_cast<f32>(p2.x()), static_cast<f32>(p2.y()), 0.0f)
- );
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::GetPerpendicularAxis(EAxis* pAxis, bool* pIs2D) const
- {
- EViewportType vpType = GetType();
- switch (vpType)
- {
- case ET_ViewportXY:
- if (pIs2D)
- {
- *pIs2D = true;
- }
- if (pAxis)
- {
- *pAxis = AXIS_Z;
- }
- break;
- case ET_ViewportXZ:
- if (pIs2D)
- {
- *pIs2D = true;
- }
- if (pAxis)
- {
- *pAxis = AXIS_Y;
- }
- break;
- case ET_ViewportYZ:
- if (pIs2D)
- {
- *pIs2D = true;
- }
- if (pAxis)
- {
- *pAxis = AXIS_X;
- }
- break;
- case ET_ViewportMap:
- case ET_ViewportZ:
- if (pIs2D)
- {
- *pIs2D = true;
- }
- break;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool QtViewport::GetAdvancedSelectModeFlag()
- {
- return m_bAdvancedSelectMode;
- }
- //////////////////////////////////////////////////////////////////////////
- #if defined(AZ_PLATFORM_WINDOWS)
- // Note: Both CreateAnglesYPR and CreateOrientationYPR were copied verbatim from Cry_Camera.h which has been removed.
- //
- // Description
- // <PRE>
- // x-YAW
- // y-PITCH (negative=looking down / positive=looking up)
- // z-ROLL
- // </PRE>
- // Note: If we are looking along the z-axis, its not possible to specify the x and z-angle
- inline Ang3 CreateAnglesYPR(const Matrix33& m)
- {
- assert(m.IsOrthonormal());
- float l = Vec3(m.m01, m.m11, 0.0f).GetLength();
- if (l > 0.0001)
- {
- return Ang3(atan2f(-m.m01 / l, m.m11 / l), atan2f(m.m21, l), atan2f(-m.m20 / l, m.m22 / l));
- }
- else
- {
- return Ang3(0, atan2f(m.m21, l), 0);
- }
- }
- // Description
- // This function builds a 3x3 orientation matrix using YPR-angles
- // Rotation order for the orientation-matrix is Z-X-Y. (Zaxis=YAW / Xaxis=PITCH / Yaxis=ROLL)
- //
- // <PRE>
- // COORDINATE-SYSTEM
- //
- // z-axis
- // ^
- // |
- // | y-axis
- // | /
- // | /
- // |/
- // +---------------> x-axis
- // </PRE>
- //
- // Example:
- // Matrix33 orientation=CreateOrientationYPR( Ang3(1,2,3) );
- inline Matrix33 CreateOrientationYPR(const Ang3& ypr)
- {
- f32 sz, cz;
- sincos_tpl(ypr.x, &sz, &cz); //Zaxis = YAW
- f32 sx, cx;
- sincos_tpl(ypr.y, &sx, &cx); //Xaxis = PITCH
- f32 sy, cy;
- sincos_tpl(ypr.z, &sy, &cy); //Yaxis = ROLL
- Matrix33 c;
- c.m00 = cy * cz - sy * sz * sx;
- c.m01 = -sz * cx;
- c.m02 = sy * cz + cy * sz * sx;
- c.m10 = cy * sz + sy * sx * cz;
- c.m11 = cz * cx;
- c.m12 = sy * sz - cy * sx * cz;
- c.m20 = -sy * cx;
- c.m21 = sx;
- c.m22 = cy * cx;
- return c;
- }
- void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam)
- {
- static C3DConnexionDriver* p3DConnexionDriver = 0;
- if (GetType() == ET_ViewportCamera)
- {
- if (!p3DConnexionDriver)
- {
- p3DConnexionDriver = (C3DConnexionDriver*)GetIEditor()->GetPluginManager()->GetPluginByGUID("{AD109901-9128-4ffd-8E67-137CB2B1C41B}");
- }
- if (p3DConnexionDriver)
- {
- S3DConnexionMessage msg;
- if (p3DConnexionDriver->GetInputMessageData((LPARAM)lParam, msg))
- {
- if (msg.bGotTranslation || msg.bGotRotation)
- {
- static int all6DOFs[6] = { 0 };
- if (msg.bGotTranslation)
- {
- all6DOFs[0] = msg.raw_translation[0];
- all6DOFs[1] = msg.raw_translation[1];
- all6DOFs[2] = msg.raw_translation[2];
- }
- if (msg.bGotRotation)
- {
- all6DOFs[3] = msg.raw_rotation[0];
- all6DOFs[4] = msg.raw_rotation[1];
- all6DOFs[5] = msg.raw_rotation[2];
- }
- Matrix34 viewTM = GetViewTM();
- // Scale axis according to CVars
- ICVar* sys_scale3DMouseTranslation = gEnv->pConsole->GetCVar("sys_scale3DMouseTranslation");
- ICVar* sys_Scale3DMouseYPR = gEnv->pConsole->GetCVar("sys_Scale3DMouseYPR");
- float fScaleYPR = sys_Scale3DMouseYPR->GetFVal();
- float s = 0.01f * gSettings.cameraMoveSpeed;
- Vec3 t = Vec3(s * all6DOFs[0], -s * all6DOFs[1], -s * all6DOFs[2] * 0.5f);
- t *= sys_scale3DMouseTranslation->GetFVal();
- float as = 0.001f * gSettings.cameraMoveSpeed;
- Ang3 ypr = CreateAnglesYPR(Matrix33(viewTM));
- ypr.x += -all6DOFs[5] * as * fScaleYPR;
- ypr.y = AZStd::clamp(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range
- ypr.z = 0; // to have camera always upward
- viewTM = Matrix34(CreateOrientationYPR(ypr), viewTM.GetTranslation());
- viewTM = viewTM * Matrix34::CreateTranslationMat(t);
- SetViewTM(viewTM);
- }
- }
- }
- }
- }
- #endif
- //////////////////////////////////////////////////////////////////////////
- float QtViewport::GetFOV() const
- {
- return SandboxEditor::CameraDefaultFovRadians();
- }
- //////////////////////////////////////////////////////////////////////////
- void QtViewport::setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir)
- {
- m_vp = vp;
- m_raySrc = raySrc;
- m_rayDir = rayDir;
- }
- #include <moc_Viewport.cpp>
|