3
0

EditorWhiteBoxTransformMode.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorWhiteBoxTransformMode.h"
  9. #include "EditorWhiteBoxComponentModeCommon.h"
  10. #include "EditorWhiteBoxComponentModeTypes.h"
  11. #include "Util/WhiteBoxEditorDrawUtil.h"
  12. #include <AzCore/std/smart_ptr/make_shared.h>
  13. #include <AzFramework/Viewport/ViewportColors.h>
  14. #include <AzToolsFramework/ActionManager/Action/ActionManagerInterface.h>
  15. #include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
  16. #include <AzToolsFramework/ActionManager/HotKey/HotKeyManagerInterface.h>
  17. #include <AzToolsFramework/API/ComponentModeCollectionInterface.h>
  18. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorContextIdentifiers.h>
  19. #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorMenuIdentifiers.h>
  20. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  21. #include <Manipulators/LinearManipulator.h>
  22. #include <Manipulators/ManipulatorManager.h>
  23. #include <Manipulators/RotationManipulators.h>
  24. #include <Manipulators/ScaleManipulators.h>
  25. #include <Manipulators/TranslationManipulators.h>
  26. #include <Viewport/ViewportSettings.h>
  27. #include <Viewport/WhiteBoxModifierUtil.h>
  28. #include <Viewport/WhiteBoxViewportConstants.h>
  29. #include <QKeySequence>
  30. namespace WhiteBox
  31. {
  32. AZ_CLASS_ALLOCATOR_IMPL(TransformMode, AZ::SystemAllocator)
  33. static const AZ::Crc32 SwitchTranslationMode = AZ_CRC_CE("org.o3de.action.whitebox.switch_translation");
  34. static const AZ::Crc32 SwitchRotationMode = AZ_CRC_CE("org.o3de.action.whitebox.switch_rotation");
  35. static const AZ::Crc32 SwitchScaleMode = AZ_CRC_CE("org.o3de.action.whitebox.switch_scale");
  36. const constexpr char* SwitchToTranslationModeTile = "Translation Mode";
  37. const constexpr char* SwitchToRotationModeTile = "Rotation Mode";
  38. const constexpr char* SwitchToScaleModeTile = "Scale Mode";
  39. const constexpr char* SwitchToTranslationModeDesc = "Switch to Translation Mode";
  40. const constexpr char* SwitchToRotationModeDesc = "Switch to Rotation Mode";
  41. const constexpr char* SwitchToScaleModeDesc = "Switch to Scale Mode";
  42. static void SetViewportUiClusterActiveButton(
  43. AzToolsFramework::ViewportUi::ClusterId clusterId, AzToolsFramework::ViewportUi::ButtonId buttonId)
  44. {
  45. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  46. AzToolsFramework::ViewportUi::DefaultViewportId,
  47. &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton,
  48. clusterId,
  49. buttonId);
  50. }
  51. static void SetViewportUiClusterDisableButton(
  52. AzToolsFramework::ViewportUi::ClusterId clusterId, AzToolsFramework::ViewportUi::ButtonId buttonId, bool isDisabled)
  53. {
  54. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  55. AzToolsFramework::ViewportUi::DefaultViewportId,
  56. &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterDisableButton,
  57. clusterId,
  58. buttonId,
  59. isDisabled);
  60. }
  61. TransformMode::TransformMode(const AZ::EntityComponentIdPair& entityComponentIdPair)
  62. : m_entityComponentIdPair(entityComponentIdPair)
  63. {
  64. EditorWhiteBoxTransformModeRequestBus::Handler::BusConnect(entityComponentIdPair);
  65. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  66. AzToolsFramework::ViewportUi::DefaultViewportId,
  67. [&](AzToolsFramework::ViewportUi::ViewportUiRequests* requests)
  68. {
  69. auto fetchIcon = [](const char* iconName)
  70. {
  71. return AZStd::string::format(":/stylesheet/img/UI20/toolbar/%s.svg", iconName);
  72. };
  73. m_transformClusterId = requests->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
  74. m_transformTranslateButtonId = requests->CreateClusterButton(m_transformClusterId, fetchIcon("Move"));
  75. m_transformRotateButtonId = requests->CreateClusterButton(m_transformClusterId, fetchIcon("Rotate"));
  76. m_transformScaleButtonId = requests->CreateClusterButton(m_transformClusterId, fetchIcon("Scale"));
  77. // set translation tooltips
  78. requests->SetClusterButtonTooltip(m_transformClusterId, m_transformTranslateButtonId,
  79. ManipulatorModeClusterTranslateTooltip);
  80. requests->SetClusterButtonTooltip(m_transformClusterId, m_transformRotateButtonId,
  81. ManipulatorModeClusterRotateTooltip);
  82. requests->SetClusterButtonTooltip(m_transformClusterId, m_transformScaleButtonId,
  83. ManipulatorModeClusterScaleTooltip);
  84. }
  85. );
  86. m_transformSelectionHandler = AZ::Event<AzToolsFramework::ViewportUi::ButtonId>::Handler(
  87. [this](AzToolsFramework::ViewportUi::ButtonId buttonId)
  88. {
  89. if (buttonId == m_transformTranslateButtonId)
  90. {
  91. ChangeTransformType(TransformType::Translation);
  92. }
  93. else if (buttonId == m_transformRotateButtonId)
  94. {
  95. ChangeTransformType(TransformType::Rotation);
  96. }
  97. else if (buttonId == m_transformScaleButtonId)
  98. {
  99. ChangeTransformType(TransformType::Scale);
  100. }
  101. }
  102. );
  103. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  104. AzToolsFramework::ViewportUi::DefaultViewportId,
  105. &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler,
  106. m_transformClusterId,
  107. m_transformSelectionHandler);
  108. RefreshManipulator();
  109. }
  110. TransformMode::~TransformMode()
  111. {
  112. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  113. AzToolsFramework::ViewportUi::DefaultViewportId,
  114. &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster,
  115. m_transformClusterId);
  116. DestroyManipulators();
  117. EditorWhiteBoxTransformModeRequestBus::Handler::BusDisconnect();
  118. }
  119. void TransformMode::RegisterActionUpdaters()
  120. {
  121. }
  122. void TransformMode::RegisterActions()
  123. {
  124. auto actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
  125. AZ_Assert(actionManagerInterface, "WhiteBoxTransformMode - could not get ActionManagerInterface on RegisterActions.");
  126. auto hotKeyManagerInterface = AZ::Interface<AzToolsFramework::HotKeyManagerInterface>::Get();
  127. AZ_Assert(hotKeyManagerInterface, "WhiteBoxTransformMode - could not get HotKeyManagerInterface on RegisterActions.");
  128. // Translation
  129. {
  130. constexpr AZStd::string_view actionIdentifier = "o3de.action.whiteBoxComponentMode.transform.translation";
  131. AzToolsFramework::ActionProperties actionProperties;
  132. actionProperties.m_name = SwitchToTranslationModeTile;
  133. actionProperties.m_description = SwitchToTranslationModeDesc;
  134. actionProperties.m_category = "White Box Component Mode - Transform";
  135. actionManagerInterface->RegisterAction(
  136. EditorIdentifiers::MainWindowActionContextIdentifier,
  137. actionIdentifier,
  138. actionProperties,
  139. []
  140. {
  141. auto componentModeCollectionInterface = AZ::Interface<AzToolsFramework::ComponentModeCollectionInterface>::Get();
  142. AZ_Assert(componentModeCollectionInterface, "Could not retrieve component mode collection.");
  143. componentModeCollectionInterface->EnumerateActiveComponents(
  144. [](const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid&)
  145. {
  146. EditorWhiteBoxTransformModeRequestBus::Event(
  147. entityComponentIdPair,
  148. &EditorWhiteBoxTransformModeRequests::ChangeTransformType,
  149. TransformType::Translation);
  150. }
  151. );
  152. }
  153. );
  154. hotKeyManagerInterface->SetActionHotKey(actionIdentifier, "1");
  155. }
  156. // Rotation
  157. {
  158. constexpr AZStd::string_view actionIdentifier = "o3de.action.whiteBoxComponentMode.transform.rotation";
  159. AzToolsFramework::ActionProperties actionProperties;
  160. actionProperties.m_name = SwitchToRotationModeTile;
  161. actionProperties.m_description = SwitchToRotationModeDesc;
  162. actionProperties.m_category = "White Box Component Mode - Transform";
  163. actionManagerInterface->RegisterAction(
  164. EditorIdentifiers::MainWindowActionContextIdentifier,
  165. actionIdentifier,
  166. actionProperties,
  167. []
  168. {
  169. auto componentModeCollectionInterface = AZ::Interface<AzToolsFramework::ComponentModeCollectionInterface>::Get();
  170. AZ_Assert(componentModeCollectionInterface, "Could not retrieve component mode collection.");
  171. componentModeCollectionInterface->EnumerateActiveComponents(
  172. [](const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid&)
  173. {
  174. EditorWhiteBoxTransformModeRequestBus::Event(
  175. entityComponentIdPair,
  176. &EditorWhiteBoxTransformModeRequests::ChangeTransformType,
  177. TransformType::Rotation);
  178. }
  179. );
  180. }
  181. );
  182. hotKeyManagerInterface->SetActionHotKey(actionIdentifier, "2");
  183. }
  184. // Scale
  185. {
  186. constexpr AZStd::string_view actionIdentifier = "o3de.action.whiteBoxComponentMode.transform.scale";
  187. AzToolsFramework::ActionProperties actionProperties;
  188. actionProperties.m_name = SwitchToScaleModeTile;
  189. actionProperties.m_description = SwitchToScaleModeDesc;
  190. actionProperties.m_category = "White Box Component Mode - Transform";
  191. actionManagerInterface->RegisterAction(
  192. EditorIdentifiers::MainWindowActionContextIdentifier,
  193. actionIdentifier,
  194. actionProperties,
  195. []
  196. {
  197. auto componentModeCollectionInterface = AZ::Interface<AzToolsFramework::ComponentModeCollectionInterface>::Get();
  198. AZ_Assert(componentModeCollectionInterface, "Could not retrieve component mode collection.");
  199. componentModeCollectionInterface->EnumerateActiveComponents(
  200. [](const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid&)
  201. {
  202. EditorWhiteBoxTransformModeRequestBus::Event(
  203. entityComponentIdPair,
  204. &EditorWhiteBoxTransformModeRequests::ChangeTransformType,
  205. TransformType::Scale);
  206. }
  207. );
  208. }
  209. );
  210. hotKeyManagerInterface->SetActionHotKey(actionIdentifier, "3");
  211. }
  212. }
  213. void TransformMode::BindActionsToModes(const AZStd::string& modeIdentifier)
  214. {
  215. auto actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
  216. AZ_Assert(actionManagerInterface, "WhiteBoxTransformMode - could not get ActionManagerInterface on BindActionsToModes.");
  217. actionManagerInterface->AssignModeToAction(modeIdentifier, "o3de.action.whiteBoxComponentMode.transform.translation");
  218. actionManagerInterface->AssignModeToAction(modeIdentifier, "o3de.action.whiteBoxComponentMode.transform.rotation");
  219. actionManagerInterface->AssignModeToAction(modeIdentifier, "o3de.action.whiteBoxComponentMode.transform.scale");
  220. actionManagerInterface->AssignModeToAction(modeIdentifier, "o3de.action.componentMode.end");
  221. }
  222. void TransformMode::BindActionsToMenus()
  223. {
  224. auto menuManagerInterface = AZ::Interface<AzToolsFramework::MenuManagerInterface>::Get();
  225. AZ_Assert(menuManagerInterface, "WhiteBoxTransformMode - could not get MenuManagerInterface on BindActionsToMenus.");
  226. menuManagerInterface->AddActionToMenu(EditorIdentifiers::EditMenuIdentifier, "o3de.action.whiteBoxComponentMode.transform.translation", 6000);
  227. menuManagerInterface->AddActionToMenu(EditorIdentifiers::EditMenuIdentifier, "o3de.action.whiteBoxComponentMode.transform.rotation", 6001);
  228. menuManagerInterface->AddActionToMenu(EditorIdentifiers::EditMenuIdentifier, "o3de.action.whiteBoxComponentMode.transform.scale", 6002);
  229. }
  230. void TransformMode::DestroyManipulators()
  231. {
  232. if (m_manipulator)
  233. {
  234. m_manipulator->Unregister();
  235. m_manipulator.reset();
  236. }
  237. }
  238. void TransformMode::ChangeTransformType(TransformType subModeType)
  239. {
  240. m_transformType = subModeType;
  241. RefreshManipulator();
  242. }
  243. void TransformMode::Refresh()
  244. {
  245. m_whiteBoxSelection.reset();
  246. DestroyManipulators();
  247. }
  248. AZStd::vector<AzToolsFramework::ActionOverride> TransformMode::PopulateActions(
  249. [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair)
  250. {
  251. return {
  252. AzToolsFramework::ActionOverride()
  253. .SetUri(SwitchTranslationMode)
  254. .SetKeySequence(QKeySequence{Qt::Key_1})
  255. .SetTitle(SwitchToTranslationModeTile)
  256. .SetTip(SwitchToTranslationModeDesc)
  257. .SetEntityComponentIdPair(entityComponentIdPair)
  258. .SetCallback(
  259. [clusterId = m_transformClusterId, buttonId = m_transformTranslateButtonId]()
  260. {
  261. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  262. AzToolsFramework::ViewportUi::DefaultViewportId,
  263. [](AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events* event,
  264. AzToolsFramework::ViewportUi::ClusterId clusterId,
  265. AzToolsFramework::ViewportUi::ButtonId buttonId)
  266. {
  267. event->PressButton(clusterId, buttonId);
  268. },
  269. clusterId,
  270. buttonId);
  271. }),
  272. AzToolsFramework::ActionOverride()
  273. .SetUri(SwitchRotationMode)
  274. .SetKeySequence(QKeySequence{Qt::Key_2})
  275. .SetTitle(SwitchToRotationModeTile)
  276. .SetTip(SwitchToRotationModeDesc)
  277. .SetEntityComponentIdPair(entityComponentIdPair)
  278. .SetCallback(
  279. [clusterId = m_transformClusterId, buttonId = m_transformRotateButtonId]()
  280. {
  281. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  282. AzToolsFramework::ViewportUi::DefaultViewportId,
  283. [](AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events* event,
  284. AzToolsFramework::ViewportUi::ClusterId clusterId,
  285. AzToolsFramework::ViewportUi::ButtonId buttonId)
  286. {
  287. event->PressButton(clusterId, buttonId);
  288. },
  289. clusterId,
  290. buttonId);
  291. }),
  292. AzToolsFramework::ActionOverride()
  293. .SetUri(SwitchScaleMode)
  294. .SetKeySequence(QKeySequence{Qt::Key_3})
  295. .SetTitle(SwitchToScaleModeTile)
  296. .SetTip(SwitchToScaleModeDesc)
  297. .SetEntityComponentIdPair(entityComponentIdPair)
  298. .SetCallback(
  299. [clusterId = m_transformClusterId, buttonId = m_transformScaleButtonId]()
  300. {
  301. AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
  302. AzToolsFramework::ViewportUi::DefaultViewportId,
  303. [](AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events* event,
  304. AzToolsFramework::ViewportUi::ClusterId clusterId,
  305. AzToolsFramework::ViewportUi::ButtonId buttonId)
  306. {
  307. event->PressButton(clusterId, buttonId);
  308. },
  309. clusterId,
  310. buttonId);
  311. })
  312. };
  313. }
  314. void TransformMode::Display(
  315. [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair,
  316. const AZ::Transform& worldFromLocal,
  317. [[maybe_unused]] const IntersectionAndRenderData& renderData,
  318. const AzFramework::ViewportInfo& viewportInfo,
  319. AzFramework::DebugDisplayRequests& debugDisplay)
  320. {
  321. WhiteBoxMesh* whiteBox = nullptr;
  322. EditorWhiteBoxComponentRequestBus::EventResult(
  323. whiteBox, m_entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  324. debugDisplay.DepthTestOn();
  325. debugDisplay.PushMatrix(worldFromLocal);
  326. if (m_polygonIntersection.has_value())
  327. {
  328. auto& polygonIntersection = m_polygonIntersection.value();
  329. DrawFace(debugDisplay, whiteBox, polygonIntersection.GetHandle(), ed_whiteBoxPolygonHover);
  330. DrawOutline(debugDisplay, whiteBox, polygonIntersection.GetHandle(), ed_whiteBoxOutlineHover);
  331. }
  332. if (m_edgeIntersection.has_value())
  333. {
  334. auto& edgeIntersection = m_edgeIntersection.value();
  335. DrawEdge(debugDisplay, whiteBox, edgeIntersection.GetHandle(), ed_whiteBoxOutlineHover);
  336. }
  337. if (m_vertexIntersection.has_value())
  338. {
  339. auto& vertexIntersection = m_vertexIntersection.value();
  340. auto handles = AZStd::array<Api::VertexHandle, 1>({ vertexIntersection.GetHandle() });
  341. DrawPoints(debugDisplay, whiteBox, worldFromLocal, viewportInfo, handles, ed_whiteBoxVertexHover);
  342. }
  343. if (m_whiteBoxSelection)
  344. {
  345. if (auto polygonSelection = AZStd::get_if<PolygonIntersection>(&m_whiteBoxSelection->m_selection))
  346. {
  347. auto vertexHandles = Api::PolygonVertexHandles(*whiteBox, polygonSelection->GetHandle());
  348. DrawPoints(debugDisplay, whiteBox, worldFromLocal, viewportInfo, vertexHandles, ed_whiteBoxVertexSelection);
  349. if (m_polygonIntersection.value_or(PolygonIntersection{}).GetHandle() != polygonSelection->GetHandle())
  350. {
  351. DrawFace(debugDisplay, whiteBox, polygonSelection->GetHandle(), ed_whiteBoxPolygonSelection);
  352. DrawOutline(debugDisplay, whiteBox, polygonSelection->GetHandle(), ed_whiteBoxOutlineSelection);
  353. }
  354. }
  355. else if (auto edgeSelection = AZStd::get_if<EdgeIntersection>(&m_whiteBoxSelection->m_selection))
  356. {
  357. auto vertexHandles = Api::EdgeVertexHandles(*whiteBox, edgeSelection->GetHandle());
  358. DrawPoints(debugDisplay, whiteBox, worldFromLocal, viewportInfo, vertexHandles, ed_whiteBoxVertexSelection);
  359. if (m_edgeIntersection.value_or(EdgeIntersection{}).GetHandle() != edgeSelection->GetHandle())
  360. {
  361. DrawEdge(debugDisplay, whiteBox, edgeSelection->GetHandle(), ed_whiteBoxOutlineSelection);
  362. }
  363. }
  364. else if (auto vertexSelection = AZStd::get_if<VertexIntersection>(&m_whiteBoxSelection->m_selection))
  365. {
  366. if (m_vertexIntersection.value_or(VertexIntersection{}).GetHandle() != vertexSelection->GetHandle())
  367. {
  368. auto handles = AZStd::array<Api::VertexHandle, 1>({ vertexSelection->GetHandle() });
  369. DrawPoints(debugDisplay, whiteBox, worldFromLocal, viewportInfo, handles, ed_whiteBoxVertexSelection);
  370. }
  371. }
  372. }
  373. debugDisplay.PopMatrix();
  374. debugDisplay.DepthTestOff();
  375. }
  376. bool TransformMode::HandleMouseInteraction(
  377. const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction,
  378. [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair,
  379. const AZStd::optional<EdgeIntersection>& edgeIntersection,
  380. const AZStd::optional<PolygonIntersection>& polygonIntersection,
  381. const AZStd::optional<VertexIntersection>& vertexIntersection)
  382. {
  383. WhiteBoxMesh* whiteBox = nullptr;
  384. EditorWhiteBoxComponentRequestBus::EventResult(
  385. whiteBox, m_entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  386. bool mouseOverManipulator = false;
  387. if (m_manipulator)
  388. {
  389. m_manipulator->ProcessManipulators(
  390. [&mouseOverManipulator](auto manipulator)
  391. {
  392. mouseOverManipulator = manipulator->MouseOver() || mouseOverManipulator;
  393. });
  394. }
  395. auto closestIntersection = mouseOverManipulator
  396. ? GeometryIntersection::None
  397. : FindClosestGeometryIntersection(edgeIntersection, polygonIntersection, vertexIntersection);
  398. m_polygonIntersection.reset();
  399. m_edgeIntersection.reset();
  400. m_vertexIntersection.reset();
  401. // update stored edge and vertex intersection
  402. switch (closestIntersection)
  403. {
  404. case GeometryIntersection::Polygon:
  405. m_polygonIntersection = polygonIntersection;
  406. break;
  407. case GeometryIntersection::Edge:
  408. m_edgeIntersection = edgeIntersection;
  409. break;
  410. case GeometryIntersection::Vertex:
  411. m_vertexIntersection = vertexIntersection;
  412. break;
  413. default:
  414. // do nothing
  415. break;
  416. }
  417. if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
  418. mouseInteraction.m_mouseEvent == AzToolsFramework::ViewportInteraction::MouseEvent::Down)
  419. {
  420. switch (closestIntersection)
  421. {
  422. case GeometryIntersection::Polygon:
  423. if (polygonIntersection.has_value())
  424. {
  425. m_whiteBoxSelection = AZStd::make_shared<TransformMode::VertexTransformSelection>();
  426. m_whiteBoxSelection->m_selection = polygonIntersection.value();
  427. RefreshManipulator();
  428. }
  429. break;
  430. case GeometryIntersection::Edge:
  431. if (edgeIntersection.has_value())
  432. {
  433. m_whiteBoxSelection = AZStd::make_shared<TransformMode::VertexTransformSelection>();
  434. m_whiteBoxSelection->m_selection = edgeIntersection.value();
  435. RefreshManipulator();
  436. }
  437. break;
  438. case GeometryIntersection::Vertex:
  439. if (vertexIntersection.has_value())
  440. {
  441. m_whiteBoxSelection = AZStd::make_shared<TransformMode::VertexTransformSelection>();
  442. m_whiteBoxSelection->m_selection = vertexIntersection.value();
  443. RefreshManipulator();
  444. }
  445. break;
  446. default:
  447. m_whiteBoxSelection.reset();
  448. DestroyManipulators();
  449. break;
  450. }
  451. }
  452. return false;
  453. }
  454. void TransformMode::RefreshManipulator()
  455. {
  456. TransformType activeTransformType = m_transformType;
  457. if (m_whiteBoxSelection && AZStd::get_if<VertexIntersection>(&m_whiteBoxSelection->m_selection))
  458. {
  459. SetViewportUiClusterDisableButton(m_transformClusterId, m_transformRotateButtonId, true);
  460. SetViewportUiClusterDisableButton(m_transformClusterId, m_transformScaleButtonId, true);
  461. activeTransformType = TransformType::Translation;
  462. }
  463. else
  464. {
  465. SetViewportUiClusterDisableButton(m_transformClusterId, m_transformRotateButtonId, false);
  466. SetViewportUiClusterDisableButton(m_transformClusterId, m_transformScaleButtonId, false);
  467. }
  468. DestroyManipulators();
  469. switch (activeTransformType)
  470. {
  471. case TransformType::Translation:
  472. CreateTranslationManipulators();
  473. SetViewportUiClusterActiveButton(m_transformClusterId, m_transformTranslateButtonId);
  474. break;
  475. case TransformType::Rotation:
  476. CreateRotationManipulators();
  477. SetViewportUiClusterActiveButton(m_transformClusterId, m_transformRotateButtonId);
  478. break;
  479. case TransformType::Scale:
  480. CreateScaleManipulators();
  481. SetViewportUiClusterActiveButton(m_transformClusterId, m_transformScaleButtonId);
  482. break;
  483. default:
  484. break;
  485. }
  486. }
  487. void TransformMode::UpdateTransformHandles(WhiteBoxMesh* mesh)
  488. {
  489. if (auto polygonSelection = AZStd::get_if<PolygonIntersection>(&m_whiteBoxSelection->m_selection))
  490. {
  491. m_whiteBoxSelection->m_vertexHandles = Api::PolygonVertexHandles(*mesh, polygonSelection->GetHandle());
  492. m_whiteBoxSelection->m_vertexPositions = Api::VertexPositions(*mesh, m_whiteBoxSelection->m_vertexHandles);
  493. m_whiteBoxSelection->m_localPosition = Api::PolygonMidpoint(*mesh, polygonSelection->GetHandle());
  494. }
  495. else if (auto edgeSelection = AZStd::get_if<EdgeIntersection>(&m_whiteBoxSelection->m_selection))
  496. {
  497. auto edgeHandle = Api::EdgeVertexHandles(*mesh, edgeSelection->GetHandle());
  498. m_whiteBoxSelection->m_vertexHandles = Api::VertexHandles(edgeHandle.cbegin(), edgeHandle.cend());
  499. m_whiteBoxSelection->m_vertexPositions = Api::VertexPositions(*mesh, m_whiteBoxSelection->m_vertexHandles);
  500. m_whiteBoxSelection->m_localPosition = Api::EdgeMidpoint(*mesh, edgeSelection->GetHandle());
  501. }
  502. else if (auto vertexSelection = AZStd::get_if<VertexIntersection>(&m_whiteBoxSelection->m_selection))
  503. {
  504. m_whiteBoxSelection->m_vertexHandles = Api::VertexHandles({ vertexSelection->GetHandle() });
  505. m_whiteBoxSelection->m_vertexPositions = Api::VertexPositions(*mesh, m_whiteBoxSelection->m_vertexHandles);
  506. m_whiteBoxSelection->m_localPosition = Api::VertexPosition(*mesh, vertexSelection->GetHandle());
  507. }
  508. m_whiteBoxSelection->m_localRotation = AZ::Quaternion::CreateIdentity();
  509. }
  510. void TransformMode::CreateTranslationManipulators()
  511. {
  512. if (!m_whiteBoxSelection)
  513. {
  514. return;
  515. }
  516. AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
  517. AZ::TransformBus::EventResult(worldTransform, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  518. AZStd::shared_ptr<AzToolsFramework::TranslationManipulators> translationManipulators =
  519. AZStd::make_shared<AzToolsFramework::TranslationManipulators>(
  520. AzToolsFramework::TranslationManipulators::Dimensions::Three, worldTransform, AZ::Vector3::CreateOne());
  521. translationManipulators->SetLineBoundWidth(AzToolsFramework::ManipulatorLineBoundWidth());
  522. translationManipulators->AddEntityComponentIdPair(m_entityComponentIdPair);
  523. AzToolsFramework::ConfigureTranslationManipulatorAppearance3d(translationManipulators.get());
  524. WhiteBoxMesh* whiteBox = nullptr;
  525. EditorWhiteBoxComponentRequestBus::EventResult(
  526. whiteBox, m_entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  527. UpdateTransformHandles(whiteBox);
  528. translationManipulators->SetLocalPosition(m_whiteBoxSelection->m_localPosition);
  529. auto mouseMoveHandlerFn = [entityComponentIdPair = m_entityComponentIdPair,
  530. transformSelection = m_whiteBoxSelection,
  531. currentManipulator = AZStd::weak_ptr<AzToolsFramework::TranslationManipulators>(translationManipulators)](const auto& action)
  532. {
  533. WhiteBoxMesh* whiteBox = nullptr;
  534. EditorWhiteBoxComponentRequestBus::EventResult(
  535. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  536. size_t vertexIndex = 0;
  537. for (const Api::VertexHandle& vertexHandle : transformSelection->m_vertexHandles)
  538. {
  539. const AZ::Vector3 vertexPosition = transformSelection->m_vertexPositions[vertexIndex++] + action.LocalPositionOffset();
  540. Api::SetVertexPosition(*whiteBox, vertexHandle, vertexPosition);
  541. }
  542. if (auto manipulator = currentManipulator.lock())
  543. {
  544. manipulator->SetLocalPosition(transformSelection->m_localPosition + action.LocalPositionOffset());
  545. }
  546. Api::CalculateNormals(*whiteBox);
  547. Api::CalculatePlanarUVs(*whiteBox);
  548. EditorWhiteBoxComponentNotificationBus::Event(
  549. entityComponentIdPair, &EditorWhiteBoxComponentNotificationBus::Events::OnWhiteBoxMeshModified);
  550. };
  551. auto mouseUpHandlerFn = [mouseMoveHandlerFn, entityComponentIdPair = m_entityComponentIdPair,
  552. transformSelection = m_whiteBoxSelection,
  553. currentManipulator = AZStd::weak_ptr<AzToolsFramework::TranslationManipulators>(
  554. translationManipulators)](const auto& action)
  555. {
  556. WhiteBoxMesh* whiteBox = nullptr;
  557. EditorWhiteBoxComponentRequestBus::EventResult(
  558. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  559. mouseMoveHandlerFn(action);
  560. transformSelection->m_vertexPositions = Api::VertexPositions(*whiteBox, transformSelection->m_vertexHandles);
  561. transformSelection->m_localPosition = transformSelection->m_localPosition + action.LocalPositionOffset();
  562. if (auto manipulator = currentManipulator.lock())
  563. {
  564. manipulator->SetLocalPosition(transformSelection->m_localPosition);
  565. }
  566. EditorWhiteBoxComponentRequestBus::Event(entityComponentIdPair, &EditorWhiteBoxComponentRequests::SerializeWhiteBox);
  567. };
  568. translationManipulators->InstallLinearManipulatorMouseMoveCallback(mouseMoveHandlerFn);
  569. translationManipulators->InstallPlanarManipulatorMouseMoveCallback(mouseMoveHandlerFn);
  570. translationManipulators->InstallSurfaceManipulatorMouseMoveCallback(mouseMoveHandlerFn);
  571. translationManipulators->InstallSurfaceManipulatorMouseUpCallback(mouseUpHandlerFn);
  572. translationManipulators->InstallPlanarManipulatorMouseUpCallback(mouseUpHandlerFn);
  573. translationManipulators->InstallLinearManipulatorMouseUpCallback(mouseUpHandlerFn);
  574. translationManipulators->Register(AzToolsFramework::g_mainManipulatorManagerId);
  575. m_manipulator = AZStd::move(translationManipulators);
  576. }
  577. void TransformMode::CreateRotationManipulators()
  578. {
  579. if (!m_whiteBoxSelection)
  580. {
  581. return;
  582. }
  583. WhiteBoxMesh* whiteBox = nullptr;
  584. EditorWhiteBoxComponentRequestBus::EventResult(
  585. whiteBox, m_entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  586. AZ::Transform worldTranform = AZ::Transform::CreateIdentity();
  587. AZ::TransformBus::EventResult(worldTranform, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  588. AZStd::shared_ptr<AzToolsFramework::RotationManipulators> rotationManipulators =
  589. AZStd::make_shared<AzToolsFramework::RotationManipulators>(worldTranform);
  590. rotationManipulators->SetCircleBoundWidth(AzToolsFramework::ManipulatorCicleBoundWidth());
  591. rotationManipulators->AddEntityComponentIdPair(m_entityComponentIdPair);
  592. UpdateTransformHandles(whiteBox);
  593. rotationManipulators->SetLocalPosition(m_whiteBoxSelection->m_localPosition);
  594. rotationManipulators->SetLocalOrientation(AZ::Quaternion::CreateIdentity());
  595. rotationManipulators->SetLocalAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
  596. rotationManipulators->ConfigureView(
  597. AzToolsFramework::RotationManipulatorRadius(),
  598. AzFramework::ViewportColors::XAxisColor,
  599. AzFramework::ViewportColors::YAxisColor,
  600. AzFramework::ViewportColors::ZAxisColor);
  601. auto mouseMoveHandlerFn = [entityComponentIdPair = m_entityComponentIdPair,
  602. transformSelection = m_whiteBoxSelection,
  603. currentManipulator = AZStd::weak_ptr<AzToolsFramework::RotationManipulators>(rotationManipulators)](
  604. const AzToolsFramework::AngularManipulator::Action& action)
  605. {
  606. WhiteBoxMesh* whiteBox = nullptr;
  607. EditorWhiteBoxComponentRequestBus::EventResult(
  608. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  609. size_t vertexIndex = 0;
  610. for (const Api::VertexHandle& vertexHandle : transformSelection->m_vertexHandles)
  611. {
  612. const AZ::Vector3 vertexPosition =
  613. (action.LocalOrientation() * transformSelection->m_localRotation.GetInverseFull())
  614. .TransformVector(transformSelection->m_vertexPositions[vertexIndex++] - transformSelection->m_localPosition) +
  615. transformSelection->m_localPosition;
  616. Api::SetVertexPosition(*whiteBox, vertexHandle, vertexPosition);
  617. }
  618. if (auto manipulator = currentManipulator.lock())
  619. {
  620. manipulator->SetLocalOrientation(action.LocalOrientation());
  621. }
  622. Api::CalculateNormals(*whiteBox);
  623. Api::CalculatePlanarUVs(*whiteBox);
  624. EditorWhiteBoxComponentNotificationBus::Event(
  625. entityComponentIdPair, &EditorWhiteBoxComponentNotificationBus::Events::OnWhiteBoxMeshModified);
  626. };
  627. rotationManipulators->InstallMouseMoveCallback(mouseMoveHandlerFn);
  628. rotationManipulators->InstallLeftMouseUpCallback(
  629. [mouseMoveHandlerFn, entityComponentIdPair = m_entityComponentIdPair,
  630. transformSelection = m_whiteBoxSelection,
  631. currentManipulator = AZStd::weak_ptr<AzToolsFramework::RotationManipulators>(rotationManipulators)](
  632. const AzToolsFramework::AngularManipulator::Action& action)
  633. {
  634. WhiteBoxMesh* whiteBox = nullptr;
  635. EditorWhiteBoxComponentRequestBus::EventResult(
  636. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  637. mouseMoveHandlerFn(action);
  638. transformSelection->m_vertexPositions = Api::VertexPositions(*whiteBox, transformSelection->m_vertexHandles);
  639. transformSelection->m_localRotation = action.LocalOrientation();
  640. if (auto manipulator = currentManipulator.lock())
  641. {
  642. manipulator->SetLocalOrientation(transformSelection->m_localRotation);
  643. }
  644. EditorWhiteBoxComponentRequestBus::Event(entityComponentIdPair, &EditorWhiteBoxComponentRequests::SerializeWhiteBox);
  645. });
  646. rotationManipulators->Register(AzToolsFramework::g_mainManipulatorManagerId);
  647. m_manipulator = AZStd::move(rotationManipulators);
  648. }
  649. void TransformMode::CreateScaleManipulators()
  650. {
  651. if (!m_whiteBoxSelection)
  652. {
  653. return;
  654. }
  655. WhiteBoxMesh* whiteBox = nullptr;
  656. EditorWhiteBoxComponentRequestBus::EventResult(
  657. whiteBox, m_entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  658. AZ::Transform worldTranform = AZ::Transform::CreateIdentity();
  659. AZ::TransformBus::EventResult(worldTranform, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  660. AZStd::shared_ptr<AzToolsFramework::ScaleManipulators> scaleManipulators =
  661. AZStd::make_shared<AzToolsFramework::ScaleManipulators>(worldTranform);
  662. scaleManipulators->SetLineBoundWidth(AzToolsFramework::ManipulatorLineBoundWidth());
  663. scaleManipulators->AddEntityComponentIdPair(m_entityComponentIdPair);
  664. scaleManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
  665. scaleManipulators->ConfigureView(
  666. AzToolsFramework::LinearManipulatorAxisLength(),
  667. AzFramework::ViewportColors::XAxisColor,
  668. AzFramework::ViewportColors::YAxisColor,
  669. AzFramework::ViewportColors::ZAxisColor);
  670. UpdateTransformHandles(whiteBox);
  671. scaleManipulators->SetLocalPosition(m_whiteBoxSelection->m_localPosition);
  672. enum class ScaleType
  673. {
  674. Uniform,
  675. NonUniform
  676. };
  677. auto mouseMoveHandlerFn =
  678. [entityComponentIdPair = m_entityComponentIdPair,
  679. transformSelection = m_whiteBoxSelection](const auto& action, ScaleType scaleType)
  680. {
  681. WhiteBoxMesh* whiteBox = nullptr;
  682. EditorWhiteBoxComponentRequestBus::EventResult(
  683. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  684. size_t vertexIndex = 0;
  685. for (const Api::VertexHandle& vertexHandle : transformSelection->m_vertexHandles)
  686. {
  687. const AZ::Vector3 vertexLocalPosition =
  688. (transformSelection->m_vertexPositions[vertexIndex++] - transformSelection->m_localPosition);
  689. const AZ::Vector3 scale = [&action, &scaleType]
  690. {
  691. switch (scaleType)
  692. {
  693. case ScaleType::Uniform:
  694. return AZ::Vector3(action.LocalScaleOffset().GetZ());
  695. case ScaleType::NonUniform:
  696. return action.LocalScaleOffset();
  697. default:
  698. break;
  699. }
  700. return AZ::Vector3();
  701. }();
  702. const AZ::Vector3 manipulatorScale = AZ::Vector3::CreateOne() + (action.m_start.m_sign * scale);
  703. const AZ::Vector3 vertexPosition = (vertexLocalPosition * manipulatorScale) + transformSelection->m_localPosition;
  704. Api::SetVertexPosition(*whiteBox, vertexHandle, vertexPosition);
  705. }
  706. Api::CalculateNormals(*whiteBox);
  707. Api::CalculatePlanarUVs(*whiteBox);
  708. EditorWhiteBoxComponentNotificationBus::Event(
  709. entityComponentIdPair, &EditorWhiteBoxComponentNotificationBus::Events::OnWhiteBoxMeshModified);
  710. };
  711. auto mouseUpHandlerFn =
  712. [mouseMoveHandlerFn, entityComponentIdPair = m_entityComponentIdPair,
  713. transformSelection = m_whiteBoxSelection](const auto& action, ScaleType scaleType)
  714. {
  715. WhiteBoxMesh* whiteBox = nullptr;
  716. EditorWhiteBoxComponentRequestBus::EventResult(
  717. whiteBox, entityComponentIdPair, &EditorWhiteBoxComponentRequests::GetWhiteBoxMesh);
  718. mouseMoveHandlerFn(action, scaleType);
  719. transformSelection->m_vertexPositions = Api::VertexPositions(*whiteBox, transformSelection->m_vertexHandles);
  720. EditorWhiteBoxComponentRequestBus::Event(entityComponentIdPair, &EditorWhiteBoxComponentRequests::SerializeWhiteBox);
  721. };
  722. scaleManipulators->InstallAxisMouseMoveCallback([mouseMoveHandlerFn](const auto& action)
  723. {
  724. return mouseMoveHandlerFn(action, ScaleType::NonUniform);
  725. });
  726. scaleManipulators->InstallAxisLeftMouseUpCallback([mouseUpHandlerFn](const auto& action)
  727. {
  728. return mouseUpHandlerFn(action, ScaleType::NonUniform);
  729. });
  730. scaleManipulators->InstallUniformMouseMoveCallback([mouseMoveHandlerFn](const auto& action)
  731. {
  732. return mouseMoveHandlerFn(action, ScaleType::Uniform);
  733. });
  734. scaleManipulators->InstallUniformLeftMouseUpCallback([mouseUpHandlerFn](const auto& action)
  735. {
  736. return mouseUpHandlerFn(action, ScaleType::Uniform);
  737. });
  738. scaleManipulators->Register(AzToolsFramework::g_mainManipulatorManagerId);
  739. m_manipulator = AZStd::move(scaleManipulators);
  740. }
  741. } // namespace WhiteBox