ViewPane.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  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. // Description : implementation file
  9. #include "EditorDefs.h"
  10. #include "CustomAspectRatioDlg.h"
  11. #include "CustomResolutionDlg.h"
  12. #include "ViewPane.h"
  13. // Qt
  14. #include <QDebug>
  15. #include <QLabel>
  16. #include <QLayout>
  17. #include <QMouseEvent>
  18. #include <QScrollArea>
  19. #include <QToolBar>
  20. #include <AzCore/Interface/Interface.h>
  21. #include <AzCore/RTTI/BehaviorContext.h>
  22. #include <AzFramework/StringFunc/StringFunc.h>
  23. #include <AzToolsFramework/ActionManager/Action/ActionManagerInterface.h>
  24. #include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
  25. #include <AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInterface.h>
  26. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorActionUpdaterIdentifiers.h>
  27. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorContextIdentifiers.h>
  28. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorMenuIdentifiers.h>
  29. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorToolBarIdentifiers.h>
  30. #include <AzToolsFramework/Editor/ActionManagerUtils.h>
  31. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorContextIdentifiers.h>
  32. #include <AzQtComponents/Components/Style.h>
  33. #include <AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h>
  34. // Editor
  35. #include "ViewManager.h"
  36. #include "Settings.h"
  37. #include "LayoutWnd.h"
  38. #include "Viewport.h"
  39. #include "LayoutConfigDialog.h"
  40. #include "MainWindow.h"
  41. #include "QtViewPaneManager.h"
  42. #include "EditorViewportWidget.h"
  43. #include <Editor/EditorViewportSettings.h>
  44. static const std::pair<int, int> ViewportRatios[] = { { 16, 9 }, { 16, 10 }, { 4, 3 }, { 5, 4 } };
  45. static const size_t ViewportRatiosCount = sizeof(ViewportRatios) / sizeof(ViewportRatios[0]);
  46. static const std::pair<int, int> ViewportResolutions[] =
  47. { { 1280, 720 }, { 1920, 1080 }, { 2560, 1440 }, { 2048, 858 }, { 1998, 1080 }, { 3480, 2160 } };
  48. static const size_t ViewportResolutionsCount = sizeof(ViewportResolutions) / sizeof(ViewportResolutions[0]);
  49. static constexpr int SortKeySpacing = 100;
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CLayoutViewPane
  52. //////////////////////////////////////////////////////////////////////////
  53. CLayoutViewPane::CLayoutViewPane(QWidget* parent)
  54. : AzQtComponents::ToolBarArea(parent)
  55. {
  56. m_viewport = nullptr;
  57. m_active = false;
  58. m_nBorder = VIEW_BORDER;
  59. m_bFullscreen = false;
  60. // Set up an optional scrollable area for our viewport. We'll use this for times that we want a fixed-size
  61. // viewport independent of main window size.
  62. m_viewportScrollArea = new QScrollArea(this);
  63. m_viewportScrollArea->setContentsMargins(QMargins());
  64. m_viewportScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  65. m_actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
  66. m_menuManagerInterface = AZ::Interface<AzToolsFramework::MenuManagerInterface>::Get();
  67. m_toolBarManagerInterface = AZ::Interface<AzToolsFramework::ToolBarManagerInterface>::Get();
  68. if (m_actionManagerInterface && m_menuManagerInterface && m_toolBarManagerInterface)
  69. {
  70. AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusConnect();
  71. }
  72. // If this is being instantiated after the Action Manager was alreadi initialized, add the toolbar.
  73. // Else it will be added in OnToolBarRegistrationHook.
  74. if (QToolBar* toolBar = m_toolBarManagerInterface->GenerateToolBar(EditorIdentifiers::ViewportTopToolBarIdentifier))
  75. {
  76. addToolBar(Qt::TopToolBarArea, toolBar);
  77. }
  78. m_id = -1;
  79. }
  80. CLayoutViewPane::~CLayoutViewPane()
  81. {
  82. AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusDisconnect();
  83. if (m_viewportScrollArea)
  84. {
  85. // We only ever add m_viewport into our scroll area, which we manage separately,
  86. // so make sure to take it back before deleting m_scrollArea. Otherwise it will
  87. // try and get deleted as a part of deleting m_scrollArea.
  88. m_viewportScrollArea->takeWidget();
  89. delete m_viewportScrollArea;
  90. }
  91. OnDestroy();
  92. }
  93. void CLayoutViewPane::OnMenuRegistrationHook()
  94. {
  95. {
  96. AzToolsFramework::MenuProperties menuProperties;
  97. menuProperties.m_name = "Viewport Camera Settings";
  98. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportCameraMenuIdentifier, menuProperties);
  99. }
  100. {
  101. AzToolsFramework::MenuProperties menuProperties;
  102. menuProperties.m_name = "Viewport Debug Info";
  103. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportDebugInfoMenuIdentifier, menuProperties);
  104. }
  105. {
  106. AzToolsFramework::MenuProperties menuProperties;
  107. menuProperties.m_name = "Viewport Helpers";
  108. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, menuProperties);
  109. }
  110. {
  111. AzToolsFramework::MenuProperties menuProperties;
  112. menuProperties.m_name = "Viewport Size";
  113. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportSizeMenuIdentifier, menuProperties);
  114. }
  115. {
  116. AzToolsFramework::MenuProperties menuProperties;
  117. menuProperties.m_name = "Ratio";
  118. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportSizeRatioMenuIdentifier, menuProperties);
  119. }
  120. {
  121. AzToolsFramework::MenuProperties menuProperties;
  122. menuProperties.m_name = "Resolution";
  123. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportSizeResolutionMenuIdentifier, menuProperties);
  124. }
  125. {
  126. AzToolsFramework::MenuProperties menuProperties;
  127. menuProperties.m_name = "Viewport Options";
  128. m_menuManagerInterface->RegisterMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, menuProperties);
  129. }
  130. }
  131. void CLayoutViewPane::OnToolBarRegistrationHook()
  132. {
  133. // Register top viewport toolbar.
  134. AzToolsFramework::ToolBarProperties toolBarProperties;
  135. toolBarProperties.m_name = "Viewport ToolBar";
  136. m_toolBarManagerInterface->RegisterToolBar(EditorIdentifiers::ViewportTopToolBarIdentifier, toolBarProperties);
  137. // Add toolbar to top of viewport.
  138. QToolBar* toolBar = m_toolBarManagerInterface->GenerateToolBar(EditorIdentifiers::ViewportTopToolBarIdentifier);
  139. addToolBar(Qt::TopToolBarArea, toolBar);
  140. }
  141. void CLayoutViewPane::OnActionRegistrationHook()
  142. {
  143. // Dummy Action with Resize Icon
  144. {
  145. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.resizeIcon";
  146. AzToolsFramework::ActionProperties actionProperties;
  147. actionProperties.m_name = "Viewport Size";
  148. actionProperties.m_iconPath = ":/Menu/resolution.svg";
  149. m_actionManagerInterface->RegisterAction(
  150. EditorIdentifiers::MainWindowActionContextIdentifier,
  151. actionIdentifier,
  152. actionProperties,
  153. []
  154. {
  155. }
  156. );
  157. }
  158. // Dummy Action with Menu Icon
  159. {
  160. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.menuIcon";
  161. AzToolsFramework::ActionProperties actionProperties;
  162. actionProperties.m_name = "Options";
  163. actionProperties.m_iconPath = ":/Menu/menu.svg";
  164. m_actionManagerInterface->RegisterAction(
  165. EditorIdentifiers::MainWindowActionContextIdentifier,
  166. actionIdentifier,
  167. actionProperties,
  168. []
  169. {
  170. }
  171. );
  172. }
  173. // Viewport Debug Information
  174. {
  175. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.info.toggle";
  176. AzToolsFramework::ActionProperties actionProperties;
  177. actionProperties.m_name = "Toggle Between States";
  178. actionProperties.m_category = "Viewport Debug Information";
  179. actionProperties.m_iconPath = ":/Menu/debug.svg";
  180. m_actionManagerInterface->RegisterCheckableAction(
  181. EditorIdentifiers::MainWindowActionContextIdentifier,
  182. actionIdentifier,
  183. actionProperties,
  184. [viewportTitleDlg = m_viewportTitleDlg]
  185. {
  186. viewportTitleDlg->OnToggleDisplayInfo();
  187. },
  188. []() -> bool
  189. {
  190. AZ::AtomBridge::ViewportInfoDisplayState currentState = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  191. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
  192. currentState, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
  193. return currentState != AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  194. }
  195. );
  196. m_actionManagerInterface->AddActionToUpdater(EditorIdentifiers::ViewportDisplayInfoStateChangedUpdaterIdentifier, actionIdentifier);
  197. }
  198. {
  199. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.info.normal";
  200. AzToolsFramework::ActionProperties actionProperties;
  201. actionProperties.m_name = "Normal";
  202. actionProperties.m_category = "Viewport Debug Information";
  203. m_actionManagerInterface->RegisterCheckableAction(
  204. EditorIdentifiers::MainWindowActionContextIdentifier,
  205. actionIdentifier,
  206. actionProperties,
  207. [viewportTitleDlg = m_viewportTitleDlg]
  208. {
  209. viewportTitleDlg->SetNormalViewportInfo();
  210. },
  211. []() -> bool
  212. {
  213. AZ::AtomBridge::ViewportInfoDisplayState currentState = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  214. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
  215. currentState, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
  216. return currentState == AZ::AtomBridge::ViewportInfoDisplayState::NormalInfo;
  217. }
  218. );
  219. m_actionManagerInterface->AddActionToUpdater(
  220. EditorIdentifiers::ViewportDisplayInfoStateChangedUpdaterIdentifier, actionIdentifier);
  221. }
  222. {
  223. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.info.full";
  224. AzToolsFramework::ActionProperties actionProperties;
  225. actionProperties.m_name = "Full";
  226. actionProperties.m_category = "Viewport Debug Information";
  227. m_actionManagerInterface->RegisterCheckableAction(
  228. EditorIdentifiers::MainWindowActionContextIdentifier,
  229. actionIdentifier,
  230. actionProperties,
  231. [viewportTitleDlg = m_viewportTitleDlg]
  232. {
  233. viewportTitleDlg->SetFullViewportInfo();
  234. },
  235. []() -> bool
  236. {
  237. AZ::AtomBridge::ViewportInfoDisplayState currentState = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  238. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
  239. currentState, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
  240. return currentState == AZ::AtomBridge::ViewportInfoDisplayState::FullInfo;
  241. }
  242. );
  243. m_actionManagerInterface->AddActionToUpdater(
  244. EditorIdentifiers::ViewportDisplayInfoStateChangedUpdaterIdentifier, actionIdentifier);
  245. }
  246. {
  247. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.info.compact";
  248. AzToolsFramework::ActionProperties actionProperties;
  249. actionProperties.m_name = "Compact";
  250. actionProperties.m_category = "Viewport Debug Information";
  251. m_actionManagerInterface->RegisterCheckableAction(
  252. EditorIdentifiers::MainWindowActionContextIdentifier,
  253. actionIdentifier,
  254. actionProperties,
  255. [viewportTitleDlg = m_viewportTitleDlg]
  256. {
  257. viewportTitleDlg->SetCompactViewportInfo();
  258. },
  259. []() -> bool
  260. {
  261. AZ::AtomBridge::ViewportInfoDisplayState currentState = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  262. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
  263. currentState, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
  264. return currentState == AZ::AtomBridge::ViewportInfoDisplayState::CompactInfo;
  265. }
  266. );
  267. m_actionManagerInterface->AddActionToUpdater(
  268. EditorIdentifiers::ViewportDisplayInfoStateChangedUpdaterIdentifier, actionIdentifier);
  269. }
  270. {
  271. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.info.none";
  272. AzToolsFramework::ActionProperties actionProperties;
  273. actionProperties.m_name = "None";
  274. actionProperties.m_category = "Viewport Debug Information";
  275. m_actionManagerInterface->RegisterCheckableAction(
  276. EditorIdentifiers::MainWindowActionContextIdentifier,
  277. actionIdentifier,
  278. actionProperties,
  279. [viewportTitleDlg = m_viewportTitleDlg]
  280. {
  281. viewportTitleDlg->SetNoViewportInfo();
  282. },
  283. []() -> bool
  284. {
  285. AZ::AtomBridge::ViewportInfoDisplayState currentState = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  286. AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
  287. currentState, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
  288. return currentState == AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
  289. });
  290. m_actionManagerInterface->AddActionToUpdater(
  291. EditorIdentifiers::ViewportDisplayInfoStateChangedUpdaterIdentifier, actionIdentifier);
  292. }
  293. // Viewport Size
  294. for (size_t i = 0; i < ViewportRatiosCount; ++i)
  295. {
  296. int width = ViewportRatios[i].first;
  297. int height = ViewportRatios[i].second;
  298. AZStd::string actionIdentifier = AZStd::string::format("o3de.action.viewport.size.ratio[%i:%i]", width, height);
  299. AzToolsFramework::ActionProperties actionProperties;
  300. actionProperties.m_name = AZStd::string::format("%i:%i", width, height);
  301. actionProperties.m_category = "Viewport Size Ratio";
  302. m_actionManagerInterface->RegisterAction(
  303. EditorIdentifiers::MainWindowActionContextIdentifier,
  304. actionIdentifier,
  305. actionProperties,
  306. [this, w = width, h = height]
  307. {
  308. SetAspectRatio(w, h);
  309. }
  310. );
  311. }
  312. {
  313. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.size.ratio.custom";
  314. AzToolsFramework::ActionProperties actionProperties;
  315. actionProperties.m_name = "Custom...";
  316. actionProperties.m_category = "Viewport Size Ratio";
  317. m_actionManagerInterface->RegisterAction(
  318. EditorIdentifiers::MainWindowActionContextIdentifier,
  319. actionIdentifier,
  320. actionProperties,
  321. [&]
  322. {
  323. const QRect viewportRect = GetViewport()->rect();
  324. const unsigned int width = viewportRect.width();
  325. const unsigned int height = viewportRect.height();
  326. int whGCD = gcd(width, height);
  327. CCustomAspectRatioDlg aspectRatioInputDialog(width / whGCD, height / whGCD, this);
  328. if (aspectRatioInputDialog.exec() == QDialog::Accepted)
  329. {
  330. const unsigned int aspectX = aspectRatioInputDialog.GetX();
  331. const unsigned int aspectY = aspectRatioInputDialog.GetY();
  332. SetAspectRatio(aspectX, aspectY);
  333. }
  334. }
  335. );
  336. }
  337. for (size_t i = 0; i < ViewportResolutionsCount; ++i)
  338. {
  339. int width = ViewportResolutions[i].first;
  340. int height = ViewportResolutions[i].second;
  341. AZStd::string actionIdentifier = AZStd::string::format("o3de.action.viewport.size.resolution[%i:%i]", width, height);
  342. AzToolsFramework::ActionProperties actionProperties;
  343. actionProperties.m_name = AZStd::string::format("%i:%i", width, height);
  344. actionProperties.m_category = "Viewport Size Resolution";
  345. m_actionManagerInterface->RegisterAction(
  346. EditorIdentifiers::MainWindowActionContextIdentifier,
  347. actionIdentifier,
  348. actionProperties,
  349. [&, w = width, h = height]
  350. {
  351. ResizeViewport(w, h);
  352. }
  353. );
  354. }
  355. {
  356. constexpr AZStd::string_view actionIdentifier = "o3de.action.viewport.size.resolution.custom";
  357. AzToolsFramework::ActionProperties actionProperties;
  358. actionProperties.m_name = "Custom...";
  359. actionProperties.m_category = "Viewport Size Resolution";
  360. m_actionManagerInterface->RegisterAction(
  361. EditorIdentifiers::MainWindowActionContextIdentifier,
  362. actionIdentifier,
  363. actionProperties,
  364. [this]
  365. {
  366. const QRect rectViewport = GetViewport()->rect();
  367. CCustomResolutionDlg resDlg(rectViewport.width(), rectViewport.height(), parentWidget());
  368. if (resDlg.exec() == QDialog::Accepted)
  369. {
  370. ResizeViewport(resDlg.GetWidth(), resDlg.GetHeight());
  371. }
  372. }
  373. );
  374. }
  375. }
  376. void CLayoutViewPane::OnMenuBindingHook()
  377. {
  378. // Camera
  379. {
  380. m_menuManagerInterface->AddWidgetToMenu(EditorIdentifiers::ViewportCameraMenuIdentifier, "o3de.widgetAction.viewport.fieldOfView", 100);
  381. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportCameraMenuIdentifier, "o3de.action.view.goToPosition", 200);
  382. m_menuManagerInterface->AddSeparatorToMenu(EditorIdentifiers::ViewportCameraMenuIdentifier, 300);
  383. m_menuManagerInterface->AddWidgetToMenu(
  384. EditorIdentifiers::ViewportCameraMenuIdentifier, "o3de.widgetAction.viewport.cameraSpeedScale", 400);
  385. }
  386. // Debug Info
  387. {
  388. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportDebugInfoMenuIdentifier, "o3de.action.viewport.info.normal", 100);
  389. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportDebugInfoMenuIdentifier, "o3de.action.viewport.info.full", 200);
  390. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportDebugInfoMenuIdentifier, "o3de.action.viewport.info.compact", 300);
  391. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportDebugInfoMenuIdentifier, "o3de.action.viewport.info.none", 400);
  392. }
  393. // Helpers
  394. {
  395. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, "o3de.action.view.toggleIcons", 100);
  396. m_menuManagerInterface->AddSeparatorToMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, 200);
  397. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, "o3de.action.view.showHelpers", 300);
  398. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, "o3de.action.view.showSelectedEntityHelpers", 400);
  399. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportHelpersMenuIdentifier, "o3de.action.view.hideHelpers", 500);
  400. }
  401. // Size
  402. {
  403. m_menuManagerInterface->AddSubMenuToMenu(EditorIdentifiers::ViewportSizeMenuIdentifier, EditorIdentifiers::ViewportSizeRatioMenuIdentifier, 100);
  404. {
  405. for (size_t i = 0; i < ViewportRatiosCount; ++i)
  406. {
  407. int width = ViewportRatios[i].first;
  408. int height = ViewportRatios[i].second;
  409. AZStd::string actionIdentifier = AZStd::string::format("o3de.action.viewport.size.ratio[%i:%i]", width, height);
  410. m_menuManagerInterface->AddActionToMenu(
  411. EditorIdentifiers::ViewportSizeRatioMenuIdentifier, actionIdentifier, SortKeySpacing * (aznumeric_cast<int>(i) + 1));
  412. }
  413. m_menuManagerInterface->AddSeparatorToMenu(
  414. EditorIdentifiers::ViewportSizeRatioMenuIdentifier, SortKeySpacing * (aznumeric_cast<int>(ViewportRatiosCount) + 1));
  415. m_menuManagerInterface->AddActionToMenu(
  416. EditorIdentifiers::ViewportSizeRatioMenuIdentifier,
  417. "o3de.action.viewport.size.ratio.custom",
  418. SortKeySpacing * (aznumeric_cast<int>(ViewportRatiosCount) + 2));
  419. }
  420. m_menuManagerInterface->AddSubMenuToMenu(EditorIdentifiers::ViewportSizeMenuIdentifier, EditorIdentifiers::ViewportSizeResolutionMenuIdentifier, 200);
  421. {
  422. for (size_t i = 0; i < ViewportResolutionsCount; ++i)
  423. {
  424. int width = ViewportResolutions[i].first;
  425. int height = ViewportResolutions[i].second;
  426. AZStd::string actionIdentifier = AZStd::string::format("o3de.action.viewport.size.resolution[%i:%i]", width, height);
  427. m_menuManagerInterface->AddActionToMenu(
  428. EditorIdentifiers::ViewportSizeResolutionMenuIdentifier, actionIdentifier, SortKeySpacing * (aznumeric_cast<int>(i) + 1));
  429. }
  430. m_menuManagerInterface->AddSeparatorToMenu(
  431. EditorIdentifiers::ViewportSizeResolutionMenuIdentifier, SortKeySpacing * (aznumeric_cast<int>(ViewportResolutionsCount) + 1));
  432. m_menuManagerInterface->AddActionToMenu(
  433. EditorIdentifiers::ViewportSizeResolutionMenuIdentifier,
  434. "o3de.action.viewport.size.resolution.custom",
  435. SortKeySpacing * (aznumeric_cast<int>(ViewportResolutionsCount) + 2));
  436. }
  437. }
  438. // Options
  439. {
  440. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, "o3de.action.edit.snap.toggleGridSnapping", 300);
  441. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, "o3de.action.edit.snap.toggleShowingGrid", 400);
  442. m_menuManagerInterface->AddWidgetToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, "o3de.widgetAction.viewport.gridSnappingSize", 500);
  443. m_menuManagerInterface->AddSeparatorToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, 600);
  444. m_menuManagerInterface->AddActionToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, "o3de.action.edit.snap.toggleAngleSnapping", 700);
  445. m_menuManagerInterface->AddWidgetToMenu(EditorIdentifiers::ViewportOptionsMenuIdentifier, "o3de.widgetAction.viewport.angleSnappingSize", 800);
  446. }
  447. }
  448. void CLayoutViewPane::OnToolBarBindingHook()
  449. {
  450. m_toolBarManagerInterface->AddWidgetToToolBar(EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.widgetAction.expander", 300);
  451. m_toolBarManagerInterface->AddWidgetToToolBar(
  452. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.widgetAction.prefab.editVisualMode", 400);
  453. m_toolBarManagerInterface->AddActionWithSubMenuToToolBar(
  454. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.action.view.goToPosition", EditorIdentifiers::ViewportCameraMenuIdentifier, 500);
  455. m_toolBarManagerInterface->AddActionWithSubMenuToToolBar(
  456. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.action.viewport.info.toggle", EditorIdentifiers::ViewportDebugInfoMenuIdentifier, 600);
  457. m_toolBarManagerInterface->AddActionWithSubMenuToToolBar(
  458. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.action.view.showHelpers", EditorIdentifiers::ViewportHelpersMenuIdentifier, 700);
  459. m_toolBarManagerInterface->AddActionWithSubMenuToToolBar(
  460. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.action.viewport.resizeIcon", EditorIdentifiers::ViewportSizeMenuIdentifier, 800);
  461. m_toolBarManagerInterface->AddActionWithSubMenuToToolBar(
  462. EditorIdentifiers::ViewportTopToolBarIdentifier, "o3de.action.viewport.menuIcon", EditorIdentifiers::ViewportOptionsMenuIdentifier, 900);
  463. }
  464. //////////////////////////////////////////////////////////////////////////
  465. void CLayoutViewPane::SetViewClass(const QString& sClass)
  466. {
  467. if (m_viewport && m_viewPaneClass == sClass)
  468. {
  469. return;
  470. }
  471. m_viewPaneClass = sClass;
  472. ReleaseViewport();
  473. QWidget* newPane = QtViewPaneManager::instance()->CreateWidget(sClass);
  474. if (newPane)
  475. {
  476. newPane->setProperty("IsViewportWidget", true);
  477. AttachViewport(newPane);
  478. }
  479. }
  480. //////////////////////////////////////////////////////////////////////////
  481. QString CLayoutViewPane::GetViewClass() const
  482. {
  483. return m_viewPaneClass;
  484. }
  485. //////////////////////////////////////////////////////////////////////////
  486. void CLayoutViewPane::OnDestroy()
  487. {
  488. ReleaseViewport();
  489. }
  490. //////////////////////////////////////////////////////////////////////////
  491. void CLayoutViewPane::SwapViewports(CLayoutViewPane* pView)
  492. {
  493. QWidget* pViewport = pView->GetViewport();
  494. QWidget* pViewportOld = m_viewport;
  495. std::swap(m_viewPaneClass, pView->m_viewPaneClass);
  496. AttachViewport(pViewport);
  497. pView->AttachViewport(pViewportOld);
  498. }
  499. void CLayoutViewPane::SetViewportExpansionPolicy(ViewportExpansionPolicy policy)
  500. {
  501. m_viewportPolicy = policy;
  502. switch (policy)
  503. {
  504. // If the requested policy is "FixedSize", wrap our viewport area in a scrollable
  505. // region so that we can always make the viewport a guaranteed fixed size regardless of the
  506. // main window size. The scrollable area will auto-resize with the main window, but the
  507. // viewport won't.
  508. case ViewportExpansionPolicy::FixedSize:
  509. {
  510. QWidget* scrollViewport = m_viewportScrollArea->viewport();
  511. m_viewportScrollArea->setWidget(m_viewport);
  512. m_viewport->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  513. // For some reason, the QScrollArea is adding a margin all around our viewable area,
  514. // so we'll shrink our viewport by an appropriate offset (twice the margin thickness)
  515. // so that it continues to fit without requiring scroll bars after switching size policies.
  516. m_viewport->resize(m_viewport->width() - (scrollViewport->x() * 2), m_viewport->height() - (scrollViewport->y() * 2));
  517. SetMainWidget(m_viewportScrollArea);
  518. update();
  519. }
  520. break;
  521. // If the requested policy is "AutoExpand", just put the viewport area directly in the ViewPane.
  522. // It will auto-resize with the main window, but requests to change the viewport size might not
  523. // result in the exact size being requested, depending on main window size and layout.
  524. case ViewportExpansionPolicy::AutoExpand:
  525. {
  526. m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  527. SetMainWidget(m_viewport);
  528. update();
  529. }
  530. break;
  531. }
  532. }
  533. //////////////////////////////////////////////////////////////////////////
  534. void CLayoutViewPane::AttachViewport(QWidget* pViewport)
  535. {
  536. if (pViewport == m_viewport)
  537. {
  538. return;
  539. }
  540. DisconnectRenderViewportInteractionRequestBus();
  541. m_viewport = pViewport;
  542. if (pViewport)
  543. {
  544. SetViewportExpansionPolicy(ViewportExpansionPolicy::AutoExpand);
  545. if (QtViewport* vp = qobject_cast<QtViewport*>(pViewport))
  546. {
  547. vp->SetViewportId(GetId());
  548. vp->SetViewPane(this);
  549. if (EditorViewportWidget* renderViewport = viewport_cast<EditorViewportWidget*>(vp))
  550. {
  551. renderViewport->ConnectViewportInteractionRequestBus();
  552. }
  553. }
  554. m_viewport->setVisible(true);
  555. setWindowTitle(m_viewPaneClass);
  556. if (QtViewport* vp = qobject_cast<QtViewport*>(pViewport))
  557. {
  558. OnFOVChanged(vp->GetFOV());
  559. }
  560. else
  561. {
  562. OnFOVChanged(SandboxEditor::CameraDefaultFovRadians());
  563. }
  564. }
  565. }
  566. //////////////////////////////////////////////////////////////////////////
  567. void CLayoutViewPane::DetachViewport()
  568. {
  569. DisconnectRenderViewportInteractionRequestBus();
  570. OnFOVChanged(SandboxEditor::CameraDefaultFovRadians());
  571. m_viewport = nullptr;
  572. }
  573. //////////////////////////////////////////////////////////////////////////
  574. void CLayoutViewPane::ReleaseViewport()
  575. {
  576. if (m_viewport)
  577. {
  578. DisconnectRenderViewportInteractionRequestBus();
  579. m_viewport->deleteLater();
  580. m_viewport = nullptr;
  581. }
  582. }
  583. void CLayoutViewPane::DisconnectRenderViewportInteractionRequestBus()
  584. {
  585. if (QtViewport* vp = qobject_cast<QtViewport*>(m_viewport))
  586. {
  587. if (EditorViewportWidget* renderViewport = viewport_cast<EditorViewportWidget*>(vp))
  588. {
  589. renderViewport->DisconnectViewportInteractionRequestBus();
  590. }
  591. }
  592. }
  593. //////////////////////////////////////////////////////////////////////////
  594. void CLayoutViewPane::ResizeViewport(int width, int height)
  595. {
  596. if (!m_viewport)
  597. {
  598. return;
  599. }
  600. // Get our MainWidget, which will either be the viewport or a scrollable area around the
  601. // viewport, depending on which expansion policy we've chosen.
  602. QWidget* mainWidget = GetMainWidget();
  603. if (!mainWidget)
  604. {
  605. mainWidget = m_viewport;
  606. }
  607. // If our main widget is a scroll area, specifically get the size of the viewable area within the scroll area.
  608. // This way, even if we currently have scroll bars visible, we'll try to resize our main window and scroll area
  609. // to make the entire viewport visible.
  610. QSize mainWidgetSize = mainWidget->size();
  611. if (QScrollArea* scrollArea = qobject_cast<QScrollArea*>(mainWidget))
  612. {
  613. mainWidgetSize = scrollArea->viewport()->size();
  614. }
  615. // Make sure our requestedSize stays within "legal" bounds.
  616. const QSize requestedSize = QSize(AZ::GetClamp(width, MIN_VIEWPORT_RES, MAX_VIEWPORT_RES),
  617. AZ::GetClamp(height, MIN_VIEWPORT_RES, MAX_VIEWPORT_RES));
  618. // The delta between our current and requested size is going to be used to try and resize the main window
  619. // (either growing or shrinking) by the exact same amount so that the new viewport size is still completely
  620. // visible without needing to adjust any other widget sizes.
  621. // Note that we're specifically taking the delta from the main widget, not the viewport.
  622. // In the "AutoResize" case, this will still directly take the delta from our viewport, but in the
  623. // "FixedSize" case we need to take the delta from the scroll area's viewable area size, since that's actually
  624. // the one we need to grow/shrink proportional to.
  625. const QSize deltaSize = requestedSize - mainWidgetSize;
  626. // Do nothing if the new size is the same as the old size.
  627. if (deltaSize == QSize(0, 0))
  628. {
  629. return;
  630. }
  631. MainWindow* mainWindow = MainWindow::instance();
  632. // We need to adjust the main window size to make it larger/smaller as appropriate
  633. // to fit the newly-resized viewport, so start by making sure it isn't maximized.
  634. if (mainWindow->isMaximized())
  635. {
  636. mainWindow->showNormal();
  637. }
  638. // Resize our main window by the amount that we want our viewport to change.
  639. // This is intended to grow our viewport by the same amount. However, this logic is a
  640. // little flawed and should get revisited at some point:
  641. // 1) It's possible that the mainWindow won't actually change to the requested size, if the requested
  642. // size is larger than the current display resolution (Qt::SetGeometry will fire a second resize event
  643. // that shrinks the mainWindow back to the display resolution and will emit a warning in debug builds),
  644. // or smaller than the minimum size allowed by the various widgets in the window.
  645. // 2) If LayoutWnd contains multiple viewports, the delta change of the main window will affect the delta
  646. // size of LayoutWnd, which is then divided proportionately among the multiple viewports, so the 1:1 size
  647. // assumption in the logic below isn't correct in the multi-viewport case.
  648. // 3) Sometimes Qt will just change this by 1 pixel (either smaller or bigger) with a second subsequent
  649. // resize event for no apparent reason.
  650. // 4) The layout of the docked windows *around* the viewport widget can affect how it grows and shrinks,
  651. // so even if you try to change the size of the layout widget, it might auto-resize afterwards to fill any
  652. // gaps between it and other widgets (console window, entity inspector, etc).
  653. mainWindow->move(0, 0);
  654. mainWindow->resize(mainWindow->size() + deltaSize);
  655. // We can avoid the problems above by using the "FixedSize" policy. If we've chosen this policy, we'll make
  656. // the viewport a scrollable region that's exactly the resolution requested here. This is useful for screenshots
  657. // in automation testing among other things, since this way we can guarantee the resolution of the screenshot matches
  658. // the resolution of any golden images we're comparing against.
  659. if (m_viewportPolicy == ViewportExpansionPolicy::FixedSize)
  660. {
  661. m_viewport->resize(requestedSize);
  662. update();
  663. }
  664. }
  665. //////////////////////////////////////////////////////////////////////////
  666. void CLayoutViewPane::SetAspectRatio(unsigned int x, unsigned int y)
  667. {
  668. if (x == 0 || y == 0)
  669. {
  670. return;
  671. }
  672. const QRect viewportRect = m_viewport->rect();
  673. // Round height to nearest multiple of y aspect, then scale width according to ratio
  674. const unsigned int height = ((viewportRect.height() + y - 1) / y) * y;
  675. const unsigned int width = height / y * x;
  676. ResizeViewport(width, height);
  677. }
  678. //////////////////////////////////////////////////////////////////////////
  679. void CLayoutViewPane::SetViewportFOV(const float fovDegrees)
  680. {
  681. if (EditorViewportWidget* pRenderViewport = qobject_cast<EditorViewportWidget*>(m_viewport))
  682. {
  683. const auto fovRadians = AZ::DegToRad(fovDegrees);
  684. pRenderViewport->SetFOV(fovRadians);
  685. // if viewport camera is active, make selected fov new default
  686. if (pRenderViewport->GetViewManager()->GetCameraObjectId() == GUID_NULL)
  687. {
  688. SandboxEditor::SetCameraDefaultFovRadians(fovRadians);
  689. }
  690. OnFOVChanged(fovRadians);
  691. }
  692. }
  693. //////////////////////////////////////////////////////////////////////////
  694. void CLayoutViewPane::ToggleMaximize()
  695. {
  696. ////////////////////////////////////////////////////////////////////////
  697. // Switch in and out of fullscreen mode for a edit view
  698. ////////////////////////////////////////////////////////////////////////
  699. CLayoutWnd* wnd = GetIEditor()->GetViewManager()->GetLayout();
  700. if (wnd)
  701. {
  702. wnd->MaximizeViewport(GetId());
  703. }
  704. setFocus();
  705. }
  706. //////////////////////////////////////////////////////////////////////////
  707. void CLayoutViewPane::OnMenuLayoutConfig()
  708. {
  709. if (GetIEditor()->IsInGameMode())
  710. {
  711. // you may not change your viewports while game mode is running.
  712. CryLog("You may not change viewport configuration while in game mode.");
  713. return;
  714. }
  715. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  716. if (layout)
  717. {
  718. CLayoutConfigDialog dlg;
  719. dlg.SetLayout(layout->GetLayout());
  720. if (dlg.exec() == QDialog::Accepted)
  721. {
  722. // Will kill this Pane. so must be last line in this function.
  723. layout->CreateLayout(dlg.GetLayout());
  724. }
  725. }
  726. }
  727. //////////////////////////////////////////////////////////////////////////
  728. void CLayoutViewPane::OnMenuViewSelected(const QString& paneName)
  729. {
  730. if (GetIEditor()->IsInGameMode())
  731. {
  732. CryLog("You may not change viewport configuration while in game mode.");
  733. // you may not change your viewports while game mode is running.
  734. return;
  735. }
  736. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  737. if (layout)
  738. {
  739. layout->BindViewport(this, paneName);
  740. }
  741. }
  742. //////////////////////////////////////////////////////////////////////////
  743. void CLayoutViewPane::OnMenuMaximized()
  744. {
  745. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  746. if (m_viewport && layout)
  747. {
  748. layout->MaximizeViewport(GetId());
  749. }
  750. }
  751. //////////////////////////////////////////////////////////////////////////
  752. void CLayoutViewPane::ShowTitleMenu()
  753. {
  754. ////////////////////////////////////////////////////////////////////////
  755. // Process clicks on the view buttons and the menu button
  756. ////////////////////////////////////////////////////////////////////////
  757. // Only continue when we have a viewport.
  758. // Create pop up menu.
  759. QMenu root(this);
  760. if (QtViewport* vp = qobject_cast<QtViewport*>(m_viewport))
  761. {
  762. vp->OnTitleMenu(&root);
  763. }
  764. if (!root.isEmpty())
  765. {
  766. root.addSeparator();
  767. }
  768. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  769. QAction* action = root.addAction(tr("Maximized"));
  770. if (layout)
  771. {
  772. connect(action, &QAction::triggered, layout, &CLayoutWnd::MaximizeViewport);
  773. }
  774. action->setChecked(IsFullscreen());
  775. action = root.addAction(tr("Configure Layout..."));
  776. if (!CViewManager::IsMultiViewportEnabled())
  777. {
  778. action->setDisabled(true);
  779. }
  780. // NOTE: this must be a QueuedConnection, so that it executes after the menu is deleted.
  781. // Changing the layout can cause the current "this" pointer to be deleted
  782. // and since we've made the "this" pointer the menu's parent,
  783. // it gets deleted when the "this" pointer is deleted. Since it's not a heap object,
  784. // that causes a crash. Using a QueuedConnection forces the layout config to happen
  785. // after the QMenu is cleaned up on the stack.
  786. connect(action, &QAction::triggered, this, &CLayoutViewPane::OnMenuLayoutConfig, Qt::QueuedConnection);
  787. root.exec(QCursor::pos());
  788. }
  789. //////////////////////////////////////////////////////////////////////////
  790. void CLayoutViewPane::mouseDoubleClickEvent(QMouseEvent* event)
  791. {
  792. if (event->button() == Qt::LeftButton)
  793. {
  794. ToggleMaximize();
  795. }
  796. }
  797. //////////////////////////////////////////////////////////////////////////
  798. void CLayoutViewPane::focusInEvent([[maybe_unused]] QFocusEvent* event)
  799. {
  800. // Forward SetFocus call to child viewport.
  801. if (m_viewport)
  802. {
  803. m_viewport->setFocus();
  804. }
  805. }
  806. //////////////////////////////////////////////////////////////////////////
  807. void CLayoutViewPane::SetFullscren(bool f)
  808. {
  809. m_bFullscreen = f;
  810. }
  811. //////////////////////////////////////////////////////////////////////////
  812. void CLayoutViewPane::SetFocusToViewport()
  813. {
  814. if (m_viewport)
  815. {
  816. m_viewport->window()->activateWindow();
  817. m_viewport->setFocus();
  818. }
  819. }
  820. //////////////////////////////////////////////////////////////////////////
  821. void CLayoutViewPane::OnFOVChanged(const float fovRadians)
  822. {
  823. AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Broadcast(
  824. &AzToolsFramework::ViewportInteraction::ViewportSettingNotifications::OnCameraFovChanged, fovRadians);
  825. }
  826. //////////////////////////////////////////////////////////////////////////
  827. namespace
  828. {
  829. AZ::Vector2 PyGetViewPortSize()
  830. {
  831. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  832. if (viewPane && viewPane->GetViewport())
  833. {
  834. const QRect rcViewport = viewPane->GetViewport()->rect();
  835. return AZ::Vector2(static_cast<float>(rcViewport.width()), static_cast<float>(rcViewport.height()));
  836. }
  837. else
  838. {
  839. return AZ::Vector2();
  840. }
  841. }
  842. void PySetViewPortSize(int width, int height)
  843. {
  844. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  845. if (viewPane)
  846. {
  847. viewPane->ResizeViewport(width, height);
  848. }
  849. }
  850. static void PyUpdateViewPort()
  851. {
  852. GetIEditor()->UpdateViews(eRedrawViewports);
  853. }
  854. void PyResizeViewport(int width, int height)
  855. {
  856. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  857. if (viewPane)
  858. {
  859. viewPane->ResizeViewport(width, height);
  860. }
  861. }
  862. void PyBindViewport(const char* viewportName)
  863. {
  864. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  865. if (viewPane)
  866. {
  867. GetIEditor()->GetViewManager()->GetLayout()->BindViewport(viewPane, viewportName);
  868. }
  869. }
  870. void PySetViewportExpansionPolicy(const char* policy)
  871. {
  872. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  873. if (viewPane)
  874. {
  875. if (AzFramework::StringFunc::Equal(policy, "AutoExpand"))
  876. {
  877. viewPane->SetViewportExpansionPolicy(CLayoutViewPane::ViewportExpansionPolicy::AutoExpand);
  878. }
  879. else if (AzFramework::StringFunc::Equal(policy, "FixedSize"))
  880. {
  881. viewPane->SetViewportExpansionPolicy(CLayoutViewPane::ViewportExpansionPolicy::FixedSize);
  882. }
  883. }
  884. }
  885. const char* PyGetViewportExpansionPolicy()
  886. {
  887. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  888. if (viewPane)
  889. {
  890. switch (viewPane->GetViewportExpansionPolicy())
  891. {
  892. case CLayoutViewPane::ViewportExpansionPolicy::AutoExpand: return "AutoExpand";
  893. case CLayoutViewPane::ViewportExpansionPolicy::FixedSize: return "FixedSize";
  894. }
  895. }
  896. return "";
  897. }
  898. unsigned int PyGetViewportCount()
  899. {
  900. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  901. return layout ? layout->GetViewPaneCount() : 0;
  902. }
  903. unsigned int PyGetActiveViewport()
  904. {
  905. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  906. if (layout)
  907. {
  908. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  909. for (unsigned int index = 0; index < layout->GetViewPaneCount(); index++)
  910. {
  911. if (viewPane == layout->GetViewPaneByIndex(index))
  912. {
  913. return index;
  914. }
  915. }
  916. }
  917. AZ_Error("Main", false, "No active viewport found.");
  918. return 0;
  919. }
  920. void PySetActiveViewport(unsigned int viewportIndex)
  921. {
  922. [[maybe_unused]] bool success = false;
  923. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  924. if (layout)
  925. {
  926. CLayoutViewPane* viewPane = layout->GetViewPaneByIndex(viewportIndex);
  927. if (viewPane)
  928. {
  929. viewPane->SetFocusToViewport();
  930. MainWindow::instance()->SetActiveView(viewPane);
  931. success = true;
  932. }
  933. }
  934. AZ_Error("Main", success, "Active viewport was not set successfully.");
  935. }
  936. unsigned int PyGetViewPaneLayout()
  937. {
  938. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  939. return layout ? layout->GetLayout() : ET_Layout0;
  940. }
  941. void PySetViewPaneLayout(unsigned int layoutId)
  942. {
  943. AZ_PUSH_DISABLE_WARNING(4296, "-Wunknown-warning-option")
  944. if ((layoutId >= ET_Layout0) && (layoutId <= ET_Layout8))
  945. AZ_POP_DISABLE_WARNING
  946. {
  947. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  948. if (layout)
  949. {
  950. layout->CreateLayout(static_cast<EViewLayout>(layoutId));
  951. }
  952. }
  953. else
  954. {
  955. AZ_Error("Main", false, "Invalid layout (%u), only values from %u to %u are valid.", layoutId, ET_Layout0, ET_Layout8);
  956. }
  957. }
  958. }
  959. //////////////////////////////////////////////////////////////////////////
  960. namespace AzToolsFramework
  961. {
  962. void ViewPanePythonFuncsHandler::Reflect(AZ::ReflectContext* context)
  963. {
  964. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  965. {
  966. // this will put these methods into the 'azlmbr.legacy.general' module
  967. auto addLegacyGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
  968. {
  969. methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
  970. ->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor")
  971. ->Attribute(AZ::Script::Attributes::Module, "legacy.general");
  972. };
  973. addLegacyGeneral(behaviorContext->Method("get_viewport_size", PyGetViewPortSize, nullptr, "Get the width and height of the active viewport."));
  974. addLegacyGeneral(behaviorContext->Method("set_viewport_size", PySetViewPortSize, nullptr, "Set the width and height of the active viewport."));
  975. addLegacyGeneral(behaviorContext->Method("update_viewport", PyUpdateViewPort, nullptr, "Update all visible SDK viewports."));
  976. addLegacyGeneral(behaviorContext->Method("resize_viewport", PyResizeViewport, nullptr, "Resizes the viewport resolution to a given width & height."));
  977. addLegacyGeneral(behaviorContext->Method("bind_viewport", PyBindViewport, nullptr, "Binds the viewport to a specific view like 'Top', 'Front', 'Perspective'."));
  978. addLegacyGeneral(behaviorContext->Method("get_viewport_expansion_policy", PyGetViewportExpansionPolicy, nullptr, "Returns whether viewports are auto-resized with the main window ('AutoExpand') or if they remain a fixed size ('FixedSize')."));
  979. addLegacyGeneral(behaviorContext->Method("set_viewport_expansion_policy", PySetViewportExpansionPolicy, nullptr, "Sets whether viewports are auto-resized with the main window ('AutoExpand') or if they remain a fixed size ('FixedSize')."));
  980. addLegacyGeneral(behaviorContext->Method("get_viewport_count", PyGetViewportCount, nullptr, "Get the total number of viewports."));
  981. addLegacyGeneral(behaviorContext->Method("get_active_viewport", PyGetActiveViewport, nullptr, "Get the active viewport index."));
  982. addLegacyGeneral(behaviorContext->Method("set_active_viewport", PySetActiveViewport, nullptr, "Set the active viewport by index."));
  983. addLegacyGeneral(behaviorContext->Method("get_view_pane_layout", PyGetViewPaneLayout, nullptr, "Get the active view pane layout."));
  984. addLegacyGeneral(behaviorContext->Method("set_view_pane_layout", PySetViewPaneLayout, nullptr, "Set the active view pane layout."));
  985. }
  986. }
  987. }
  988. #include <moc_ViewPane.cpp>