Viewport.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "Viewport.h"
  10. // Qt
  11. #include <QPainter>
  12. // AzQtComponents
  13. #include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h>
  14. #include <AzCore/Math/IntersectSegment.h>
  15. #include <MathConversion.h>
  16. // AzToolsFramework
  17. #include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
  18. #include <AzToolsFramework/Viewport/ViewportMessages.h>
  19. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  20. // Editor
  21. #include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h"
  22. #include "ViewManager.h"
  23. #include "Include/HitContext.h"
  24. #include "Util/3DConnexionDriver.h"
  25. #include "PluginManager.h"
  26. #include "GameEngine.h"
  27. #include "Settings.h"
  28. #include <Editor/EditorViewportSettings.h>
  29. #ifdef LoadCursor
  30. #undef LoadCursor
  31. #endif
  32. //////////////////////////////////////////////////////////////////////
  33. // Viewport drag and drop support
  34. //////////////////////////////////////////////////////////////////////
  35. void QtViewport::BuildDragDropContext(
  36. AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point)
  37. {
  38. context.m_hitLocation = AzToolsFramework::FindClosestPickIntersection(
  39. viewportId,
  40. AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point * devicePixelRatioF()),
  41. AzToolsFramework::EditorPickRayLength,
  42. AzToolsFramework::GetDefaultEntityPlacementDistance());
  43. }
  44. void QtViewport::dragEnterEvent(QDragEnterEvent* event)
  45. {
  46. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  47. {
  48. return;
  49. }
  50. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  51. if (m_dropCallback)
  52. {
  53. event->setDropAction(Qt::CopyAction);
  54. event->setAccepted(true);
  55. }
  56. else
  57. {
  58. // new bus-based way of doing it (install a listener!)
  59. using namespace AzQtComponents;
  60. ViewportDragContext context;
  61. BuildDragDropContext(context, GetViewportId(), event->pos());
  62. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context);
  63. }
  64. }
  65. void QtViewport::dragMoveEvent(QDragMoveEvent* event)
  66. {
  67. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  68. {
  69. return;
  70. }
  71. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  72. if (m_dropCallback)
  73. {
  74. event->setDropAction(Qt::CopyAction);
  75. event->setAccepted(true);
  76. }
  77. else
  78. {
  79. // new bus-based way of doing it (install a listener!)
  80. using namespace AzQtComponents;
  81. ViewportDragContext context;
  82. BuildDragDropContext(context, GetViewportId(), event->pos());
  83. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context);
  84. }
  85. }
  86. void QtViewport::dropEvent(QDropEvent* event)
  87. {
  88. using namespace AzQtComponents;
  89. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  90. {
  91. return;
  92. }
  93. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  94. if (m_dropCallback)
  95. {
  96. m_dropCallback(this, event->pos().x(), event->pos().y(), m_dropCallbackCustom);
  97. event->setAccepted(true);
  98. }
  99. else
  100. {
  101. // new bus-based way of doing it (install a listener!)
  102. ViewportDragContext context;
  103. BuildDragDropContext(context, GetViewportId(), event->pos());
  104. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context);
  105. if (event->isAccepted())
  106. {
  107. // send focus to whatever window accepted it. Its not necessarily this window, as it might be a child embedded in it.
  108. QWidget* widget = qApp->widgetAt(event->pos());
  109. if (widget)
  110. {
  111. widget->setFocus(Qt::MouseFocusReason);
  112. }
  113. }
  114. }
  115. }
  116. void QtViewport::dragLeaveEvent(QDragLeaveEvent* event)
  117. {
  118. using namespace AzQtComponents;
  119. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragLeave, event);
  120. }
  121. //////////////////////////////////////////////////////////////////////////
  122. float CViewport::GetFOV() const
  123. {
  124. return SandboxEditor::CameraDefaultFovRadians();
  125. }
  126. //////////////////////////////////////////////////////////////////////
  127. // Construction/Destruction
  128. //////////////////////////////////////////////////////////////////////
  129. bool QtViewport::m_bDegradateQuality = false;
  130. QtViewport::QtViewport(QWidget* parent)
  131. : QWidget(parent)
  132. , m_renderOverlay(this)
  133. {
  134. m_cViewMenu.addMenu(tr("&View Options"))->addAction(tr("&Fullscreen"));
  135. //connect(action, &QAction::triggered, );
  136. m_selectionTolerance = 0;
  137. m_fGridZoom = 1.0f;
  138. m_nLastUpdateFrame = 0;
  139. m_nLastMouseMoveFrame = 0;
  140. //////////////////////////////////////////////////////////////////////////
  141. // Init standard cursors.
  142. //////////////////////////////////////////////////////////////////////////
  143. m_hCurrCursor = QCursor();
  144. m_hCursor[STD_CURSOR_DEFAULT] = QCursor(Qt::ArrowCursor);
  145. m_hCursor[STD_CURSOR_HIT] = CMFCUtils::LoadCursor(IDC_POINTER_OBJHIT);
  146. m_hCursor[STD_CURSOR_MOVE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_MOVE);
  147. m_hCursor[STD_CURSOR_ROTATE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_ROTATE);
  148. m_hCursor[STD_CURSOR_SCALE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_SCALE);
  149. m_hCursor[STD_CURSOR_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_PLUS);
  150. m_hCursor[STD_CURSOR_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_MINUS);
  151. m_hCursor[STD_CURSOR_SUBOBJ_SEL] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT);
  152. m_hCursor[STD_CURSOR_SUBOBJ_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_PLUS);
  153. m_hCursor[STD_CURSOR_SUBOBJ_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_MINUS);
  154. m_activeAxis = AXIS_TERRAIN;
  155. m_screenTM.SetIdentity();
  156. m_bAdvancedSelectMode = false;
  157. GetIEditor()->GetViewManager()->RegisterViewport(this);
  158. m_nCurViewportID = MAX_NUM_VIEWPORTS - 1;
  159. m_dropCallback = nullptr; // Leroy@Conffx
  160. setMouseTracking(true);
  161. setFocusPolicy(Qt::StrongFocus);
  162. // Create drop target to handle Qt drop events.
  163. setAcceptDrops(true);
  164. m_renderOverlay.setVisible(true);
  165. m_renderOverlay.setUpdatesEnabled(false);
  166. m_renderOverlay.setMouseTracking(true);
  167. m_renderOverlay.setObjectName("renderOverlay");
  168. m_renderOverlay.winId(); // Force the render overlay to create a backing native window
  169. m_viewportUi.InitializeViewportUi(this, &m_renderOverlay);
  170. setAcceptDrops(true);
  171. }
  172. //////////////////////////////////////////////////////////////////////////
  173. QtViewport::~QtViewport()
  174. {
  175. GetIEditor()->GetViewManager()->UnregisterViewport(this);
  176. }
  177. //////////////////////////////////////////////////////////////////////////
  178. void QtViewport::ScreenToClient(QPoint& pPoint) const
  179. {
  180. pPoint = mapFromGlobal(pPoint);
  181. }
  182. //////////////////////////////////////////////////////////////////////////
  183. void QtViewport::GetDimensions(int* pWidth, int* pHeight) const
  184. {
  185. if (pWidth)
  186. {
  187. *pWidth = width();
  188. }
  189. if (pHeight)
  190. {
  191. *pHeight = height();
  192. }
  193. }
  194. //////////////////////////////////////////////////////////////////////////
  195. void QtViewport::AddPostRenderer(IPostRenderer* pPostRenderer)
  196. {
  197. stl::push_back_unique(m_postRenderers, pPostRenderer);
  198. }
  199. //////////////////////////////////////////////////////////////////////////
  200. bool QtViewport::RemovePostRenderer(IPostRenderer* pPostRenderer)
  201. {
  202. PostRenderers::iterator itr = m_postRenderers.begin();
  203. PostRenderers::iterator end = m_postRenderers.end();
  204. for (; itr != end; ++itr)
  205. {
  206. if (*itr == pPostRenderer)
  207. {
  208. break;
  209. }
  210. }
  211. if (itr != end)
  212. {
  213. m_postRenderers.erase(itr);
  214. return true;
  215. }
  216. return false;
  217. }
  218. //////////////////////////////////////////////////////////////////////////
  219. void QtViewport::OnMouseWheel([[maybe_unused]] Qt::KeyboardModifiers modifiers, short zDelta, [[maybe_unused]] const QPoint& pt)
  220. {
  221. if (zDelta != 0)
  222. {
  223. float z = GetZoomFactor() + (zDelta / 120.0f) * 0.5f;
  224. SetZoomFactor(z);
  225. GetIEditor()->GetViewManager()->SetZoomFactor(z);
  226. }
  227. }
  228. //////////////////////////////////////////////////////////////////////////
  229. QString QtViewport::GetName() const
  230. {
  231. return windowTitle();
  232. }
  233. //////////////////////////////////////////////////////////////////////////
  234. void QtViewport::SetName(const QString& name)
  235. {
  236. setWindowTitle(name);
  237. }
  238. //////////////////////////////////////////////////////////////////////////
  239. void QtViewport::resizeEvent(QResizeEvent* event)
  240. {
  241. QWidget::resizeEvent(event);
  242. m_renderOverlay.setGeometry(rect());
  243. Update();
  244. }
  245. //////////////////////////////////////////////////////////////////////////
  246. void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event)
  247. {
  248. QPainter painter(this);
  249. // Fill the entire client area
  250. painter.fillRect(rect(), QColor(0xf0, 0xf0, 0xf0));
  251. }
  252. //////////////////////////////////////////////////////////////////////////
  253. void QtViewport::OnActivate()
  254. {
  255. ////////////////////////////////////////////////////////////////////////
  256. // Make this edit window the current one
  257. ////////////////////////////////////////////////////////////////////////
  258. }
  259. //////////////////////////////////////////////////////////////////////////
  260. void QtViewport::OnDeactivate()
  261. {
  262. }
  263. //////////////////////////////////////////////////////////////////////////
  264. void QtViewport::ResetContent()
  265. {
  266. }
  267. //////////////////////////////////////////////////////////////////////////
  268. void QtViewport::UpdateContent(int flags)
  269. {
  270. if (flags & eRedrawViewports)
  271. {
  272. update();
  273. }
  274. }
  275. //////////////////////////////////////////////////////////////////////////
  276. void QtViewport::Update()
  277. {
  278. m_viewportUi.Update();
  279. m_bAdvancedSelectMode = false;
  280. if (CheckVirtualKey(Qt::Key_Space) && !CheckVirtualKey(Qt::Key_Shift) && hasFocus())
  281. {
  282. m_bAdvancedSelectMode = true;
  283. }
  284. m_nLastUpdateFrame++;
  285. }
  286. //////////////////////////////////////////////////////////////////////////
  287. QPoint QtViewport::WorldToView(const Vec3& wp) const
  288. {
  289. return QPoint(static_cast<int>(wp.x), static_cast<int>(wp.y));
  290. }
  291. //////////////////////////////////////////////////////////////////////////
  292. Vec3 QtViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) const
  293. {
  294. QPoint p = WorldToView(wp);
  295. Vec3 out;
  296. out.x = static_cast<f32>(p.x());
  297. out.y = static_cast<f32>(p.y());
  298. out.z = wp.z;
  299. return out;
  300. }
  301. //////////////////////////////////////////////////////////////////////////
  302. 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
  303. {
  304. Vec3 wp;
  305. wp.x = static_cast<f32>(vp.x());
  306. wp.y = static_cast<f32>(vp.y());
  307. wp.z = 0;
  308. if (pCollideWithTerrain)
  309. {
  310. *pCollideWithTerrain = true;
  311. }
  312. return wp;
  313. }
  314. //////////////////////////////////////////////////////////////////////////
  315. Vec3 QtViewport::ViewToWorldNormal([[maybe_unused]] const QPoint& vp, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bTestRenderMesh)
  316. {
  317. return Vec3(0, 0, 0);
  318. }
  319. //////////////////////////////////////////////////////////////////////////
  320. void QtViewport::ViewToWorldRay([[maybe_unused]] const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const
  321. {
  322. raySrc(0, 0, 0);
  323. rayDir(0, 0, -1);
  324. }
  325. void QtViewport::mousePressEvent(QMouseEvent* event)
  326. {
  327. switch (event->button())
  328. {
  329. case Qt::LeftButton:
  330. OnLButtonDown(event->modifiers(), event->pos());
  331. break;
  332. case Qt::MiddleButton:
  333. OnMButtonDown(event->modifiers(), event->pos());
  334. break;
  335. case Qt::RightButton:
  336. OnRButtonDown(event->modifiers(), event->pos());
  337. break;
  338. }
  339. }
  340. void QtViewport::mouseReleaseEvent(QMouseEvent* event)
  341. {
  342. switch (event->button())
  343. {
  344. case Qt::LeftButton:
  345. OnLButtonUp(event->modifiers(), event->pos());
  346. break;
  347. case Qt::MiddleButton:
  348. OnMButtonUp(event->modifiers(), event->pos());
  349. break;
  350. case Qt::RightButton:
  351. OnRButtonUp(event->modifiers(), event->pos());
  352. break;
  353. }
  354. // For MFC compatibility, send a spurious move event after a button release.
  355. // CryDesigner depends on this behaviour
  356. mouseMoveEvent(event);
  357. }
  358. void QtViewport::mouseDoubleClickEvent(QMouseEvent* event)
  359. {
  360. switch (event->button())
  361. {
  362. case Qt::LeftButton:
  363. OnLButtonDblClk(event->modifiers(), event->pos());
  364. break;
  365. case Qt::MiddleButton:
  366. OnMButtonDblClk(event->modifiers(), event->pos());
  367. break;
  368. case Qt::RightButton:
  369. OnRButtonDblClk(event->modifiers(), event->pos());
  370. break;
  371. }
  372. }
  373. void QtViewport::mouseMoveEvent(QMouseEvent* event)
  374. {
  375. OnMouseMove(event->modifiers(), event->buttons(), event->pos());
  376. OnSetCursor();
  377. }
  378. void QtViewport::wheelEvent(QWheelEvent* event)
  379. {
  380. OnMouseWheel(event->modifiers(), static_cast<short>(event->angleDelta().y()), event->position().toPoint());
  381. event->accept();
  382. }
  383. void QtViewport::keyPressEvent(QKeyEvent* event)
  384. {
  385. int nativeKey = event->nativeVirtualKey();
  386. #if AZ_TRAIT_OS_PLATFORM_APPLE
  387. // nativeVirtualKey is always zero on macOS, therefore we
  388. // need to manually set the nativeKey based on the Qt key
  389. switch (event->key())
  390. {
  391. case Qt::Key_Control:
  392. nativeKey = VK_CONTROL;
  393. break;
  394. case Qt::Key_Alt:
  395. nativeKey = VK_MENU;
  396. break;
  397. case Qt::Key_QuoteLeft:
  398. nativeKey = VK_OEM_3;
  399. break;
  400. case Qt::Key_BracketLeft:
  401. nativeKey = VK_OEM_4;
  402. break;
  403. case Qt::Key_BracketRight:
  404. nativeKey = VK_OEM_6;
  405. break;
  406. case Qt::Key_Comma:
  407. nativeKey = VK_OEM_COMMA;
  408. break;
  409. case Qt::Key_Period:
  410. nativeKey = VK_OEM_PERIOD;
  411. break;
  412. case Qt::Key_Escape:
  413. nativeKey = VK_ESCAPE;
  414. break;
  415. }
  416. #endif
  417. OnKeyDown(nativeKey, 1, event->nativeModifiers());
  418. }
  419. void QtViewport::keyReleaseEvent(QKeyEvent* event)
  420. {
  421. int nativeKey = event->nativeVirtualKey();
  422. #if AZ_TRAIT_OS_PLATFORM_APPLE
  423. // nativeVirtualKey is always zero on macOS, therefore we
  424. // need to manually set the nativeKey based on the Qt key
  425. switch (event->key())
  426. {
  427. case Qt::Key_Control:
  428. nativeKey = VK_CONTROL;
  429. break;
  430. case Qt::Key_Alt:
  431. nativeKey = VK_MENU;
  432. break;
  433. case Qt::Key_QuoteLeft:
  434. nativeKey = VK_OEM_3;
  435. break;
  436. case Qt::Key_BracketLeft:
  437. nativeKey = VK_OEM_4;
  438. break;
  439. case Qt::Key_BracketRight:
  440. nativeKey = VK_OEM_6;
  441. break;
  442. case Qt::Key_Comma:
  443. nativeKey = VK_OEM_COMMA;
  444. break;
  445. case Qt::Key_Period:
  446. nativeKey = VK_OEM_PERIOD;
  447. break;
  448. case Qt::Key_Escape:
  449. nativeKey = VK_ESCAPE;
  450. break;
  451. }
  452. #endif
  453. OnKeyUp(nativeKey, 1, event->nativeModifiers());
  454. }
  455. //////////////////////////////////////////////////////////////////////////
  456. void QtViewport::OnSetCursor()
  457. {
  458. }
  459. //////////////////////////////////////////////////////////////////////////
  460. void QtViewport::ResetSelectionRegion()
  461. {
  462. m_selectedRect = QRect();
  463. }
  464. void QtViewport::SetSelectionRectangle(const QRect& rect)
  465. {
  466. m_selectedRect = rect.normalized();
  467. }
  468. //////////////////////////////////////////////////////////////////////////
  469. void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect)
  470. {
  471. Vec3 org;
  472. AZ::Aabb box = AZ::Aabb::CreateNull();
  473. //adjust QRect bottom and right corner once before extracting bottom/right coordinates
  474. const QRect correctedRect = rect.adjusted(0, 0, 1, 1);
  475. Vec3 p1 = ViewToWorld(correctedRect.topLeft());
  476. Vec3 p2 = ViewToWorld(correctedRect.bottomRight());
  477. org = p1;
  478. // Calculate selection volume.
  479. if (!bNormalizeRect)
  480. {
  481. box.AddPoint(LYVec3ToAZVec3(p1));
  482. box.AddPoint(LYVec3ToAZVec3(p2));
  483. }
  484. else
  485. {
  486. const QRect rc = correctedRect.normalized();
  487. box.AddPoint(LYVec3ToAZVec3(ViewToWorld(rc.topLeft())));
  488. box.AddPoint(LYVec3ToAZVec3(ViewToWorld(rc.topRight())));
  489. box.AddPoint(LYVec3ToAZVec3(ViewToWorld(rc.bottomLeft())));
  490. box.AddPoint(LYVec3ToAZVec3(ViewToWorld(rc.bottomRight())));
  491. }
  492. AZ::Vector3 boxMin = box.GetMin();
  493. AZ::Vector3 boxMax = box.GetMax();
  494. boxMin.SetZ(-10000);
  495. boxMax.SetZ(10000);
  496. box.Set(boxMin, boxMax);
  497. // Show marker position in the status bar
  498. float w = box.GetXExtent();
  499. float h = box.GetYExtent();
  500. char szNewStatusText[512];
  501. sprintf_s(szNewStatusText, "X:%g Y:%g Z:%g W:%g H:%g", org.x, org.y, org.z, w, h);
  502. GetIEditor()->SetStatusText(szNewStatusText);
  503. }
  504. //////////////////////////////////////////////////////////////////////////
  505. void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString)
  506. {
  507. setCursor(hCursor);
  508. m_cursorStr = cursorString;
  509. }
  510. //////////////////////////////////////////////////////////////////////////
  511. void QtViewport::SetCurrentCursor(EStdCursor stdCursor, const QString& cursorString)
  512. {
  513. QCursor hCursor = m_hCursor[stdCursor];
  514. setCursor(hCursor);
  515. m_cursorStr = cursorString;
  516. }
  517. void QtViewport::SetSupplementaryCursorStr(const QString& str)
  518. {
  519. m_cursorSupplementaryStr = str;
  520. }
  521. //////////////////////////////////////////////////////////////////////////
  522. void QtViewport::SetCurrentCursor(EStdCursor stdCursor)
  523. {
  524. QCursor hCursor = m_hCursor[stdCursor];
  525. setCursor(hCursor);
  526. }
  527. //////////////////////////////////////////////////////////////////////////
  528. void QtViewport::SetCursorString(const QString& cursorString)
  529. {
  530. m_cursorStr = cursorString;
  531. }
  532. //////////////////////////////////////////////////////////////////////////
  533. void QtViewport::ResetCursor()
  534. {
  535. SetCurrentCursor(STD_CURSOR_DEFAULT, QString());
  536. }
  537. //////////////////////////////////////////////////////////////////////////
  538. HWND QtViewport::renderOverlayHWND() const
  539. {
  540. return reinterpret_cast<HWND>(m_renderOverlay.winId());
  541. }
  542. //////////////////////////////////////////////////////////////////////////
  543. void QtViewport::setRenderOverlayVisible(bool visible)
  544. {
  545. m_renderOverlay.setVisible(visible);
  546. }
  547. bool QtViewport::isRenderOverlayVisible() const
  548. {
  549. return m_renderOverlay.isVisible();
  550. }
  551. //////////////////////////////////////////////////////////////////////////
  552. void QtViewport::SetAxisConstrain(int axis)
  553. {
  554. m_activeAxis = axis;
  555. };
  556. AzToolsFramework::ViewportInteraction::MouseInteraction QtViewport::BuildMouseInteraction(
  557. [[maybe_unused]] Qt::MouseButtons buttons, [[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point)
  558. {
  559. // Implemented by sub-class
  560. return AzToolsFramework::ViewportInteraction::MouseInteraction();
  561. }
  562. //////////////////////////////////////////////////////////////////////////
  563. bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
  564. {
  565. Vec3 raySrc(0, 0, 0), rayDir(1, 0, 0);
  566. ViewToWorldRay(point, hitInfo.raySrc, hitInfo.rayDir);
  567. hitInfo.view = this;
  568. hitInfo.point2d = point;
  569. if (m_bAdvancedSelectMode)
  570. {
  571. hitInfo.bUseSelectionHelpers = true;
  572. }
  573. const int viewportId = GetViewportId();
  574. AzToolsFramework::EntityIdList visibleEntityIds;
  575. AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
  576. viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
  577. visibleEntityIds);
  578. // Look through all visible entities to find the closest one to the specified mouse point
  579. using namespace AzToolsFramework::ViewportInteraction;
  580. AZ::EntityId entityIdUnderCursor;
  581. float closestDistance = std::numeric_limits<float>::max();
  582. MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(),
  583. QGuiApplication::queryKeyboardModifiers(),
  584. point);
  585. for (auto entityId : visibleEntityIds)
  586. {
  587. using AzFramework::ViewportInfo;
  588. // Check if components provide an aabb
  589. if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId });
  590. aabb.IsValid())
  591. {
  592. // Coarse grain check
  593. if (AzToolsFramework::AabbIntersectMouseRay(mouseInteraction, aabb))
  594. {
  595. // If success, pick against specific component
  596. if (AzToolsFramework::PickEntity(
  597. entityId, mouseInteraction,
  598. closestDistance, viewportId))
  599. {
  600. entityIdUnderCursor = entityId;
  601. }
  602. }
  603. }
  604. }
  605. // If we hit a valid Entity, then store the distance in the HitContext
  606. // so that the caller can use this for calculations
  607. if (entityIdUnderCursor.IsValid())
  608. {
  609. hitInfo.dist = closestDistance;
  610. return true;
  611. }
  612. return false;
  613. }
  614. //////////////////////////////////////////////////////////////////////////
  615. void QtViewport::SetZoomFactor(float fZoomFactor)
  616. {
  617. m_fZoomFactor = fZoomFactor;
  618. if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
  619. {
  620. GetViewManager()->SetZoom2D(fZoomFactor);
  621. }
  622. };
  623. //////////////////////////////////////////////////////////////////////////
  624. float QtViewport::GetZoomFactor() const
  625. {
  626. if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
  627. {
  628. m_fZoomFactor = GetViewManager()->GetZoom2D();
  629. }
  630. return m_fZoomFactor;
  631. };
  632. //////////////////////////////////////////////////////////////////////////
  633. Vec3 QtViewport::SnapToGrid(const Vec3& vec)
  634. {
  635. return vec;
  636. }
  637. //////////////////////////////////////////////////////////////////////////
  638. void QtViewport::BeginUndo()
  639. {
  640. DegradateQuality(true);
  641. GetIEditor()->BeginUndo();
  642. }
  643. //////////////////////////////////////////////////////////////////////////
  644. void QtViewport::AcceptUndo(const QString& undoDescription)
  645. {
  646. DegradateQuality(false);
  647. GetIEditor()->AcceptUndo(undoDescription);
  648. GetIEditor()->UpdateViews(eUpdateObjects);
  649. }
  650. //////////////////////////////////////////////////////////////////////////
  651. void QtViewport::CancelUndo()
  652. {
  653. DegradateQuality(false);
  654. GetIEditor()->CancelUndo();
  655. GetIEditor()->UpdateViews(eUpdateObjects);
  656. }
  657. //////////////////////////////////////////////////////////////////////////
  658. void QtViewport::RestoreUndo()
  659. {
  660. GetIEditor()->RestoreUndo();
  661. }
  662. //////////////////////////////////////////////////////////////////////////
  663. bool QtViewport::IsUndoRecording() const
  664. {
  665. return GetIEditor()->IsUndoRecording();
  666. }
  667. //////////////////////////////////////////////////////////////////////////
  668. void QtViewport::DegradateQuality(bool bEnable)
  669. {
  670. m_bDegradateQuality = bEnable;
  671. }
  672. //////////////////////////////////////////////////////////////////////////
  673. QSize QtViewport::GetIdealSize() const
  674. {
  675. return QSize(0, 0);
  676. }
  677. //////////////////////////////////////////////////////////////////////////
  678. bool QtViewport::IsBoundsVisible([[maybe_unused]] const AZ::Aabb& box) const
  679. {
  680. // Always visible in standard implementation.
  681. return true;
  682. }
  683. //////////////////////////////////////////////////////////////////////////
  684. float QtViewport::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const
  685. {
  686. QPoint p1 = WorldToView(lineP1);
  687. QPoint p2 = WorldToView(lineP2);
  688. return AZ::Intersect::PointSegmentDistanceSq(
  689. AZ::Vector3(static_cast<f32>(point.x()), static_cast<f32>(point.y()), 0.0f),
  690. AZ::Vector3(static_cast<f32>(p1.x()), static_cast<f32>(p1.y()), 0.0f),
  691. AZ::Vector3(static_cast<f32>(p2.x()), static_cast<f32>(p2.y()), 0.0f)
  692. );
  693. }
  694. //////////////////////////////////////////////////////////////////////////
  695. void QtViewport::GetPerpendicularAxis(EAxis* pAxis, bool* pIs2D) const
  696. {
  697. EViewportType vpType = GetType();
  698. switch (vpType)
  699. {
  700. case ET_ViewportXY:
  701. if (pIs2D)
  702. {
  703. *pIs2D = true;
  704. }
  705. if (pAxis)
  706. {
  707. *pAxis = AXIS_Z;
  708. }
  709. break;
  710. case ET_ViewportXZ:
  711. if (pIs2D)
  712. {
  713. *pIs2D = true;
  714. }
  715. if (pAxis)
  716. {
  717. *pAxis = AXIS_Y;
  718. }
  719. break;
  720. case ET_ViewportYZ:
  721. if (pIs2D)
  722. {
  723. *pIs2D = true;
  724. }
  725. if (pAxis)
  726. {
  727. *pAxis = AXIS_X;
  728. }
  729. break;
  730. case ET_ViewportMap:
  731. case ET_ViewportZ:
  732. if (pIs2D)
  733. {
  734. *pIs2D = true;
  735. }
  736. break;
  737. }
  738. }
  739. //////////////////////////////////////////////////////////////////////////
  740. bool QtViewport::GetAdvancedSelectModeFlag()
  741. {
  742. return m_bAdvancedSelectMode;
  743. }
  744. //////////////////////////////////////////////////////////////////////////
  745. #if defined(AZ_PLATFORM_WINDOWS)
  746. // Note: Both CreateAnglesYPR and CreateOrientationYPR were copied verbatim from Cry_Camera.h which has been removed.
  747. //
  748. // Description
  749. // <PRE>
  750. // x-YAW
  751. // y-PITCH (negative=looking down / positive=looking up)
  752. // z-ROLL
  753. // </PRE>
  754. // Note: If we are looking along the z-axis, its not possible to specify the x and z-angle
  755. inline Ang3 CreateAnglesYPR(const Matrix33& m)
  756. {
  757. assert(m.IsOrthonormal());
  758. float l = Vec3(m.m01, m.m11, 0.0f).GetLength();
  759. if (l > 0.0001)
  760. {
  761. return Ang3(atan2f(-m.m01 / l, m.m11 / l), atan2f(m.m21, l), atan2f(-m.m20 / l, m.m22 / l));
  762. }
  763. else
  764. {
  765. return Ang3(0, atan2f(m.m21, l), 0);
  766. }
  767. }
  768. // Description
  769. // This function builds a 3x3 orientation matrix using YPR-angles
  770. // Rotation order for the orientation-matrix is Z-X-Y. (Zaxis=YAW / Xaxis=PITCH / Yaxis=ROLL)
  771. //
  772. // <PRE>
  773. // COORDINATE-SYSTEM
  774. //
  775. // z-axis
  776. // ^
  777. // |
  778. // | y-axis
  779. // | /
  780. // | /
  781. // |/
  782. // +---------------> x-axis
  783. // </PRE>
  784. //
  785. // Example:
  786. // Matrix33 orientation=CreateOrientationYPR( Ang3(1,2,3) );
  787. inline Matrix33 CreateOrientationYPR(const Ang3& ypr)
  788. {
  789. f32 sz, cz;
  790. sincos_tpl(ypr.x, &sz, &cz); //Zaxis = YAW
  791. f32 sx, cx;
  792. sincos_tpl(ypr.y, &sx, &cx); //Xaxis = PITCH
  793. f32 sy, cy;
  794. sincos_tpl(ypr.z, &sy, &cy); //Yaxis = ROLL
  795. Matrix33 c;
  796. c.m00 = cy * cz - sy * sz * sx;
  797. c.m01 = -sz * cx;
  798. c.m02 = sy * cz + cy * sz * sx;
  799. c.m10 = cy * sz + sy * sx * cz;
  800. c.m11 = cz * cx;
  801. c.m12 = sy * sz - cy * sx * cz;
  802. c.m20 = -sy * cx;
  803. c.m21 = sx;
  804. c.m22 = cy * cx;
  805. return c;
  806. }
  807. void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam)
  808. {
  809. static C3DConnexionDriver* p3DConnexionDriver = 0;
  810. if (GetType() == ET_ViewportCamera)
  811. {
  812. if (!p3DConnexionDriver)
  813. {
  814. p3DConnexionDriver = (C3DConnexionDriver*)GetIEditor()->GetPluginManager()->GetPluginByGUID("{AD109901-9128-4ffd-8E67-137CB2B1C41B}");
  815. }
  816. if (p3DConnexionDriver)
  817. {
  818. S3DConnexionMessage msg;
  819. if (p3DConnexionDriver->GetInputMessageData((LPARAM)lParam, msg))
  820. {
  821. if (msg.bGotTranslation || msg.bGotRotation)
  822. {
  823. static int all6DOFs[6] = { 0 };
  824. if (msg.bGotTranslation)
  825. {
  826. all6DOFs[0] = msg.raw_translation[0];
  827. all6DOFs[1] = msg.raw_translation[1];
  828. all6DOFs[2] = msg.raw_translation[2];
  829. }
  830. if (msg.bGotRotation)
  831. {
  832. all6DOFs[3] = msg.raw_rotation[0];
  833. all6DOFs[4] = msg.raw_rotation[1];
  834. all6DOFs[5] = msg.raw_rotation[2];
  835. }
  836. Matrix34 viewTM = GetViewTM();
  837. // Scale axis according to CVars
  838. ICVar* sys_scale3DMouseTranslation = gEnv->pConsole->GetCVar("sys_scale3DMouseTranslation");
  839. ICVar* sys_Scale3DMouseYPR = gEnv->pConsole->GetCVar("sys_Scale3DMouseYPR");
  840. float fScaleYPR = sys_Scale3DMouseYPR->GetFVal();
  841. float s = 0.01f * gSettings.cameraMoveSpeed;
  842. Vec3 t = Vec3(s * all6DOFs[0], -s * all6DOFs[1], -s * all6DOFs[2] * 0.5f);
  843. t *= sys_scale3DMouseTranslation->GetFVal();
  844. float as = 0.001f * gSettings.cameraMoveSpeed;
  845. Ang3 ypr = CreateAnglesYPR(Matrix33(viewTM));
  846. ypr.x += -all6DOFs[5] * as * fScaleYPR;
  847. ypr.y = AZStd::clamp(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range
  848. ypr.z = 0; // to have camera always upward
  849. viewTM = Matrix34(CreateOrientationYPR(ypr), viewTM.GetTranslation());
  850. viewTM = viewTM * Matrix34::CreateTranslationMat(t);
  851. SetViewTM(viewTM);
  852. }
  853. }
  854. }
  855. }
  856. }
  857. #endif
  858. //////////////////////////////////////////////////////////////////////////
  859. float QtViewport::GetFOV() const
  860. {
  861. return SandboxEditor::CameraDefaultFovRadians();
  862. }
  863. //////////////////////////////////////////////////////////////////////////
  864. void QtViewport::setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir)
  865. {
  866. m_vp = vp;
  867. m_raySrc = raySrc;
  868. m_rayDir = rayDir;
  869. }
  870. #include <moc_Viewport.cpp>