ViewPane.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  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 = AZ::GetGCD(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. SandboxEditor::SetCameraDefaultFovRadians(fovRadians);
  687. OnFOVChanged(fovRadians);
  688. }
  689. }
  690. //////////////////////////////////////////////////////////////////////////
  691. void CLayoutViewPane::ToggleMaximize()
  692. {
  693. ////////////////////////////////////////////////////////////////////////
  694. // Switch in and out of fullscreen mode for a edit view
  695. ////////////////////////////////////////////////////////////////////////
  696. CLayoutWnd* wnd = GetIEditor()->GetViewManager()->GetLayout();
  697. if (wnd)
  698. {
  699. wnd->MaximizeViewport(GetId());
  700. }
  701. setFocus();
  702. }
  703. //////////////////////////////////////////////////////////////////////////
  704. void CLayoutViewPane::OnMenuLayoutConfig()
  705. {
  706. if (GetIEditor()->IsInGameMode())
  707. {
  708. // you may not change your viewports while game mode is running.
  709. CryLog("You may not change viewport configuration while in game mode.");
  710. return;
  711. }
  712. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  713. if (layout)
  714. {
  715. CLayoutConfigDialog dlg;
  716. dlg.SetLayout(layout->GetLayout());
  717. if (dlg.exec() == QDialog::Accepted)
  718. {
  719. // Will kill this Pane. so must be last line in this function.
  720. layout->CreateLayout(dlg.GetLayout());
  721. }
  722. }
  723. }
  724. //////////////////////////////////////////////////////////////////////////
  725. void CLayoutViewPane::OnMenuViewSelected(const QString& paneName)
  726. {
  727. if (GetIEditor()->IsInGameMode())
  728. {
  729. CryLog("You may not change viewport configuration while in game mode.");
  730. // you may not change your viewports while game mode is running.
  731. return;
  732. }
  733. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  734. if (layout)
  735. {
  736. layout->BindViewport(this, paneName);
  737. }
  738. }
  739. //////////////////////////////////////////////////////////////////////////
  740. void CLayoutViewPane::OnMenuMaximized()
  741. {
  742. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  743. if (m_viewport && layout)
  744. {
  745. layout->MaximizeViewport(GetId());
  746. }
  747. }
  748. //////////////////////////////////////////////////////////////////////////
  749. void CLayoutViewPane::ShowTitleMenu()
  750. {
  751. ////////////////////////////////////////////////////////////////////////
  752. // Process clicks on the view buttons and the menu button
  753. ////////////////////////////////////////////////////////////////////////
  754. // Only continue when we have a viewport.
  755. // Create pop up menu.
  756. QMenu root(this);
  757. if (QtViewport* vp = qobject_cast<QtViewport*>(m_viewport))
  758. {
  759. vp->OnTitleMenu(&root);
  760. }
  761. if (!root.isEmpty())
  762. {
  763. root.addSeparator();
  764. }
  765. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  766. QAction* action = root.addAction(tr("Maximized"));
  767. if (layout)
  768. {
  769. connect(action, &QAction::triggered, layout, &CLayoutWnd::MaximizeViewport);
  770. }
  771. action->setChecked(IsFullscreen());
  772. action = root.addAction(tr("Configure Layout..."));
  773. if (!CViewManager::IsMultiViewportEnabled())
  774. {
  775. action->setDisabled(true);
  776. }
  777. // NOTE: this must be a QueuedConnection, so that it executes after the menu is deleted.
  778. // Changing the layout can cause the current "this" pointer to be deleted
  779. // and since we've made the "this" pointer the menu's parent,
  780. // it gets deleted when the "this" pointer is deleted. Since it's not a heap object,
  781. // that causes a crash. Using a QueuedConnection forces the layout config to happen
  782. // after the QMenu is cleaned up on the stack.
  783. connect(action, &QAction::triggered, this, &CLayoutViewPane::OnMenuLayoutConfig, Qt::QueuedConnection);
  784. root.exec(QCursor::pos());
  785. }
  786. //////////////////////////////////////////////////////////////////////////
  787. void CLayoutViewPane::mouseDoubleClickEvent(QMouseEvent* event)
  788. {
  789. if (event->button() == Qt::LeftButton)
  790. {
  791. ToggleMaximize();
  792. }
  793. }
  794. //////////////////////////////////////////////////////////////////////////
  795. void CLayoutViewPane::focusInEvent([[maybe_unused]] QFocusEvent* event)
  796. {
  797. // Forward SetFocus call to child viewport.
  798. if (m_viewport)
  799. {
  800. m_viewport->setFocus();
  801. }
  802. }
  803. //////////////////////////////////////////////////////////////////////////
  804. void CLayoutViewPane::SetFullscren(bool f)
  805. {
  806. m_bFullscreen = f;
  807. }
  808. //////////////////////////////////////////////////////////////////////////
  809. void CLayoutViewPane::SetFocusToViewport()
  810. {
  811. if (m_viewport)
  812. {
  813. m_viewport->window()->activateWindow();
  814. m_viewport->setFocus();
  815. }
  816. }
  817. //////////////////////////////////////////////////////////////////////////
  818. void CLayoutViewPane::OnFOVChanged(const float fovRadians)
  819. {
  820. AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Broadcast(
  821. &AzToolsFramework::ViewportInteraction::ViewportSettingNotifications::OnCameraFovChanged, fovRadians);
  822. }
  823. //////////////////////////////////////////////////////////////////////////
  824. namespace
  825. {
  826. AZ::Vector2 PyGetViewPortSize()
  827. {
  828. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  829. if (viewPane && viewPane->GetViewport())
  830. {
  831. const QRect rcViewport = viewPane->GetViewport()->rect();
  832. return AZ::Vector2(static_cast<float>(rcViewport.width()), static_cast<float>(rcViewport.height()));
  833. }
  834. else
  835. {
  836. return AZ::Vector2();
  837. }
  838. }
  839. void PySetViewPortSize(int width, int height)
  840. {
  841. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  842. if (viewPane)
  843. {
  844. viewPane->ResizeViewport(width, height);
  845. }
  846. }
  847. static void PyUpdateViewPort()
  848. {
  849. GetIEditor()->UpdateViews(eRedrawViewports);
  850. }
  851. void PyResizeViewport(int width, int height)
  852. {
  853. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  854. if (viewPane)
  855. {
  856. viewPane->ResizeViewport(width, height);
  857. }
  858. }
  859. void PyBindViewport(const char* viewportName)
  860. {
  861. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  862. if (viewPane)
  863. {
  864. GetIEditor()->GetViewManager()->GetLayout()->BindViewport(viewPane, viewportName);
  865. }
  866. }
  867. void PySetViewportExpansionPolicy(const char* policy)
  868. {
  869. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  870. if (viewPane)
  871. {
  872. if (AzFramework::StringFunc::Equal(policy, "AutoExpand"))
  873. {
  874. viewPane->SetViewportExpansionPolicy(CLayoutViewPane::ViewportExpansionPolicy::AutoExpand);
  875. }
  876. else if (AzFramework::StringFunc::Equal(policy, "FixedSize"))
  877. {
  878. viewPane->SetViewportExpansionPolicy(CLayoutViewPane::ViewportExpansionPolicy::FixedSize);
  879. }
  880. }
  881. }
  882. const char* PyGetViewportExpansionPolicy()
  883. {
  884. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  885. if (viewPane)
  886. {
  887. switch (viewPane->GetViewportExpansionPolicy())
  888. {
  889. case CLayoutViewPane::ViewportExpansionPolicy::AutoExpand: return "AutoExpand";
  890. case CLayoutViewPane::ViewportExpansionPolicy::FixedSize: return "FixedSize";
  891. }
  892. }
  893. return "";
  894. }
  895. unsigned int PyGetViewportCount()
  896. {
  897. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  898. return layout ? layout->GetViewPaneCount() : 0;
  899. }
  900. unsigned int PyGetActiveViewport()
  901. {
  902. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  903. if (layout)
  904. {
  905. CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
  906. for (unsigned int index = 0; index < layout->GetViewPaneCount(); index++)
  907. {
  908. if (viewPane == layout->GetViewPaneByIndex(index))
  909. {
  910. return index;
  911. }
  912. }
  913. }
  914. AZ_Error("Main", false, "No active viewport found.");
  915. return 0;
  916. }
  917. void PySetActiveViewport(unsigned int viewportIndex)
  918. {
  919. [[maybe_unused]] bool success = false;
  920. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  921. if (layout)
  922. {
  923. CLayoutViewPane* viewPane = layout->GetViewPaneByIndex(viewportIndex);
  924. if (viewPane)
  925. {
  926. viewPane->SetFocusToViewport();
  927. MainWindow::instance()->SetActiveView(viewPane);
  928. success = true;
  929. }
  930. }
  931. AZ_Error("Main", success, "Active viewport was not set successfully.");
  932. }
  933. unsigned int PyGetViewPaneLayout()
  934. {
  935. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  936. return layout ? layout->GetLayout() : ET_Layout0;
  937. }
  938. void PySetViewPaneLayout(unsigned int layoutId)
  939. {
  940. AZ_PUSH_DISABLE_WARNING(4296, "-Wunknown-warning-option")
  941. if ((layoutId >= ET_Layout0) && (layoutId <= ET_Layout8))
  942. AZ_POP_DISABLE_WARNING
  943. {
  944. CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout();
  945. if (layout)
  946. {
  947. layout->CreateLayout(static_cast<EViewLayout>(layoutId));
  948. }
  949. }
  950. else
  951. {
  952. AZ_Error("Main", false, "Invalid layout (%u), only values from %u to %u are valid.", layoutId, ET_Layout0, ET_Layout8);
  953. }
  954. }
  955. }
  956. //////////////////////////////////////////////////////////////////////////
  957. namespace AzToolsFramework
  958. {
  959. void ViewPanePythonFuncsHandler::Reflect(AZ::ReflectContext* context)
  960. {
  961. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  962. {
  963. // this will put these methods into the 'azlmbr.legacy.general' module
  964. auto addLegacyGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
  965. {
  966. methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
  967. ->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor")
  968. ->Attribute(AZ::Script::Attributes::Module, "legacy.general");
  969. };
  970. addLegacyGeneral(behaviorContext->Method("get_viewport_size", PyGetViewPortSize, nullptr, "Get the width and height of the active viewport."));
  971. addLegacyGeneral(behaviorContext->Method("set_viewport_size", PySetViewPortSize, nullptr, "Set the width and height of the active viewport."));
  972. addLegacyGeneral(behaviorContext->Method("update_viewport", PyUpdateViewPort, nullptr, "Update all visible SDK viewports."));
  973. addLegacyGeneral(behaviorContext->Method("resize_viewport", PyResizeViewport, nullptr, "Resizes the viewport resolution to a given width & height."));
  974. addLegacyGeneral(behaviorContext->Method("bind_viewport", PyBindViewport, nullptr, "Binds the viewport to a specific view like 'Top', 'Front', 'Perspective'."));
  975. 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')."));
  976. 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')."));
  977. addLegacyGeneral(behaviorContext->Method("get_viewport_count", PyGetViewportCount, nullptr, "Get the total number of viewports."));
  978. addLegacyGeneral(behaviorContext->Method("get_active_viewport", PyGetActiveViewport, nullptr, "Get the active viewport index."));
  979. addLegacyGeneral(behaviorContext->Method("set_active_viewport", PySetActiveViewport, nullptr, "Set the active viewport by index."));
  980. addLegacyGeneral(behaviorContext->Method("get_view_pane_layout", PyGetViewPaneLayout, nullptr, "Get the active view pane layout."));
  981. addLegacyGeneral(behaviorContext->Method("set_view_pane_layout", PySetViewPaneLayout, nullptr, "Set the active view pane layout."));
  982. }
  983. }
  984. }
  985. #include <moc_ViewPane.cpp>