Viewport.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  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. // AzToolsFramework
  15. #include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
  16. #include <AzToolsFramework/Viewport/ViewportMessages.h>
  17. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  18. // Editor
  19. #include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h"
  20. #include "ViewManager.h"
  21. #include "Include/HitContext.h"
  22. #include "Objects/ObjectManager.h"
  23. #include "Util/3DConnexionDriver.h"
  24. #include "PluginManager.h"
  25. #include "GameEngine.h"
  26. #include "Settings.h"
  27. #include <Editor/EditorViewportSettings.h>
  28. #ifdef LoadCursor
  29. #undef LoadCursor
  30. #endif
  31. //////////////////////////////////////////////////////////////////////
  32. // Viewport drag and drop support
  33. //////////////////////////////////////////////////////////////////////
  34. void QtViewport::BuildDragDropContext(
  35. AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point)
  36. {
  37. context.m_hitLocation = AzToolsFramework::FindClosestPickIntersection(
  38. viewportId, AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point), AzToolsFramework::EditorPickRayLength,
  39. AzToolsFramework::GetDefaultEntityPlacementDistance());
  40. }
  41. void QtViewport::dragEnterEvent(QDragEnterEvent* event)
  42. {
  43. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  44. {
  45. return;
  46. }
  47. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  48. if (m_dropCallback)
  49. {
  50. event->setDropAction(Qt::CopyAction);
  51. event->setAccepted(true);
  52. }
  53. else
  54. {
  55. // new bus-based way of doing it (install a listener!)
  56. using namespace AzQtComponents;
  57. ViewportDragContext context;
  58. BuildDragDropContext(context, GetViewportId(), event->pos());
  59. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context);
  60. }
  61. }
  62. void QtViewport::dragMoveEvent(QDragMoveEvent* event)
  63. {
  64. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  65. {
  66. return;
  67. }
  68. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  69. if (m_dropCallback)
  70. {
  71. event->setDropAction(Qt::CopyAction);
  72. event->setAccepted(true);
  73. }
  74. else
  75. {
  76. // new bus-based way of doing it (install a listener!)
  77. using namespace AzQtComponents;
  78. ViewportDragContext context;
  79. BuildDragDropContext(context, GetViewportId(), event->pos());
  80. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context);
  81. }
  82. }
  83. void QtViewport::dropEvent(QDropEvent* event)
  84. {
  85. using namespace AzQtComponents;
  86. if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
  87. {
  88. return;
  89. }
  90. // first use the legacy pathway, which assumes its always okay as long as any callback is installed
  91. if (m_dropCallback)
  92. {
  93. m_dropCallback(this, event->pos().x(), event->pos().y(), m_dropCallbackCustom);
  94. event->setAccepted(true);
  95. }
  96. else
  97. {
  98. // new bus-based way of doing it (install a listener!)
  99. ViewportDragContext context;
  100. BuildDragDropContext(context, GetViewportId(), event->pos());
  101. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context);
  102. }
  103. }
  104. void QtViewport::dragLeaveEvent(QDragLeaveEvent* event)
  105. {
  106. using namespace AzQtComponents;
  107. DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragLeave, event);
  108. }
  109. //////////////////////////////////////////////////////////////////////////
  110. float CViewport::GetFOV() const
  111. {
  112. return SandboxEditor::CameraDefaultFovRadians();
  113. }
  114. //////////////////////////////////////////////////////////////////////
  115. // Construction/Destruction
  116. //////////////////////////////////////////////////////////////////////
  117. bool QtViewport::m_bDegradateQuality = false;
  118. QtViewport::QtViewport(QWidget* parent)
  119. : QWidget(parent)
  120. , m_renderOverlay(this)
  121. {
  122. m_cViewMenu.addMenu(tr("&View Options"))->addAction(tr("&Fullscreen"));
  123. //connect(action, &QAction::triggered, );
  124. m_selectionTolerance = 0;
  125. m_fGridZoom = 1.0f;
  126. m_nLastUpdateFrame = 0;
  127. m_nLastMouseMoveFrame = 0;
  128. //////////////////////////////////////////////////////////////////////////
  129. // Init standard cursors.
  130. //////////////////////////////////////////////////////////////////////////
  131. m_hCurrCursor = QCursor();
  132. m_hCursor[STD_CURSOR_DEFAULT] = QCursor(Qt::ArrowCursor);
  133. m_hCursor[STD_CURSOR_HIT] = CMFCUtils::LoadCursor(IDC_POINTER_OBJHIT);
  134. m_hCursor[STD_CURSOR_MOVE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_MOVE);
  135. m_hCursor[STD_CURSOR_ROTATE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_ROTATE);
  136. m_hCursor[STD_CURSOR_SCALE] = CMFCUtils::LoadCursor(IDC_POINTER_OBJECT_SCALE);
  137. m_hCursor[STD_CURSOR_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_PLUS);
  138. m_hCursor[STD_CURSOR_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_MINUS);
  139. m_hCursor[STD_CURSOR_SUBOBJ_SEL] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT);
  140. m_hCursor[STD_CURSOR_SUBOBJ_SEL_PLUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_PLUS);
  141. m_hCursor[STD_CURSOR_SUBOBJ_SEL_MINUS] = CMFCUtils::LoadCursor(IDC_POINTER_SO_SELECT_MINUS);
  142. m_activeAxis = AXIS_TERRAIN;
  143. for (int i = 0; i < LAST_COORD_SYSTEM; i++)
  144. {
  145. m_constructionMatrix[i].SetIdentity();
  146. }
  147. m_screenTM.SetIdentity();
  148. m_pMouseOverObject = nullptr;
  149. m_bAdvancedSelectMode = false;
  150. m_constructionPlane.SetPlane(Vec3_OneZ, Vec3_Zero);
  151. m_constructionPlaneAxisX = Vec3_Zero;
  152. m_constructionPlaneAxisY = Vec3_Zero;
  153. GetIEditor()->GetViewManager()->RegisterViewport(this);
  154. m_nCurViewportID = MAX_NUM_VIEWPORTS - 1;
  155. m_dropCallback = nullptr; // Leroy@Conffx
  156. setMouseTracking(true);
  157. setFocusPolicy(Qt::StrongFocus);
  158. // Create drop target to handle Qt drop events.
  159. setAcceptDrops(true);
  160. m_renderOverlay.setVisible(true);
  161. m_renderOverlay.setUpdatesEnabled(false);
  162. m_renderOverlay.setMouseTracking(true);
  163. m_renderOverlay.setObjectName("renderOverlay");
  164. m_renderOverlay.winId(); // Force the render overlay to create a backing native window
  165. m_viewportUi.InitializeViewportUi(this, &m_renderOverlay);
  166. setAcceptDrops(true);
  167. }
  168. //////////////////////////////////////////////////////////////////////////
  169. QtViewport::~QtViewport()
  170. {
  171. GetIEditor()->GetViewManager()->UnregisterViewport(this);
  172. }
  173. //////////////////////////////////////////////////////////////////////////
  174. void QtViewport::ScreenToClient(QPoint& pPoint) const
  175. {
  176. pPoint = mapFromGlobal(pPoint);
  177. }
  178. //////////////////////////////////////////////////////////////////////////
  179. void QtViewport::GetDimensions(int* pWidth, int* pHeight) const
  180. {
  181. if (pWidth)
  182. {
  183. *pWidth = width();
  184. }
  185. if (pHeight)
  186. {
  187. *pHeight = height();
  188. }
  189. }
  190. //////////////////////////////////////////////////////////////////////////
  191. void QtViewport::AddPostRenderer(IPostRenderer* pPostRenderer)
  192. {
  193. stl::push_back_unique(m_postRenderers, pPostRenderer);
  194. }
  195. //////////////////////////////////////////////////////////////////////////
  196. bool QtViewport::RemovePostRenderer(IPostRenderer* pPostRenderer)
  197. {
  198. PostRenderers::iterator itr = m_postRenderers.begin();
  199. PostRenderers::iterator end = m_postRenderers.end();
  200. for (; itr != end; ++itr)
  201. {
  202. if (*itr == pPostRenderer)
  203. {
  204. break;
  205. }
  206. }
  207. if (itr != end)
  208. {
  209. m_postRenderers.erase(itr);
  210. return true;
  211. }
  212. return false;
  213. }
  214. //////////////////////////////////////////////////////////////////////////
  215. void QtViewport::OnMouseWheel([[maybe_unused]] Qt::KeyboardModifiers modifiers, short zDelta, [[maybe_unused]] const QPoint& pt)
  216. {
  217. if (zDelta != 0)
  218. {
  219. float z = GetZoomFactor() + (zDelta / 120.0f) * 0.5f;
  220. SetZoomFactor(z);
  221. GetIEditor()->GetViewManager()->SetZoomFactor(z);
  222. }
  223. }
  224. //////////////////////////////////////////////////////////////////////////
  225. QString QtViewport::GetName() const
  226. {
  227. return windowTitle();
  228. }
  229. //////////////////////////////////////////////////////////////////////////
  230. void QtViewport::SetName(const QString& name)
  231. {
  232. setWindowTitle(name);
  233. }
  234. //////////////////////////////////////////////////////////////////////////
  235. void QtViewport::resizeEvent(QResizeEvent* event)
  236. {
  237. QWidget::resizeEvent(event);
  238. m_renderOverlay.setGeometry(rect());
  239. Update();
  240. }
  241. //////////////////////////////////////////////////////////////////////////
  242. void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event)
  243. {
  244. QPainter painter(this);
  245. // Fill the entire client area
  246. painter.fillRect(rect(), QColor(0xf0, 0xf0, 0xf0));
  247. }
  248. //////////////////////////////////////////////////////////////////////////
  249. void QtViewport::OnActivate()
  250. {
  251. ////////////////////////////////////////////////////////////////////////
  252. // Make this edit window the current one
  253. ////////////////////////////////////////////////////////////////////////
  254. }
  255. //////////////////////////////////////////////////////////////////////////
  256. void QtViewport::OnDeactivate()
  257. {
  258. }
  259. //////////////////////////////////////////////////////////////////////////
  260. void QtViewport::ResetContent()
  261. {
  262. m_pMouseOverObject = nullptr;
  263. }
  264. //////////////////////////////////////////////////////////////////////////
  265. void QtViewport::UpdateContent(int flags)
  266. {
  267. if (flags & eRedrawViewports)
  268. {
  269. update();
  270. }
  271. }
  272. //////////////////////////////////////////////////////////////////////////
  273. void QtViewport::Update()
  274. {
  275. m_viewportUi.Update();
  276. m_bAdvancedSelectMode = false;
  277. if (CheckVirtualKey(Qt::Key_Space) && !CheckVirtualKey(Qt::Key_Shift) && hasFocus())
  278. {
  279. m_bAdvancedSelectMode = true;
  280. }
  281. m_nLastUpdateFrame++;
  282. }
  283. //////////////////////////////////////////////////////////////////////////
  284. QPoint QtViewport::WorldToView(const Vec3& wp) const
  285. {
  286. return QPoint(static_cast<int>(wp.x), static_cast<int>(wp.y));
  287. }
  288. //////////////////////////////////////////////////////////////////////////
  289. Vec3 QtViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) const
  290. {
  291. QPoint p = WorldToView(wp);
  292. Vec3 out;
  293. out.x = static_cast<f32>(p.x());
  294. out.y = static_cast<f32>(p.y());
  295. out.z = wp.z;
  296. return out;
  297. }
  298. //////////////////////////////////////////////////////////////////////////
  299. 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
  300. {
  301. Vec3 wp;
  302. wp.x = static_cast<f32>(vp.x());
  303. wp.y = static_cast<f32>(vp.y());
  304. wp.z = 0;
  305. if (pCollideWithTerrain)
  306. {
  307. *pCollideWithTerrain = true;
  308. }
  309. return wp;
  310. }
  311. //////////////////////////////////////////////////////////////////////////
  312. Vec3 QtViewport::ViewToWorldNormal([[maybe_unused]] const QPoint& vp, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bTestRenderMesh)
  313. {
  314. return Vec3(0, 0, 0);
  315. }
  316. //////////////////////////////////////////////////////////////////////////
  317. void QtViewport::ViewToWorldRay([[maybe_unused]] const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const
  318. {
  319. raySrc(0, 0, 0);
  320. rayDir(0, 0, -1);
  321. }
  322. void QtViewport::mousePressEvent(QMouseEvent* event)
  323. {
  324. switch (event->button())
  325. {
  326. case Qt::LeftButton:
  327. OnLButtonDown(event->modifiers(), event->pos());
  328. break;
  329. case Qt::MiddleButton:
  330. OnMButtonDown(event->modifiers(), event->pos());
  331. break;
  332. case Qt::RightButton:
  333. OnRButtonDown(event->modifiers(), event->pos());
  334. break;
  335. }
  336. }
  337. void QtViewport::mouseReleaseEvent(QMouseEvent* event)
  338. {
  339. switch (event->button())
  340. {
  341. case Qt::LeftButton:
  342. OnLButtonUp(event->modifiers(), event->pos());
  343. break;
  344. case Qt::MiddleButton:
  345. OnMButtonUp(event->modifiers(), event->pos());
  346. break;
  347. case Qt::RightButton:
  348. OnRButtonUp(event->modifiers(), event->pos());
  349. break;
  350. }
  351. // For MFC compatibility, send a spurious move event after a button release.
  352. // CryDesigner depends on this behaviour
  353. mouseMoveEvent(event);
  354. }
  355. void QtViewport::mouseDoubleClickEvent(QMouseEvent* event)
  356. {
  357. switch (event->button())
  358. {
  359. case Qt::LeftButton:
  360. OnLButtonDblClk(event->modifiers(), event->pos());
  361. break;
  362. case Qt::MiddleButton:
  363. OnMButtonDblClk(event->modifiers(), event->pos());
  364. break;
  365. case Qt::RightButton:
  366. OnRButtonDblClk(event->modifiers(), event->pos());
  367. break;
  368. }
  369. }
  370. void QtViewport::mouseMoveEvent(QMouseEvent* event)
  371. {
  372. OnMouseMove(event->modifiers(), event->buttons(), event->pos());
  373. OnSetCursor();
  374. }
  375. void QtViewport::wheelEvent(QWheelEvent* event)
  376. {
  377. OnMouseWheel(event->modifiers(), static_cast<short>(event->angleDelta().y()), event->position().toPoint());
  378. event->accept();
  379. }
  380. void QtViewport::keyPressEvent(QKeyEvent* event)
  381. {
  382. int nativeKey = event->nativeVirtualKey();
  383. #if AZ_TRAIT_OS_PLATFORM_APPLE
  384. // nativeVirtualKey is always zero on macOS, therefore we
  385. // need to manually set the nativeKey based on the Qt key
  386. switch (event->key())
  387. {
  388. case Qt::Key_Control:
  389. nativeKey = VK_CONTROL;
  390. break;
  391. case Qt::Key_Alt:
  392. nativeKey = VK_MENU;
  393. break;
  394. case Qt::Key_QuoteLeft:
  395. nativeKey = VK_OEM_3;
  396. break;
  397. case Qt::Key_BracketLeft:
  398. nativeKey = VK_OEM_4;
  399. break;
  400. case Qt::Key_BracketRight:
  401. nativeKey = VK_OEM_6;
  402. break;
  403. case Qt::Key_Comma:
  404. nativeKey = VK_OEM_COMMA;
  405. break;
  406. case Qt::Key_Period:
  407. nativeKey = VK_OEM_PERIOD;
  408. break;
  409. case Qt::Key_Escape:
  410. nativeKey = VK_ESCAPE;
  411. break;
  412. }
  413. #endif
  414. OnKeyDown(nativeKey, 1, event->nativeModifiers());
  415. }
  416. void QtViewport::keyReleaseEvent(QKeyEvent* event)
  417. {
  418. int nativeKey = event->nativeVirtualKey();
  419. #if AZ_TRAIT_OS_PLATFORM_APPLE
  420. // nativeVirtualKey is always zero on macOS, therefore we
  421. // need to manually set the nativeKey based on the Qt key
  422. switch (event->key())
  423. {
  424. case Qt::Key_Control:
  425. nativeKey = VK_CONTROL;
  426. break;
  427. case Qt::Key_Alt:
  428. nativeKey = VK_MENU;
  429. break;
  430. case Qt::Key_QuoteLeft:
  431. nativeKey = VK_OEM_3;
  432. break;
  433. case Qt::Key_BracketLeft:
  434. nativeKey = VK_OEM_4;
  435. break;
  436. case Qt::Key_BracketRight:
  437. nativeKey = VK_OEM_6;
  438. break;
  439. case Qt::Key_Comma:
  440. nativeKey = VK_OEM_COMMA;
  441. break;
  442. case Qt::Key_Period:
  443. nativeKey = VK_OEM_PERIOD;
  444. break;
  445. case Qt::Key_Escape:
  446. nativeKey = VK_ESCAPE;
  447. break;
  448. }
  449. #endif
  450. OnKeyUp(nativeKey, 1, event->nativeModifiers());
  451. }
  452. //////////////////////////////////////////////////////////////////////////
  453. void QtViewport::OnSetCursor()
  454. {
  455. }
  456. //////////////////////////////////////////////////////////////////////////
  457. void QtViewport::ResetSelectionRegion()
  458. {
  459. AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0));
  460. GetIEditor()->SetSelectedRegion(box);
  461. m_selectedRect = QRect();
  462. }
  463. void QtViewport::SetSelectionRectangle(const QRect& rect)
  464. {
  465. m_selectedRect = rect.normalized();
  466. }
  467. //////////////////////////////////////////////////////////////////////////
  468. void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect)
  469. {
  470. Vec3 org;
  471. AABB box;
  472. box.Reset();
  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.Add(p1);
  482. box.Add(p2);
  483. }
  484. else
  485. {
  486. const QRect rc = correctedRect.normalized();
  487. box.Add(ViewToWorld(rc.topLeft()));
  488. box.Add(ViewToWorld(rc.topRight()));
  489. box.Add(ViewToWorld(rc.bottomLeft()));
  490. box.Add(ViewToWorld(rc.bottomRight()));
  491. }
  492. box.min.z = -10000;
  493. box.max.z = 10000;
  494. GetIEditor()->SetSelectedRegion(box);
  495. // Show marker position in the status bar
  496. float w = box.max.x - box.min.x;
  497. float h = box.max.y - box.min.y;
  498. char szNewStatusText[512];
  499. sprintf_s(szNewStatusText, "X:%g Y:%g Z:%g W:%g H:%g", org.x, org.y, org.z, w, h);
  500. GetIEditor()->SetStatusText(szNewStatusText);
  501. }
  502. //////////////////////////////////////////////////////////////////////////
  503. void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString)
  504. {
  505. setCursor(hCursor);
  506. m_cursorStr = cursorString;
  507. }
  508. //////////////////////////////////////////////////////////////////////////
  509. void QtViewport::SetCurrentCursor(EStdCursor stdCursor, const QString& cursorString)
  510. {
  511. QCursor hCursor = m_hCursor[stdCursor];
  512. setCursor(hCursor);
  513. m_cursorStr = cursorString;
  514. }
  515. void QtViewport::SetSupplementaryCursorStr(const QString& str)
  516. {
  517. m_cursorSupplementaryStr = str;
  518. }
  519. //////////////////////////////////////////////////////////////////////////
  520. void QtViewport::SetCurrentCursor(EStdCursor stdCursor)
  521. {
  522. QCursor hCursor = m_hCursor[stdCursor];
  523. setCursor(hCursor);
  524. }
  525. //////////////////////////////////////////////////////////////////////////
  526. void QtViewport::SetCursorString(const QString& cursorString)
  527. {
  528. m_cursorStr = cursorString;
  529. }
  530. //////////////////////////////////////////////////////////////////////////
  531. void QtViewport::ResetCursor()
  532. {
  533. SetCurrentCursor(STD_CURSOR_DEFAULT, QString());
  534. }
  535. //////////////////////////////////////////////////////////////////////////
  536. void QtViewport::SetConstructionOrigin(const Vec3& worldPos)
  537. {
  538. Matrix34 tm;
  539. tm.SetIdentity();
  540. tm.SetTranslation(worldPos);
  541. SetConstructionMatrix(COORDS_LOCAL, tm);
  542. SetConstructionMatrix(COORDS_PARENT, tm);
  543. SetConstructionMatrix(COORDS_USERDEFINED, tm);
  544. }
  545. //////////////////////////////////////////////////////////////////////////
  546. void QtViewport::SetConstructionMatrix(RefCoordSys coordSys, const Matrix34& xform)
  547. {
  548. m_constructionMatrix[coordSys] = xform;
  549. m_constructionMatrix[coordSys].OrthonormalizeFast(); // Remove scale component from matrix.
  550. if (coordSys == COORDS_LOCAL)
  551. {
  552. m_constructionMatrix[COORDS_VIEW].SetTranslation(xform.GetTranslation());
  553. m_constructionMatrix[COORDS_WORLD].SetTranslation(xform.GetTranslation());
  554. m_constructionMatrix[COORDS_USERDEFINED].SetIdentity();
  555. m_constructionMatrix[COORDS_USERDEFINED].SetTranslation(xform.GetTranslation());
  556. m_constructionMatrix[COORDS_PARENT] = xform;
  557. }
  558. MakeConstructionPlane(GetAxisConstrain());
  559. }
  560. //////////////////////////////////////////////////////////////////////////
  561. const Matrix34& QtViewport::GetConstructionMatrix(RefCoordSys coordSys)
  562. {
  563. if (coordSys == COORDS_VIEW)
  564. {
  565. return m_constructionMatrix[COORDS_WORLD];
  566. }
  567. return m_constructionMatrix[coordSys];
  568. }
  569. //////////////////////////////////////////////////////////////////////////
  570. void QtViewport::AssignConstructionPlane(const Vec3& p1, const Vec3& p2, const Vec3& p3)
  571. {
  572. m_constructionPlane.SetPlane(p1, p2, p3);
  573. m_constructionPlaneAxisX = p3 - p1;
  574. m_constructionPlaneAxisY = p2 - p1;
  575. }
  576. //////////////////////////////////////////////////////////////////////////
  577. HWND QtViewport::renderOverlayHWND() const
  578. {
  579. return reinterpret_cast<HWND>(m_renderOverlay.winId());
  580. }
  581. //////////////////////////////////////////////////////////////////////////
  582. void QtViewport::setRenderOverlayVisible(bool visible)
  583. {
  584. m_renderOverlay.setVisible(visible);
  585. }
  586. bool QtViewport::isRenderOverlayVisible() const
  587. {
  588. return m_renderOverlay.isVisible();
  589. }
  590. //////////////////////////////////////////////////////////////////////////
  591. void QtViewport::MakeConstructionPlane(int axis)
  592. {
  593. QPoint cursorPos;
  594. if (m_mouseCaptured)
  595. {
  596. cursorPos = m_cMouseDownPos;
  597. }
  598. else
  599. {
  600. cursorPos = QCursor::pos();
  601. ScreenToClient(cursorPos);
  602. }
  603. Vec3 raySrc(Vec3_Zero), rayDir(Vec3_OneX);
  604. ViewToWorldRay(cursorPos, raySrc, rayDir);
  605. int coordSys = GetIEditor()->GetReferenceCoordSys();
  606. Vec3 xAxis(Vec3_OneX);
  607. Vec3 yAxis(Vec3_OneY);
  608. Vec3 zAxis(Vec3_OneZ);
  609. xAxis = m_constructionMatrix[coordSys].TransformVector(xAxis);
  610. yAxis = m_constructionMatrix[coordSys].TransformVector(yAxis);
  611. zAxis = m_constructionMatrix[coordSys].TransformVector(zAxis);
  612. Vec3 pos = m_constructionMatrix[coordSys].GetTranslation();
  613. if (axis == AXIS_X)
  614. {
  615. // X direction.
  616. Vec3 n;
  617. float d1 = fabs(rayDir.Dot(yAxis));
  618. float d2 = fabs(rayDir.Dot(zAxis));
  619. if (d1 > d2)
  620. {
  621. n = yAxis;
  622. }
  623. else
  624. {
  625. n = zAxis;
  626. }
  627. if (rayDir.Dot(n) < 0)
  628. {
  629. n = -n; // face construction plane to the ray.
  630. }
  631. //Vec3 n = Vec3(0,0,1);
  632. Vec3 v1 = n.Cross(xAxis);
  633. Vec3 v2 = n.Cross(v1);
  634. AssignConstructionPlane(pos, pos + v2, pos + v1);
  635. }
  636. else if (axis == AXIS_Y)
  637. {
  638. // Y direction.
  639. Vec3 n;
  640. float d1 = fabs(rayDir.Dot(xAxis));
  641. float d2 = fabs(rayDir.Dot(zAxis));
  642. if (d1 > d2)
  643. {
  644. n = xAxis;
  645. }
  646. else
  647. {
  648. n = zAxis;
  649. }
  650. if (rayDir.Dot(n) < 0)
  651. {
  652. n = -n; // face construction plane to the ray.
  653. }
  654. Vec3 v1 = n.Cross(yAxis);
  655. Vec3 v2 = n.Cross(v1);
  656. AssignConstructionPlane(pos, pos + v2, pos + v1);
  657. }
  658. else if (axis == AXIS_Z)
  659. {
  660. // Z direction.
  661. Vec3 n;
  662. float d1 = fabs(rayDir.Dot(xAxis));
  663. float d2 = fabs(rayDir.Dot(yAxis));
  664. if (d1 > d2)
  665. {
  666. n = xAxis;
  667. }
  668. else
  669. {
  670. n = yAxis;
  671. }
  672. if (rayDir.Dot(n) < 0)
  673. {
  674. n = -n; // face construction plane to the ray.
  675. }
  676. Vec3 v1 = n.Cross(zAxis);
  677. Vec3 v2 = n.Cross(v1);
  678. AssignConstructionPlane(pos, pos + v2, pos + v1);
  679. }
  680. else if (axis == AXIS_XY)
  681. {
  682. AssignConstructionPlane(pos, pos + yAxis, pos + xAxis);
  683. }
  684. else if (axis == AXIS_XZ)
  685. {
  686. AssignConstructionPlane(pos, pos + zAxis, pos + xAxis);
  687. }
  688. else if (axis == AXIS_YZ)
  689. {
  690. AssignConstructionPlane(pos, pos + zAxis, pos + yAxis);
  691. }
  692. else
  693. {
  694. AssignConstructionPlane(pos, pos + yAxis, pos + xAxis);
  695. }
  696. }
  697. //////////////////////////////////////////////////////////////////////////
  698. Vec3 QtViewport::MapViewToCP(const QPoint& point, int axis)
  699. {
  700. AZ_PROFILE_FUNCTION(Editor);
  701. if (axis == AXIS_TERRAIN)
  702. {
  703. return SnapToGrid(ViewToWorld(point));
  704. }
  705. MakeConstructionPlane(axis);
  706. Vec3 raySrc(Vec3_Zero), rayDir(Vec3_OneX);
  707. ViewToWorldRay(point, raySrc, rayDir);
  708. Vec3 v;
  709. Ray ray(raySrc, rayDir);
  710. if (!Intersect::Ray_Plane(ray, m_constructionPlane, v))
  711. {
  712. Plane inversePlane = m_constructionPlane;
  713. inversePlane.n = -inversePlane.n;
  714. inversePlane.d = -inversePlane.d;
  715. if (!Intersect::Ray_Plane(ray, inversePlane, v))
  716. {
  717. v = Vec3_Zero;
  718. }
  719. }
  720. // Snap value to grid.
  721. v = SnapToGrid(v);
  722. return v;
  723. }
  724. //////////////////////////////////////////////////////////////////////////
  725. Vec3 QtViewport::GetCPVector(const Vec3& p1, const Vec3& p2, int axis)
  726. {
  727. Vec3 v = p2 - p1;
  728. int coordSys = GetIEditor()->GetReferenceCoordSys();
  729. Vec3 xAxis(Vec3_OneX);
  730. Vec3 yAxis(Vec3_OneY);
  731. Vec3 zAxis(Vec3_OneZ);
  732. // In local coordinate system transform axises by construction matrix.
  733. xAxis = m_constructionMatrix[coordSys].TransformVector(xAxis);
  734. yAxis = m_constructionMatrix[coordSys].TransformVector(yAxis);
  735. zAxis = m_constructionMatrix[coordSys].TransformVector(zAxis);
  736. if (axis == AXIS_X || axis == AXIS_Y || axis == AXIS_Z)
  737. {
  738. // Project vector v on transformed axis x,y or z.
  739. Vec3 axisVector;
  740. if (axis == AXIS_X)
  741. {
  742. axisVector = xAxis;
  743. }
  744. if (axis == AXIS_Y)
  745. {
  746. axisVector = yAxis;
  747. }
  748. if (axis == AXIS_Z)
  749. {
  750. axisVector = zAxis;
  751. }
  752. // Project vector on construction plane into the one of axises.
  753. v = v.Dot(axisVector) * axisVector;
  754. }
  755. else if (axis == AXIS_XY)
  756. {
  757. // Project vector v on transformed plane x/y.
  758. Vec3 planeNormal = xAxis.Cross(yAxis);
  759. Vec3 projV = v.Dot(planeNormal) * planeNormal;
  760. v = v - projV;
  761. }
  762. else if (axis == AXIS_XZ)
  763. {
  764. // Project vector v on transformed plane x/y.
  765. Vec3 planeNormal = xAxis.Cross(zAxis);
  766. Vec3 projV = v.Dot(planeNormal) * planeNormal;
  767. v = v - projV;
  768. }
  769. else if (axis == AXIS_YZ)
  770. {
  771. // Project vector v on transformed plane x/y.
  772. Vec3 planeNormal = yAxis.Cross(zAxis);
  773. Vec3 projV = v.Dot(planeNormal) * planeNormal;
  774. v = v - projV;
  775. }
  776. else if (axis == AXIS_TERRAIN)
  777. {
  778. v.z = 0;
  779. }
  780. return v;
  781. }
  782. //////////////////////////////////////////////////////////////////////////
  783. void QtViewport::SetAxisConstrain(int axis)
  784. {
  785. m_activeAxis = axis;
  786. };
  787. AzToolsFramework::ViewportInteraction::MouseInteraction QtViewport::BuildMouseInteraction(
  788. [[maybe_unused]] Qt::MouseButtons buttons, [[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point)
  789. {
  790. // Implemented by sub-class
  791. return AzToolsFramework::ViewportInteraction::MouseInteraction();
  792. }
  793. //////////////////////////////////////////////////////////////////////////
  794. bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
  795. {
  796. Vec3 raySrc(0, 0, 0), rayDir(1, 0, 0);
  797. ViewToWorldRay(point, hitInfo.raySrc, hitInfo.rayDir);
  798. hitInfo.view = this;
  799. hitInfo.point2d = point;
  800. if (m_bAdvancedSelectMode)
  801. {
  802. hitInfo.bUseSelectionHelpers = true;
  803. }
  804. const int viewportId = GetViewportId();
  805. AzToolsFramework::EntityIdList visibleEntityIds;
  806. AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
  807. viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
  808. visibleEntityIds);
  809. // Look through all visible entities to find the closest one to the specified mouse point
  810. using namespace AzToolsFramework::ViewportInteraction;
  811. AZ::EntityId entityIdUnderCursor;
  812. float closestDistance = std::numeric_limits<float>::max();
  813. MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(),
  814. QGuiApplication::queryKeyboardModifiers(),
  815. point);
  816. for (auto entityId : visibleEntityIds)
  817. {
  818. using AzFramework::ViewportInfo;
  819. // Check if components provide an aabb
  820. if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId });
  821. aabb.IsValid())
  822. {
  823. // Coarse grain check
  824. if (AzToolsFramework::AabbIntersectMouseRay(mouseInteraction, aabb))
  825. {
  826. // If success, pick against specific component
  827. if (AzToolsFramework::PickEntity(
  828. entityId, mouseInteraction,
  829. closestDistance, viewportId))
  830. {
  831. entityIdUnderCursor = entityId;
  832. }
  833. }
  834. }
  835. }
  836. // If we hit a valid Entity, then store the distance in the HitContext
  837. // so that the caller can use this for calculations
  838. if (entityIdUnderCursor.IsValid())
  839. {
  840. hitInfo.dist = closestDistance;
  841. return true;
  842. }
  843. return false;
  844. }
  845. //////////////////////////////////////////////////////////////////////////
  846. void QtViewport::SetZoomFactor(float fZoomFactor)
  847. {
  848. m_fZoomFactor = fZoomFactor;
  849. if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
  850. {
  851. GetViewManager()->SetZoom2D(fZoomFactor);
  852. }
  853. };
  854. //////////////////////////////////////////////////////////////////////////
  855. float QtViewport::GetZoomFactor() const
  856. {
  857. if (gSettings.viewports.bSync2DViews && GetType() != ET_ViewportCamera && GetType() != ET_ViewportModel)
  858. {
  859. m_fZoomFactor = GetViewManager()->GetZoom2D();
  860. }
  861. return m_fZoomFactor;
  862. };
  863. //////////////////////////////////////////////////////////////////////////
  864. Vec3 QtViewport::SnapToGrid(const Vec3& vec)
  865. {
  866. return vec;
  867. }
  868. //////////////////////////////////////////////////////////////////////////
  869. void QtViewport::BeginUndo()
  870. {
  871. DegradateQuality(true);
  872. GetIEditor()->BeginUndo();
  873. }
  874. //////////////////////////////////////////////////////////////////////////
  875. void QtViewport::AcceptUndo(const QString& undoDescription)
  876. {
  877. DegradateQuality(false);
  878. GetIEditor()->AcceptUndo(undoDescription);
  879. GetIEditor()->UpdateViews(eUpdateObjects);
  880. }
  881. //////////////////////////////////////////////////////////////////////////
  882. void QtViewport::CancelUndo()
  883. {
  884. DegradateQuality(false);
  885. GetIEditor()->CancelUndo();
  886. GetIEditor()->UpdateViews(eUpdateObjects);
  887. }
  888. //////////////////////////////////////////////////////////////////////////
  889. void QtViewport::RestoreUndo()
  890. {
  891. GetIEditor()->RestoreUndo();
  892. }
  893. //////////////////////////////////////////////////////////////////////////
  894. bool QtViewport::IsUndoRecording() const
  895. {
  896. return GetIEditor()->IsUndoRecording();
  897. }
  898. //////////////////////////////////////////////////////////////////////////
  899. void QtViewport::DegradateQuality(bool bEnable)
  900. {
  901. m_bDegradateQuality = bEnable;
  902. }
  903. //////////////////////////////////////////////////////////////////////////
  904. QSize QtViewport::GetIdealSize() const
  905. {
  906. return QSize(0, 0);
  907. }
  908. //////////////////////////////////////////////////////////////////////////
  909. bool QtViewport::IsBoundsVisible([[maybe_unused]] const AABB& box) const
  910. {
  911. // Always visible in standard implementation.
  912. return true;
  913. }
  914. //////////////////////////////////////////////////////////////////////////
  915. float QtViewport::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const
  916. {
  917. QPoint p1 = WorldToView(lineP1);
  918. QPoint p2 = WorldToView(lineP2);
  919. return PointToLineDistance2D(
  920. Vec3(static_cast<f32>(p1.x()), static_cast<f32>(p1.y()), 0.0f),
  921. Vec3(static_cast<f32>(p2.x()), static_cast<f32>(p2.y()), 0.0f),
  922. Vec3(static_cast<f32>(point.x()), static_cast<f32>(point.y()), 0.0f));
  923. }
  924. //////////////////////////////////////////////////////////////////////////
  925. void QtViewport::GetPerpendicularAxis(EAxis* pAxis, bool* pIs2D) const
  926. {
  927. EViewportType vpType = GetType();
  928. switch (vpType)
  929. {
  930. case ET_ViewportXY:
  931. if (pIs2D)
  932. {
  933. *pIs2D = true;
  934. }
  935. if (pAxis)
  936. {
  937. *pAxis = AXIS_Z;
  938. }
  939. break;
  940. case ET_ViewportXZ:
  941. if (pIs2D)
  942. {
  943. *pIs2D = true;
  944. }
  945. if (pAxis)
  946. {
  947. *pAxis = AXIS_Y;
  948. }
  949. break;
  950. case ET_ViewportYZ:
  951. if (pIs2D)
  952. {
  953. *pIs2D = true;
  954. }
  955. if (pAxis)
  956. {
  957. *pAxis = AXIS_X;
  958. }
  959. break;
  960. case ET_ViewportMap:
  961. case ET_ViewportZ:
  962. if (pIs2D)
  963. {
  964. *pIs2D = true;
  965. }
  966. break;
  967. }
  968. }
  969. //////////////////////////////////////////////////////////////////////////
  970. bool QtViewport::GetAdvancedSelectModeFlag()
  971. {
  972. return m_bAdvancedSelectMode;
  973. }
  974. //////////////////////////////////////////////////////////////////////////
  975. #if defined(AZ_PLATFORM_WINDOWS)
  976. // Note: Both CreateAnglesYPR and CreateOrientationYPR were copied verbatim from Cry_Camera.h which has been removed.
  977. //
  978. // Description
  979. // <PRE>
  980. // x-YAW
  981. // y-PITCH (negative=looking down / positive=looking up)
  982. // z-ROLL
  983. // </PRE>
  984. // Note: If we are looking along the z-axis, its not possible to specify the x and z-angle
  985. inline Ang3 CreateAnglesYPR(const Matrix33& m)
  986. {
  987. assert(m.IsOrthonormal());
  988. float l = Vec3(m.m01, m.m11, 0.0f).GetLength();
  989. if (l > 0.0001)
  990. {
  991. return Ang3(atan2f(-m.m01 / l, m.m11 / l), atan2f(m.m21, l), atan2f(-m.m20 / l, m.m22 / l));
  992. }
  993. else
  994. {
  995. return Ang3(0, atan2f(m.m21, l), 0);
  996. }
  997. }
  998. // Description
  999. // This function builds a 3x3 orientation matrix using YPR-angles
  1000. // Rotation order for the orientation-matrix is Z-X-Y. (Zaxis=YAW / Xaxis=PITCH / Yaxis=ROLL)
  1001. //
  1002. // <PRE>
  1003. // COORDINATE-SYSTEM
  1004. //
  1005. // z-axis
  1006. // ^
  1007. // |
  1008. // | y-axis
  1009. // | /
  1010. // | /
  1011. // |/
  1012. // +---------------> x-axis
  1013. // </PRE>
  1014. //
  1015. // Example:
  1016. // Matrix33 orientation=CreateOrientationYPR( Ang3(1,2,3) );
  1017. inline Matrix33 CreateOrientationYPR(const Ang3& ypr)
  1018. {
  1019. f32 sz, cz;
  1020. sincos_tpl(ypr.x, &sz, &cz); //Zaxis = YAW
  1021. f32 sx, cx;
  1022. sincos_tpl(ypr.y, &sx, &cx); //Xaxis = PITCH
  1023. f32 sy, cy;
  1024. sincos_tpl(ypr.z, &sy, &cy); //Yaxis = ROLL
  1025. Matrix33 c;
  1026. c.m00 = cy * cz - sy * sz * sx;
  1027. c.m01 = -sz * cx;
  1028. c.m02 = sy * cz + cy * sz * sx;
  1029. c.m10 = cy * sz + sy * sx * cz;
  1030. c.m11 = cz * cx;
  1031. c.m12 = sy * sz - cy * sx * cz;
  1032. c.m20 = -sy * cx;
  1033. c.m21 = sx;
  1034. c.m22 = cy * cx;
  1035. return c;
  1036. }
  1037. void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam)
  1038. {
  1039. static C3DConnexionDriver* p3DConnexionDriver = 0;
  1040. if (GetType() == ET_ViewportCamera)
  1041. {
  1042. if (!p3DConnexionDriver)
  1043. {
  1044. p3DConnexionDriver = (C3DConnexionDriver*)GetIEditor()->GetPluginManager()->GetPluginByGUID("{AD109901-9128-4ffd-8E67-137CB2B1C41B}");
  1045. }
  1046. if (p3DConnexionDriver)
  1047. {
  1048. S3DConnexionMessage msg;
  1049. if (p3DConnexionDriver->GetInputMessageData((LPARAM)lParam, msg))
  1050. {
  1051. if (msg.bGotTranslation || msg.bGotRotation)
  1052. {
  1053. static int all6DOFs[6] = { 0 };
  1054. if (msg.bGotTranslation)
  1055. {
  1056. all6DOFs[0] = msg.raw_translation[0];
  1057. all6DOFs[1] = msg.raw_translation[1];
  1058. all6DOFs[2] = msg.raw_translation[2];
  1059. }
  1060. if (msg.bGotRotation)
  1061. {
  1062. all6DOFs[3] = msg.raw_rotation[0];
  1063. all6DOFs[4] = msg.raw_rotation[1];
  1064. all6DOFs[5] = msg.raw_rotation[2];
  1065. }
  1066. Matrix34 viewTM = GetViewTM();
  1067. // Scale axis according to CVars
  1068. ICVar* sys_scale3DMouseTranslation = gEnv->pConsole->GetCVar("sys_scale3DMouseTranslation");
  1069. ICVar* sys_Scale3DMouseYPR = gEnv->pConsole->GetCVar("sys_Scale3DMouseYPR");
  1070. float fScaleYPR = sys_Scale3DMouseYPR->GetFVal();
  1071. float s = 0.01f * gSettings.cameraMoveSpeed;
  1072. Vec3 t = Vec3(s * all6DOFs[0], -s * all6DOFs[1], -s * all6DOFs[2] * 0.5f);
  1073. t *= sys_scale3DMouseTranslation->GetFVal();
  1074. float as = 0.001f * gSettings.cameraMoveSpeed;
  1075. Ang3 ypr = CreateAnglesYPR(Matrix33(viewTM));
  1076. ypr.x += -all6DOFs[5] * as * fScaleYPR;
  1077. ypr.y = AZStd::clamp(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range
  1078. ypr.z = 0; // to have camera always upward
  1079. viewTM = Matrix34(CreateOrientationYPR(ypr), viewTM.GetTranslation());
  1080. viewTM = viewTM * Matrix34::CreateTranslationMat(t);
  1081. SetViewTM(viewTM);
  1082. }
  1083. }
  1084. }
  1085. }
  1086. }
  1087. #endif
  1088. //////////////////////////////////////////////////////////////////////////
  1089. float QtViewport::GetFOV() const
  1090. {
  1091. return SandboxEditor::CameraDefaultFovRadians();
  1092. }
  1093. //////////////////////////////////////////////////////////////////////////
  1094. void QtViewport::setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir)
  1095. {
  1096. m_vp = vp;
  1097. m_raySrc = raySrc;
  1098. m_rayDir = rayDir;
  1099. }
  1100. #include <moc_Viewport.cpp>