3
0

ImGuiManager.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  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 "ImGuiManager.h"
  9. #include <ImGuiContextScope.h>
  10. #include <AzCore/PlatformIncl.h>
  11. #include <AzCore/Debug/Profiler.h>
  12. #ifdef IMGUI_ENABLED
  13. #include <AzCore/Console/IConsole.h>
  14. #include <AzCore/Interface/Interface.h>
  15. #include <AzCore/Jobs/Algorithms.h>
  16. #include <AzCore/Jobs/JobCompletion.h>
  17. #include <AzCore/Jobs/JobFunction.h>
  18. #include <AzCore/Component/ComponentApplicationBus.h>
  19. #include <AzCore/std/containers/fixed_unordered_map.h>
  20. #include <AzCore/Time/ITime.h>
  21. #include <AzFramework/Input/Buses/Requests/InputTextEntryRequestBus.h>
  22. #include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
  23. #include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
  24. #include <AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h>
  25. #include <AzFramework/Input/Devices/Touch/InputDeviceTouch.h>
  26. #include <AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.h>
  27. #include <AzFramework/Viewport/ViewportBus.h>
  28. #include <IConsole.h>
  29. #include <imgui/imgui_internal.h>
  30. #include <ISystem.h>
  31. #include <sstream>
  32. #include <string>
  33. using namespace AzFramework;
  34. using namespace ImGui;
  35. // Wheel Delta const value.
  36. static const constexpr uint32_t IMGUI_WHEEL_DELTA = 120; // From WinUser.h, for Linux
  37. // Typedef and local static map to hold LyInput->ImGui Nav mappings ( filled up in Initialize() )
  38. using LyButtonImGuiNavIndexPair = AZStd::pair<AzFramework::InputChannelId, ImGuiNavInput_>;
  39. using LyButtonImGuiNavIndexMap = AZStd::fixed_unordered_map<AzFramework::InputChannelId, ImGuiNavInput_, 11, 32>;
  40. static LyButtonImGuiNavIndexMap s_lyInputToImGuiNavIndexMap;
  41. AZ_DEFINE_BUDGET(ImGui);
  42. /**
  43. An anonymous namespace containing helper functions for interoperating with AzFrameworkInput.
  44. */
  45. namespace
  46. {
  47. /**
  48. Utility function to map an AzFrameworkInput device key to its integer index.
  49. @param inputChannelId the ID for an AzFrameworkInput device key.
  50. @return the index of the indicated key, or -1 if not found.
  51. */
  52. unsigned int GetAzKeyIndex(const InputChannelId& inputChannelId)
  53. {
  54. const auto& keys = InputDeviceKeyboard::Key::All;
  55. const auto& it = AZStd::find(keys.cbegin(), keys.cend(), inputChannelId);
  56. return it != keys.cend() ? static_cast<unsigned int>(it - keys.cbegin()) : UINT_MAX;
  57. }
  58. /**
  59. Utility function to map an AzFrameworkInput mouse device button to its integer index.
  60. @param inputChannelId the ID for an AzFrameworkInput mouse device button.
  61. @return the index of the indicated button, or -1 if not found.
  62. */
  63. unsigned int GetAzMouseButtonIndex(const InputChannelId& inputChannelId)
  64. {
  65. const auto& buttons = InputDeviceMouse::Button::All;
  66. const auto& it = AZStd::find(buttons.cbegin(), buttons.cend(), inputChannelId);
  67. return it != buttons.cend() ? static_cast<unsigned int>(it - buttons.cbegin()) : UINT_MAX;
  68. }
  69. /**
  70. Utility function to map an AzFrameworkInput touch input to its integer index.
  71. @param inputChannelId the ID for an AzFrameworkInput touch input.
  72. @return the index of the indicated touch, or -1 if not found.
  73. */
  74. unsigned int GetAzTouchIndex(const InputChannelId& inputChannelId)
  75. {
  76. const auto& touches = InputDeviceTouch::Touch::All;
  77. const auto& it = AZStd::find(touches.cbegin(), touches.cend(), inputChannelId);
  78. return it != touches.cend() ? static_cast<unsigned int>(it - touches.cbegin()) : UINT_MAX;
  79. }
  80. }
  81. void ImGuiManager::Initialize()
  82. {
  83. // Register for Buses
  84. ImGuiManagerBus::Handler::BusConnect();
  85. // Register for Input Notifications
  86. InputChannelEventListener::Connect();
  87. InputTextEventListener::Connect();
  88. // Dynamically Load ImGui
  89. #if defined(LOAD_IMGUI_LIB_DYNAMICALLY) && !defined(AZ_MONOLITHIC_BUILD)
  90. AZ::OSString imgGuiLibPath = "imguilib";
  91. // Let the application process the path
  92. AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::ResolveModulePath, imgGuiLibPath);
  93. m_imgSharedLib = AZ::DynamicModuleHandle::Create(imgGuiLibPath.c_str());
  94. if (!m_imgSharedLib->Load())
  95. {
  96. AZ_Warning("ImGuiManager", false, "%s %s", __func__, "Unable to load " AZ_DYNAMIC_LIBRARY_PREFIX "imguilib" AZ_DYNAMIC_LIBRARY_EXTENSION "-- Skipping ImGui Initialization.");
  97. return;
  98. }
  99. #endif // defined(LOAD_IMGUI_LIB_DYNAMICALLY) && !defined(AZ_MONOLITHIC_BUILD)
  100. // Create ImGui Context
  101. m_imguiContext = ImGui::CreateContext();
  102. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  103. // Set config file
  104. ImGuiIO& io = ImGui::GetIO();
  105. #if defined(IMGUI_DISABLE_AUTOMATIC_INI_SAVING_LOADING)
  106. io.IniFilename = nullptr;
  107. #endif
  108. // Enable Nav Keyboard by default and allow
  109. io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  110. io.ConfigFlags |= ImGuiConfigFlags_NavEnableSetMousePos;
  111. // Config Keyboard Mapping keys.
  112. io.KeyMap[ImGuiKey_Tab] = GetAzKeyIndex(InputDeviceKeyboard::Key::EditTab);
  113. io.KeyMap[ImGuiKey_LeftArrow] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationArrowLeft);
  114. io.KeyMap[ImGuiKey_RightArrow] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationArrowRight);
  115. io.KeyMap[ImGuiKey_UpArrow] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationArrowUp);
  116. io.KeyMap[ImGuiKey_DownArrow] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationArrowDown);
  117. io.KeyMap[ImGuiKey_PageUp] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationPageUp);
  118. io.KeyMap[ImGuiKey_PageDown] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationPageDown);
  119. io.KeyMap[ImGuiKey_Home] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationHome);
  120. io.KeyMap[ImGuiKey_End] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationEnd);
  121. io.KeyMap[ImGuiKey_Insert] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationInsert);
  122. io.KeyMap[ImGuiKey_Delete] = GetAzKeyIndex(InputDeviceKeyboard::Key::NavigationDelete);
  123. io.KeyMap[ImGuiKey_Backspace] = GetAzKeyIndex(InputDeviceKeyboard::Key::EditBackspace);
  124. io.KeyMap[ImGuiKey_Space] = GetAzKeyIndex(InputDeviceKeyboard::Key::EditSpace);
  125. io.KeyMap[ImGuiKey_Enter] = GetAzKeyIndex(InputDeviceKeyboard::Key::EditEnter);
  126. io.KeyMap[ImGuiKey_Escape] = GetAzKeyIndex(InputDeviceKeyboard::Key::Escape);
  127. io.KeyMap[ImGuiKey_A] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericA);
  128. io.KeyMap[ImGuiKey_C] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericC);
  129. io.KeyMap[ImGuiKey_V] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericV);
  130. io.KeyMap[ImGuiKey_X] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericX);
  131. io.KeyMap[ImGuiKey_Y] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericY);
  132. io.KeyMap[ImGuiKey_Z] = GetAzKeyIndex(InputDeviceKeyboard::Key::AlphanumericZ);
  133. // Initialize controller button mapping
  134. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::A, ImGuiNavInput_Activate));
  135. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::B, ImGuiNavInput_Cancel));
  136. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::X, ImGuiNavInput_Menu));
  137. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::Y, ImGuiNavInput_Input));
  138. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::DU, ImGuiNavInput_DpadUp));
  139. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::DD, ImGuiNavInput_DpadDown));
  140. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::DL, ImGuiNavInput_DpadLeft));
  141. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::DR, ImGuiNavInput_DpadRight));
  142. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::R1, ImGuiNavInput_FocusNext));
  143. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Button::L1, ImGuiNavInput_FocusPrev));
  144. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Trigger::L2, ImGuiNavInput_TweakSlow));
  145. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::Trigger::R2, ImGuiNavInput_TweakFast));
  146. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LU, ImGuiNavInput_LStickUp));
  147. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LD, ImGuiNavInput_LStickDown));
  148. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LL, ImGuiNavInput_LStickLeft));
  149. s_lyInputToImGuiNavIndexMap.insert(LyButtonImGuiNavIndexPair(InputDeviceGamepad::ThumbStickDirection::LR, ImGuiNavInput_LStickRight));
  150. // Set the initial Display Size (gets updated each frame anyway)
  151. io.DisplaySize.x = 1920;
  152. io.DisplaySize.y = 1080;
  153. // Create a default font
  154. io.Fonts->AddFontDefault();
  155. io.Fonts->Build();
  156. // Broadcast ImGui Ready to Listeners
  157. ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnImGuiInitialize);
  158. m_button1Pressed = m_button2Pressed = false;
  159. m_menuBarStatusChanged = false;
  160. // See if a hardware mouse device is connected on startup, we will use it to help determine if we should draw the mouse cursor and turn on controller support by default if one is not found.
  161. // Future work here could include responding to the mouse being connected and disconnected at run-time, but this is fine for now.
  162. const AzFramework::InputDevice* mouseDevice = AzFramework::InputDeviceRequests::FindInputDevice(AzFramework::InputDeviceMouse::Id);
  163. m_hardwardeMouseConnected = mouseDevice && mouseDevice->IsConnected();
  164. AZ::Interface<ImGui::IImGuiManager>::Register(this);
  165. }
  166. void ImGuiManager::Shutdown()
  167. {
  168. AZ::Interface<ImGui::IImGuiManager>::Unregister(this);
  169. if (!gEnv)
  170. {
  171. AZ_Warning("ImGuiManager", false, "%s %s", __func__, "gEnv Invalid -- Skipping ImGui Shutdown.");
  172. return;
  173. }
  174. #if defined(LOAD_IMGUI_LIB_DYNAMICALLY) && !defined(AZ_MONOLITHIC_BUILD)
  175. if (m_imgSharedLib->IsLoaded())
  176. {
  177. m_imgSharedLib->Unload();
  178. }
  179. #endif
  180. // Unregister from Buses
  181. ImGuiManagerBus::Handler::BusDisconnect();
  182. InputChannelEventListener::Disconnect();
  183. InputTextEventListener::Disconnect();
  184. AzFramework::WindowNotificationBus::Handler::BusDisconnect();
  185. // Finally, destroy the ImGui Context.
  186. ImGui::DestroyContext(m_imguiContext);
  187. }
  188. void ImGui::ImGuiManager::OverrideRenderWindowSize(uint32_t width, uint32_t height)
  189. {
  190. m_windowSize.m_width = width;
  191. m_windowSize.m_height = height;
  192. m_overridingWindowSize = true;
  193. // Don't listen for window updates if our window size is being overridden
  194. AzFramework::WindowNotificationBus::Handler::BusDisconnect();
  195. }
  196. void ImGui::ImGuiManager::RestoreRenderWindowSizeToDefault()
  197. {
  198. m_overridingWindowSize = false;
  199. InitWindowSize();
  200. }
  201. void ImGui::ImGuiManager::SetDpiScalingFactor(float dpiScalingFactor)
  202. {
  203. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  204. ImGuiIO& io = ImGui::GetIO();
  205. // Set the global font scale to size our UI to the scaling factor
  206. // Note: Currently we use the default, 13px fixed-size IMGUI font, so this can get somewhat blurry
  207. io.FontGlobalScale = dpiScalingFactor;
  208. }
  209. float ImGui::ImGuiManager::GetDpiScalingFactor() const
  210. {
  211. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  212. ImGuiIO& io = ImGui::GetIO();
  213. return io.FontGlobalScale;
  214. }
  215. ImDrawData* ImGui::ImGuiManager::GetImguiDrawData()
  216. {
  217. AZ_PROFILE_FUNCTION(ImGui);
  218. if (m_clientMenuBarState == DisplayState::Hidden)
  219. {
  220. // the first frame that this is true means that it has been deactivated, the following condtional is to avoid
  221. // continuous bus notifications
  222. if (m_imGuiBroadcastState.m_deactivationBroadcastStatus == ImGuiStateBroadcast::NotBroadcast)
  223. {
  224. AzFramework::ViewportImGuiNotificationBus::Broadcast(&AzFramework::ViewportImGuiNotificationBus::Events::OnImGuiDeactivated);
  225. m_imGuiBroadcastState.m_deactivationBroadcastStatus = ImGuiStateBroadcast::Broadcast;
  226. // reset the following state to ActivationNotBroadcasted so when ImGui is first activated,
  227. // it sends the activation bus notification
  228. m_imGuiBroadcastState.m_activationBroadcastStatus = ImGuiStateBroadcast::NotBroadcast;
  229. }
  230. return nullptr;
  231. }
  232. else if (auto* console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
  233. {
  234. int consoleDeactivated = 0;
  235. console->GetCvarValue("sys_DeactivateConsole", consoleDeactivated);
  236. if (consoleDeactivated != 0)
  237. {
  238. ToggleToImGuiVisibleState(DisplayState::Hidden);
  239. return nullptr;
  240. }
  241. }
  242. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  243. // Update Display Size
  244. ImGuiIO& io = ImGui::GetIO();
  245. io.DisplaySize = m_lastRenderResolution;
  246. if (m_clientMenuBarState == DisplayState::Visible)
  247. {
  248. if (IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Mouse))
  249. {
  250. // Update Mouse Position from Stick Position
  251. m_controllerMousePosition[0] = AZ::GetClamp(m_controllerMousePosition[0] + ((io.NavInputs[ImGuiNavInput_LStickRight] - io.NavInputs[ImGuiNavInput_LStickLeft]) * m_controllerMouseSensitivity), 0.0f, m_renderResolution.x);
  252. m_controllerMousePosition[1] = AZ::GetClamp(m_controllerMousePosition[1] + ((io.NavInputs[ImGuiNavInput_LStickDown] - io.NavInputs[ImGuiNavInput_LStickUp]) * m_controllerMouseSensitivity), 0.0f, m_renderResolution.y);
  253. io.MousePos.x = m_controllerMousePosition[0];
  254. io.MousePos.y = m_controllerMousePosition[1];
  255. io.MouseDown[0] = (io.NavInputs[ImGuiNavInput_Activate] > 0.1f);
  256. io.MouseDown[1] = (io.NavInputs[ImGuiNavInput_Cancel] > 0.1f);
  257. }
  258. else if (m_useLastPrimaryTouchPosition)
  259. {
  260. io.MousePos.x = m_lastPrimaryTouchPosition[0];
  261. io.MousePos.y = m_lastPrimaryTouchPosition[1];
  262. m_controllerMousePosition[0] = io.MousePos.x;
  263. m_controllerMousePosition[1] = io.MousePos.y;
  264. m_useLastPrimaryTouchPosition = false;
  265. }
  266. else
  267. {
  268. AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero();
  269. InputSystemCursorRequestBus::EventResult(
  270. systemCursorPositionNormalized,
  271. InputDeviceMouse::Id,
  272. &InputSystemCursorRequests::GetSystemCursorPositionNormalized);
  273. io.MousePos.x = systemCursorPositionNormalized.GetX() * m_lastRenderResolution.x;
  274. io.MousePos.y = systemCursorPositionNormalized.GetY() * m_lastRenderResolution.y;
  275. m_controllerMousePosition[0] = io.MousePos.x;
  276. m_controllerMousePosition[1] = io.MousePos.y;
  277. }
  278. // Clear NavInputs if either the mouse is explicitly enabled, or if the contextual controller is explicitly disabled
  279. if (IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Mouse) || !IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Contextual))
  280. {
  281. memset(io.NavInputs, 0, sizeof(io.NavInputs));
  282. }
  283. }
  284. // If no item and no window is focused, we should artificially add focus to the Main Menu Bar, to save 1 step when navigating with a controller.
  285. if (!ImGui::IsAnyItemFocused() && !ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow))
  286. {
  287. ImGuiWindow* mainMenuWin = ImGui::FindWindowByName("##MainMenuBar");
  288. if (mainMenuWin)
  289. {
  290. ImGui::GetCurrentContext()->NavLayer = ImGuiNavLayer_Menu;
  291. ImGui::GetCurrentContext()->NavWindow = mainMenuWin;
  292. ImGui::NavInitWindow(mainMenuWin, true);
  293. }
  294. }
  295. // Show or hide the virtual keyboard as necessary
  296. bool hasTextEntryStarted = false;
  297. AzFramework::InputTextEntryRequestBus::EventResult(hasTextEntryStarted,
  298. AzFramework::InputDeviceVirtualKeyboard::Id,
  299. &AzFramework::InputTextEntryRequests::HasTextEntryStarted);
  300. if (io.WantTextInput && !hasTextEntryStarted)
  301. {
  302. AzFramework::InputTextEntryRequests::VirtualKeyboardOptions options;
  303. AzFramework::InputTextEntryRequestBus::Broadcast(&AzFramework::InputTextEntryRequests::TextEntryStart, options);
  304. }
  305. else if (!io.WantTextInput && hasTextEntryStarted)
  306. {
  307. AzFramework::InputTextEntryRequestBus::Broadcast(&AzFramework::InputTextEntryRequests::TextEntryStop);
  308. io.KeysDown[GetAzKeyIndex(InputDeviceKeyboard::Key::EditEnter)] = false;
  309. }
  310. // Start New Frame
  311. ImGui::NewFrame();
  312. // Advance ImGui by Elapsed Frame Time
  313. const AZ::TimeUs gameTickTimeUs = AZ::GetSimulationTickDeltaTimeUs();
  314. io.DeltaTime = AZ::TimeUsToSeconds(gameTickTimeUs);
  315. //// END FROM PREUPDATE
  316. AZ::u32 backBufferWidth = m_windowSize.m_width;
  317. AZ::u32 backBufferHeight = m_windowSize.m_height;
  318. // Find ImGui Render Resolution.
  319. int renderRes[2];
  320. switch (m_resolutionMode)
  321. {
  322. default:
  323. break;
  324. case ImGuiResolutionMode::LockToResolution:
  325. renderRes[0] = static_cast<int>(m_renderResolution.x);
  326. renderRes[1] = static_cast<int>(m_renderResolution.y);
  327. break;
  328. case ImGuiResolutionMode::MatchRenderResolution:
  329. renderRes[0] = backBufferWidth;
  330. renderRes[1] = backBufferHeight;
  331. break;
  332. case ImGuiResolutionMode::MatchToMaxRenderResolution:
  333. if (backBufferWidth <= static_cast<AZ::u32>(m_renderResolution.x))
  334. {
  335. renderRes[0] = backBufferWidth;
  336. renderRes[1] = backBufferHeight;
  337. }
  338. else
  339. {
  340. renderRes[0] = static_cast<int>(m_renderResolution.x);
  341. renderRes[1] = static_cast<int>(m_renderResolution.y);
  342. }
  343. break;
  344. }
  345. ImVec2 scaleRects( static_cast<float>(backBufferWidth) / static_cast<float>(renderRes[0]),
  346. static_cast<float>(backBufferHeight / static_cast<float>(renderRes[1])));
  347. // Save off the last render resolution for input
  348. m_lastRenderResolution.x = static_cast<float>(renderRes[0]);
  349. m_lastRenderResolution.y = static_cast<float>(renderRes[1]);
  350. // Trigger all listeners to run their updates
  351. ImGuiUpdateListenerBus::Broadcast(&ImGuiUpdateListenerBus::Events::OnImGuiUpdate);
  352. // Run imgui's internal render and retrieve resulting draw data
  353. ImGui::Render();
  354. ImDrawData* drawData = ImGui::GetDrawData();
  355. if (drawData != nullptr)
  356. {
  357. // Supply Scale Rects
  358. drawData->ScaleClipRects(scaleRects);
  359. }
  360. if (m_imGuiBroadcastState.m_activationBroadcastStatus == ImGuiStateBroadcast::NotBroadcast)
  361. {
  362. AzFramework::ViewportImGuiNotificationBus::Broadcast(&AzFramework::ViewportImGuiNotificationBus::Events::OnImGuiActivated);
  363. m_imGuiBroadcastState.m_activationBroadcastStatus = ImGuiStateBroadcast::Broadcast;
  364. m_imGuiBroadcastState.m_deactivationBroadcastStatus = ImGuiStateBroadcast::NotBroadcast;
  365. }
  366. // Clear the simulated backspace key
  367. if (m_simulateBackspaceKeyPressed)
  368. {
  369. io.KeysDown[GetAzKeyIndex(InputDeviceKeyboard::Key::EditBackspace)] = false;
  370. m_simulateBackspaceKeyPressed = false;
  371. }
  372. return drawData;
  373. }
  374. /**
  375. @return true if input should be consumed, false otherwise.
  376. */
  377. bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
  378. {
  379. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  380. ImGuiIO& io = ImGui::GetIO();
  381. const InputChannelId& inputChannelId = inputChannel.GetInputChannelId();
  382. const InputDeviceId& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
  383. bool consumeEvent = false;
  384. // Handle Keyboard Inputs
  385. if (InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
  386. {
  387. // Handle Keyboard Hotkeys
  388. if (inputChannel.IsStateBegan())
  389. {
  390. // Cycle through ImGui Menu Bar States on Home button press
  391. if (inputChannelId == InputDeviceKeyboard::Key::NavigationHome)
  392. {
  393. ToggleThroughImGuiVisibleState();
  394. }
  395. }
  396. // Handle Keyboard Modifier Keys
  397. if (inputChannelId == InputDeviceKeyboard::Key::ModifierShiftL
  398. || inputChannelId == InputDeviceKeyboard::Key::ModifierShiftR)
  399. {
  400. io.KeyShift = inputChannel.IsActive();
  401. }
  402. else if (inputChannelId == InputDeviceKeyboard::Key::ModifierAltL
  403. || inputChannelId == InputDeviceKeyboard::Key::ModifierAltR)
  404. {
  405. io.KeyAlt = inputChannel.IsActive();
  406. }
  407. else if (inputChannelId == InputDeviceKeyboard::Key::ModifierCtrlL
  408. || inputChannelId == InputDeviceKeyboard::Key::ModifierCtrlR)
  409. {
  410. io.KeyCtrl = inputChannel.IsActive();
  411. }
  412. // Set Keydown Flag in ImGui Keys Array
  413. const int keyIndex = GetAzKeyIndex(inputChannelId);
  414. if (0 <= keyIndex && keyIndex < AZ_ARRAY_SIZE(io.KeysDown))
  415. {
  416. io.KeysDown[keyIndex] = inputChannel.IsActive();
  417. }
  418. }
  419. // Handle Controller Inputs
  420. else if (InputDeviceGamepad::IsGamepadDevice(inputDeviceId))
  421. {
  422. // Only pipe in Controller Nav Inputs when at least 1 of the two controller modes are enabled.
  423. if (m_controllerModeFlags)
  424. {
  425. const auto lyButtonToImGuiNav = s_lyInputToImGuiNavIndexMap.find(inputChannelId);
  426. if (lyButtonToImGuiNav != s_lyInputToImGuiNavIndexMap.end())
  427. {
  428. const ImGuiNavInput_ imGuiNavInput = lyButtonToImGuiNav->second;
  429. io.NavInputs[imGuiNavInput] = inputChannel.GetValue();
  430. }
  431. }
  432. //Switch menu bar display only if two buttons are pressed at the same time
  433. if (inputChannelId == InputDeviceGamepad::Button::L1)
  434. {
  435. if (inputChannel.IsStateBegan())
  436. {
  437. m_button1Pressed = true;
  438. }
  439. if (inputChannel.IsStateEnded())
  440. {
  441. m_button1Pressed = false;
  442. m_menuBarStatusChanged = false;
  443. }
  444. }
  445. if (inputChannelId == InputDeviceGamepad::Button::R1)
  446. {
  447. if (inputChannel.IsStateBegan())
  448. {
  449. m_button2Pressed = true;
  450. }
  451. if (inputChannel.IsStateEnded())
  452. {
  453. m_button2Pressed = false;
  454. m_menuBarStatusChanged = false;
  455. }
  456. }
  457. if (!m_menuBarStatusChanged && m_button1Pressed && m_button2Pressed)
  458. {
  459. ToggleThroughImGuiVisibleState();
  460. }
  461. }
  462. // Handle Mouse Inputs
  463. else if (InputDeviceMouse::IsMouseDevice(inputDeviceId))
  464. {
  465. const int mouseButtonIndex = GetAzMouseButtonIndex(inputChannelId);
  466. if (0 <= mouseButtonIndex && mouseButtonIndex < AZ_ARRAY_SIZE(io.MouseDown))
  467. {
  468. io.MouseDown[mouseButtonIndex] = inputChannel.IsActive();
  469. // only consume the event during edit mode in the editor so the viewport doesn't also respond to it
  470. consumeEvent = gEnv->IsEditing() && io.WantCaptureMouse;
  471. }
  472. else if (inputChannelId == InputDeviceMouse::Movement::Z)
  473. {
  474. io.MouseWheel = inputChannel.GetValue() / static_cast<float>(IMGUI_WHEEL_DELTA);
  475. // only consume the event during edit mode in the editor so the viewport doesn't also respond to it
  476. consumeEvent = gEnv->IsEditing() && io.WantCaptureMouse;
  477. }
  478. }
  479. // Handle Touch Inputs
  480. else if (InputDeviceTouch::IsTouchDevice(inputDeviceId))
  481. {
  482. const int touchIndex = GetAzTouchIndex(inputChannelId);
  483. if (0 <= touchIndex && touchIndex < AZ_ARRAY_SIZE(io.MouseDown))
  484. {
  485. io.MouseDown[touchIndex] = inputChannel.IsActive();
  486. }
  487. if (touchIndex == 0)
  488. {
  489. const AzFramework::InputChannel::PositionData2D* positionData2D = inputChannel.GetCustomData<AzFramework::InputChannel::PositionData2D>();
  490. if (positionData2D)
  491. {
  492. m_lastPrimaryTouchPosition[0] = positionData2D->m_normalizedPosition.GetX() * m_lastRenderResolution.x;
  493. m_lastPrimaryTouchPosition[1] = positionData2D->m_normalizedPosition.GetY() * m_lastRenderResolution.y;
  494. m_useLastPrimaryTouchPosition = true;
  495. }
  496. }
  497. }
  498. // Handle Virtual Keyboard Inputs
  499. else if (InputDeviceVirtualKeyboard::IsVirtualKeyboardDevice(inputDeviceId))
  500. {
  501. if (inputChannelId == AzFramework::InputDeviceVirtualKeyboard::Command::EditEnter)
  502. {
  503. // Simulate the enter key being pressed
  504. io.KeysDown[GetAzKeyIndex(InputDeviceKeyboard::Key::EditEnter)] = true;
  505. }
  506. }
  507. if (m_clientMenuBarState == DisplayState::Visible)
  508. {
  509. // If we have the Discrete Input Mode Enabled.. then consume the input here.
  510. if (m_enableDiscreteInputMode)
  511. {
  512. return true;
  513. }
  514. return consumeEvent;
  515. }
  516. // don't allow event capturing when ImGui isn't active
  517. return false;
  518. }
  519. bool ImGuiManager::IsControllerSupportModeEnabled(ImGuiControllerModeFlags::FlagType controllerMode) const
  520. {
  521. return !!(m_controllerModeFlags & controllerMode);
  522. }
  523. void ImGuiManager::EnableControllerSupportMode(ImGuiControllerModeFlags::FlagType controllerMode, bool enable)
  524. {
  525. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  526. if (enable)
  527. {
  528. // Enable - Add flag by or'ing in.
  529. m_controllerModeFlags |= controllerMode;
  530. }
  531. else
  532. {
  533. // Disable - Remove flag by and'ing the flag inverse
  534. m_controllerModeFlags &= ~controllerMode;
  535. }
  536. const bool controllerMouseEnabled = IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Mouse);
  537. // Draw the ImGui Mouse cursor if either the hardware mouse is connected, or the controller mouse is enabled.
  538. ImGui::GetIO().MouseDrawCursor = m_hardwardeMouseConnected || controllerMouseEnabled;
  539. // Set or unset ImGui Config flags based on which modes are enabled.
  540. if (controllerMouseEnabled)
  541. {
  542. ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad;
  543. ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard;
  544. }
  545. else if (IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Contextual))
  546. {
  547. ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
  548. ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  549. }
  550. }
  551. bool ImGuiManager::OnInputTextEventFiltered(const AZStd::string& textUTF8)
  552. {
  553. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  554. ImGuiIO& io = ImGui::GetIO();
  555. io.AddInputCharactersUTF8(textUTF8.c_str());
  556. if (textUTF8 == "\b" && !io.KeysDown[GetAzKeyIndex(InputDeviceKeyboard::Key::EditBackspace)])
  557. {
  558. // Simulate the backspace key being pressed
  559. io.KeysDown[GetAzKeyIndex(InputDeviceKeyboard::Key::EditBackspace)] = true;
  560. m_simulateBackspaceKeyPressed = true;
  561. }
  562. return io.WantTextInput && m_clientMenuBarState == DisplayState::Visible;;
  563. }
  564. void ImGuiManager::ToggleToImGuiVisibleState(DisplayState state)
  565. {
  566. if (state != m_clientMenuBarState)
  567. {
  568. DisplayState initialState = m_clientMenuBarState;
  569. while (m_clientMenuBarState != state)
  570. {
  571. ToggleThroughImGuiVisibleState();
  572. // Prevent infinite loop if the Toggle function can't get to the desired state naturally
  573. if (m_clientMenuBarState == initialState)
  574. {
  575. AZ_Warning("ImGuiManager", false, "SetClientMenuBarState failed to naturally enter the reguested state");
  576. m_clientMenuBarState = state;
  577. break;
  578. }
  579. }
  580. }
  581. }
  582. void ImGuiManager::ToggleThroughImGuiVisibleState()
  583. {
  584. ImGui::ImGuiContextScope contextScope(m_imguiContext);
  585. switch (m_clientMenuBarState)
  586. {
  587. case DisplayState::Hidden:
  588. m_clientMenuBarState = DisplayState::Visible;
  589. if (gEnv->IsEditor() && !gEnv->IsEditorGameMode())
  590. {
  591. // The system cursor is visible so we don't need ImGui's cursor
  592. ImGui::GetIO().MouseDrawCursor = false;
  593. // Disable discrete input in edit mode because the user has to click in the viewport to navigate,
  594. // so there's no concern about ImGui mouse movements also navigating the camera.
  595. m_enableDiscreteInputMode = false;
  596. }
  597. else
  598. {
  599. // We're either in game launcher or in Editor game mode and the system cursor is hidden so we'll
  600. // show ImGui's cursor instead, but only if a mouse is available.
  601. ImGui::GetIO().MouseDrawCursor = m_hardwardeMouseConnected || IsControllerSupportModeEnabled(ImGuiControllerModeFlags::Mouse);
  602. // During gameplay, the mouse usually affects the camera, so we want the discrete mode to be available by default,
  603. // so the user can easily turn off gameplay input while interacting with ImGui.
  604. m_enableDiscreteInputMode = true;
  605. }
  606. // Fetch old cursor state
  607. AzFramework::InputSystemCursorRequestBus::EventResult(m_previousSystemCursorState,
  608. AzFramework::InputDeviceMouse::Id,
  609. &AzFramework::InputSystemCursorRequests::GetSystemCursorState);
  610. // Set new cursor state
  611. AzFramework::InputSystemCursorRequestBus::Event(AzFramework::InputDeviceMouse::Id,
  612. &AzFramework::InputSystemCursorRequests::SetSystemCursorState,
  613. AzFramework::SystemCursorState::UnconstrainedAndVisible);
  614. // Get window size if it wasn't initialized
  615. InitWindowSize();
  616. break;
  617. default:
  618. case DisplayState::Visible:
  619. m_clientMenuBarState = DisplayState::Hidden;
  620. // Avoid hiding the cursor when in the Editor and not in game mode
  621. const bool inGame = !gEnv->IsEditor() || gEnv->IsEditorGameMode();
  622. const bool cursorWasVisible = m_previousSystemCursorState == AzFramework::SystemCursorState::ConstrainedAndVisible ||
  623. m_previousSystemCursorState == AzFramework::SystemCursorState::UnconstrainedAndVisible;
  624. if (inGame || cursorWasVisible)
  625. {
  626. AzFramework::InputSystemCursorRequestBus::Event(AzFramework::InputDeviceMouse::Id,
  627. &AzFramework::InputSystemCursorRequests::SetSystemCursorState,
  628. m_previousSystemCursorState);
  629. }
  630. m_previousSystemCursorState = AzFramework::SystemCursorState::Unknown;
  631. break;
  632. }
  633. m_menuBarStatusChanged = true;
  634. m_setEnabledEvent.Signal(m_clientMenuBarState == DisplayState::Hidden);
  635. }
  636. void ImGuiManager::OnResolutionChanged(uint32_t width, uint32_t height)
  637. {
  638. m_windowSize.m_width = width;
  639. m_windowSize.m_height = height;
  640. }
  641. void ImGuiManager::InitWindowSize()
  642. {
  643. // We only need to initialize the window size by querying the window the first time.
  644. // After that we will get OnWindowResize notifications
  645. if (!m_overridingWindowSize && !AzFramework::WindowNotificationBus::Handler::BusIsConnected())
  646. {
  647. AzFramework::NativeWindowHandle windowHandle = nullptr;
  648. AzFramework::WindowSystemRequestBus::BroadcastResult(windowHandle, &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  649. if (windowHandle)
  650. {
  651. AzFramework::WindowRequestBus::EventResult(m_windowSize, windowHandle, &AzFramework::WindowRequestBus::Events::GetRenderResolution);
  652. AzFramework::WindowNotificationBus::Handler::BusConnect(windowHandle);
  653. }
  654. }
  655. }
  656. ////// IMGUI CVAR STUFF /////////
  657. namespace ImGuiCVARNames
  658. {
  659. static const char* s_imgui_AutoEnableComponents_Name = "imgui_AutoEnableComponents";
  660. static const char* s_imgui_DiscreteInputMode_Name = "imgui_DiscreteInputMode";
  661. static const char* s_imgui_EnableAssetExplorer_Name = "imgui_EnableAssetExplorer";
  662. static const char* s_imgui_EnableCameraMonitor_Name = "imgui_EnableCameraMonitor";
  663. static const char* s_imgui_EnableEntityOutliner_Name = "imgui_EnableEntityOutliner";
  664. static const char* s_imgui_EnableImGui_Name = "imgui_EnableImGui";
  665. static const char* s_imgui_EnableController_Name = "imgui_EnableController";
  666. static const char* s_imgui_EnableControllerMouse_Name = "imgui_EnableControllerMouse";
  667. static const char* s_imgui_ControllerMouseSensitivity_Name = "imgui_ControllerMouseSensitivity";
  668. }
  669. void OnAutoEnableComponentsCBFunc(ICVar* pArgs)
  670. {
  671. std::string token;
  672. std::istringstream tokenStream(pArgs->GetString());
  673. while (std::getline(tokenStream, token, ','))
  674. {
  675. AZStd::string enableSearchString = token.c_str();
  676. ImGui::ImGuiEntityOutlinerRequestBus::Broadcast(&ImGui::IImGuiEntityOutlinerRequests::AddAutoEnableSearchString, enableSearchString);
  677. }
  678. }
  679. void OnEnableEntityOutlinerCBFunc(ICVar* pArgs)
  680. {
  681. ImGui::ImGuiEntityOutlinerRequestBus::Broadcast(&ImGui::IImGuiEntityOutlinerRequests::SetEnabled, pArgs->GetIVal() != 0);
  682. }
  683. void OnEnableAssetExplorerCBFunc(ICVar* pArgs)
  684. {
  685. ImGui::ImGuiAssetExplorerRequestBus::Broadcast(&ImGui::IImGuiAssetExplorerRequests::SetEnabled, pArgs->GetIVal() != 0);
  686. }
  687. void OnEnableCameraMonitorCBFunc(ICVar* pArgs)
  688. {
  689. ImGui::ImGuiCameraMonitorRequestBus::Broadcast(&ImGui::IImGuiCameraMonitorRequests::SetEnabled, pArgs->GetIVal() != 0);
  690. }
  691. void OnShowImGuiCBFunc(ICVar* pArgs)
  692. {
  693. ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetDisplayState, pArgs->GetIVal() != 0 ? ImGui::DisplayState::Visible : ImGui::DisplayState::Hidden);
  694. }
  695. void OnDiscreteInputModeCBFunc(ICVar* pArgs)
  696. {
  697. ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetEnableDiscreteInputMode, pArgs->GetIVal() != 0 );
  698. }
  699. void OnEnableControllerCBFunc(ICVar* pArgs)
  700. {
  701. ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Contextual, (pArgs->GetIVal() != 0));
  702. }
  703. void OnEnableControllerMouseCBFunc(ICVar* pArgs)
  704. {
  705. ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Mouse, (pArgs->GetIVal() != 0));
  706. }
  707. void OnControllerMouseSensitivityCBFunc(ICVar* pArgs)
  708. {
  709. ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetControllerMouseSensitivity, pArgs->GetFVal());
  710. }
  711. void ImGuiManager::RegisterImGuiCVARs()
  712. {
  713. // These are already checked before we enter this function, but lets make double sure and prevent crashes.
  714. if (!gEnv || !gEnv->pConsole)
  715. {
  716. return;
  717. }
  718. // We should also just make sure we aren't registering these twice. Check by just checking the first one.
  719. if (gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableImGui_Name) != nullptr)
  720. {
  721. return;
  722. }
  723. // Register CVARs
  724. gEnv->pConsole->RegisterString(ImGuiCVARNames::s_imgui_AutoEnableComponents_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Components by search string, as they are added to the Scene. Comma delimited list."), OnAutoEnableComponentsCBFunc);
  725. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableImGui_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui on Startup"), OnShowImGuiCBFunc);
  726. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableEntityOutliner_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Entity Outliner on Startup"), OnEnableEntityOutlinerCBFunc);
  727. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableCameraMonitor_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Camera Monitor on Startup"), OnEnableCameraMonitorCBFunc);
  728. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableAssetExplorer_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Asset Explorer on Startup"), OnEnableAssetExplorerCBFunc);
  729. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_DiscreteInputMode_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Discrete Input Mode, adds a 2nd Visibility Mode, with the 1st having input going toward ImGui and the 2nd having input going toward the game. If not set, Input will go to both ImGui and the game when ImGui is enabled."), OnDiscreteInputModeCBFunc);
  730. // Enable the Contextual Controller support by default when the hardware mouse is not detected.
  731. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableController_Name, (m_hardwardeMouseConnected ? 0 : 1), VF_DEV_ONLY, CVARHELP("Enable ImGui Controller support. Default to Off on PC, On on Console."), OnEnableControllerCBFunc);
  732. gEnv->pConsole->RegisterInt(ImGuiCVARNames::s_imgui_EnableControllerMouse_Name, 0, VF_DEV_ONLY, CVARHELP("Enable ImGui Controller Mouse support. Default to Off on PC, On on Console."), OnEnableControllerMouseCBFunc);
  733. gEnv->pConsole->RegisterFloat(ImGuiCVARNames::s_imgui_ControllerMouseSensitivity_Name, 5.0f, VF_DEV_ONLY, CVARHELP("ImGui Controller Mouse Sensitivty. Frame Multiplier for stick mouse sensitivity"), OnControllerMouseSensitivityCBFunc);
  734. // Init CVARs to current values
  735. OnAutoEnableComponentsCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_AutoEnableComponents_Name));
  736. OnShowImGuiCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableImGui_Name));
  737. OnEnableAssetExplorerCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableAssetExplorer_Name));
  738. OnEnableCameraMonitorCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableCameraMonitor_Name));
  739. OnEnableEntityOutlinerCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableEntityOutliner_Name));
  740. OnDiscreteInputModeCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_DiscreteInputMode_Name));
  741. OnEnableControllerCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableController_Name));
  742. OnEnableControllerMouseCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_EnableControllerMouse_Name));
  743. OnControllerMouseSensitivityCBFunc(gEnv->pConsole->GetCVar(ImGuiCVARNames::s_imgui_ControllerMouseSensitivity_Name));
  744. }
  745. ////// IMGUI CVAR STUFF /////////
  746. void AddMenuItemHelper(bool& control, const char* show, const char* hide)
  747. {
  748. if (control)
  749. {
  750. if (ImGui::MenuItem(hide))
  751. {
  752. control = false;
  753. }
  754. }
  755. else if (ImGui::MenuItem(show))
  756. {
  757. control = true;
  758. }
  759. }
  760. #endif // ~IMGUI_ENABLED