Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

UI.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /*!
  2. * \file src/UI.cpp
  3. * \brief UI/Event Manager
  4. *
  5. * \author xythobuz
  6. */
  7. #include "imgui/imgui.h"
  8. #include "global.h"
  9. #include "Camera.h"
  10. #include "Console.h"
  11. #include "Game.h"
  12. #include "Log.h"
  13. #include "Menu.h"
  14. #include "Render.h"
  15. #include "RunTime.h"
  16. #include "SoundManager.h"
  17. #include "TextureManager.h"
  18. #include "World.h"
  19. #include "system/Sound.h"
  20. #include "system/Window.h"
  21. #include "utils/time.h"
  22. #include "UI.h"
  23. #include <glbinding/gl/gl.h>
  24. #include <glm/gtc/matrix_transform.hpp>
  25. Shader UI::imguiShader;
  26. bool UI::visible = false;
  27. unsigned int UI::fontTex;
  28. std::string UI::iniFilename;
  29. std::string UI::logFilename;
  30. bool UI::metaKeyIsActive = false;
  31. std::list<std::tuple<KeyboardButton, bool>> UI::keyboardEvents;
  32. std::list<std::tuple<unsigned int, unsigned int, KeyboardButton, bool>> UI::clickEvents;
  33. std::list<std::tuple<int, int, int, int>> UI::motionEvents;
  34. std::list<std::tuple<int, int>> UI::scrollEvents;
  35. void UI::setSize(glm::i32vec2 s) {
  36. ImGuiIO& io = ImGui::GetIO();
  37. io.DisplaySize = ImVec2(s.x, s.y);
  38. }
  39. int UI::initialize() {
  40. if (imguiShader.compile(imguiShaderVertex, imguiShaderFragment) < 0)
  41. return -1;
  42. if (imguiShader.addUniform("screen") < 0)
  43. return -2;
  44. if (imguiShader.addUniform("textureSampler") < 0)
  45. return -3;
  46. iniFilename = RunTime::getBaseDir() + "/imgui.ini";
  47. logFilename = RunTime::getBaseDir() + "/imgui_log.txt";
  48. ImGuiIO& io = ImGui::GetIO();
  49. io.DisplaySize = ImVec2(Window::getSize().x, Window::getSize().y);
  50. io.DeltaTime = 1.0f / 60.0f;
  51. io.IniFilename = iniFilename.c_str();
  52. io.LogFilename = logFilename.c_str();
  53. io.KeyMap[ImGuiKey_Tab] = tabKey;
  54. io.KeyMap[ImGuiKey_LeftArrow] = leftKey;
  55. io.KeyMap[ImGuiKey_RightArrow] = rightKey;
  56. io.KeyMap[ImGuiKey_UpArrow] = upKey;
  57. io.KeyMap[ImGuiKey_DownArrow] = downKey;
  58. io.KeyMap[ImGuiKey_Home] = homeKey;
  59. io.KeyMap[ImGuiKey_End] = endKey;
  60. io.KeyMap[ImGuiKey_Delete] = delKey;
  61. io.KeyMap[ImGuiKey_Backspace] = backspaceKey;
  62. io.KeyMap[ImGuiKey_Enter] = enterKey;
  63. io.KeyMap[ImGuiKey_Escape] = escapeKey;
  64. io.KeyMap[ImGuiKey_A] = aKey;
  65. io.KeyMap[ImGuiKey_C] = cKey;
  66. io.KeyMap[ImGuiKey_V] = vKey;
  67. io.KeyMap[ImGuiKey_X] = xKey;
  68. io.KeyMap[ImGuiKey_Y] = yKey;
  69. io.KeyMap[ImGuiKey_Z] = zKey;
  70. io.RenderDrawListsFn = UI::renderImGui;
  71. io.GetClipboardTextFn = Window::getClipboard;
  72. io.SetClipboardTextFn = Window::setClipboard;
  73. io.ImeSetInputScreenPosFn = Window::inputPositionCallback;
  74. // Load font texture
  75. //! \fixme allow loading other TTF fonts
  76. unsigned char* pixels;
  77. int width, height;
  78. io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
  79. fontTex = TextureManager::loadBufferSlot(pixels, width, height, ColorMode::RGBA, 32,
  80. TextureStorage::SYSTEM, -1, true);
  81. auto bm = TextureManager::getBufferManager(fontTex, TextureStorage::SYSTEM);
  82. io.Fonts->TexID = bm;
  83. // Set up OpenRaider style
  84. ImGuiStyle& style = ImGui::GetStyle();
  85. style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
  86. style.Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
  87. style.Colors[ImGuiCol_Border] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
  88. style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
  89. style.Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f);
  90. style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(1.00f, 0.40f, 0.40f, 0.45f);
  91. style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.65f, 0.50f, 0.50f, 0.55f);
  92. style.Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.70f, 1.00f, 0.45f);
  93. style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.65f, 1.00f, 0.20f);
  94. style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.65f, 1.00f, 0.15f);
  95. style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.65f, 1.00f, 0.30f);
  96. style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.65f, 1.00f, 0.40f);
  97. style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1.00f, 0.16f, 0.16f, 0.40f);
  98. style.Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
  99. style.Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
  100. style.Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
  101. style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(1.00f, 0.20f, 0.22f, 1.00f);
  102. style.Colors[ImGuiCol_Button] = ImVec4(1.00f, 0.20f, 0.20f, 0.60f);
  103. style.Colors[ImGuiCol_ButtonHovered] = ImVec4(1.00f, 0.20f, 0.18f, 1.00f);
  104. style.Colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
  105. style.Colors[ImGuiCol_Header] = ImVec4(0.21f, 0.54f, 1.00f, 0.45f);
  106. style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.22f, 0.56f, 1.00f, 0.80f);
  107. style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.00f, 0.31f, 1.00f, 1.00f);
  108. style.Colors[ImGuiCol_Column] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
  109. style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.60f, 0.40f, 0.40f, 1.00f);
  110. style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
  111. style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
  112. style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
  113. style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
  114. style.Colors[ImGuiCol_CloseButton] = ImVec4(0.21f, 0.56f, 1.00f, 0.50f);
  115. style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.21f, 0.32f, 1.00f, 0.60f);
  116. style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
  117. style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
  118. style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
  119. style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
  120. style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
  121. style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
  122. style.Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
  123. style.WindowPadding = ImVec2(2, 2);
  124. style.WindowRounding = 9;
  125. style.FramePadding = ImVec2(2, 1);
  126. style.ItemSpacing = ImVec2(2, 2);
  127. style.ItemInnerSpacing = ImVec2(1, 1);
  128. style.TouchExtraPadding = ImVec2(0, 0);
  129. style.IndentSpacing = 3;
  130. style.ScrollbarWidth = 10;
  131. return 0;
  132. }
  133. void UI::eventsFinished() {
  134. ImGuiIO& io = ImGui::GetIO();
  135. io.DisplaySize = ImVec2(Window::getSize().x, Window::getSize().y);
  136. static unsigned long lastTime = 0;
  137. io.DeltaTime = (systemTimerGet() - lastTime) / 1000.0f;
  138. lastTime = systemTimerGet();
  139. if (io.DeltaTime <= 0.0f)
  140. io.DeltaTime = 1.0f / 60.0f;
  141. ImGui::NewFrame();
  142. if (!(visible || Console::isVisible() || Menu::isVisible())) {
  143. while (!motionEvents.empty()) {
  144. auto i = motionEvents.front();
  145. Game::handleMouseMotion(std::get<0>(i), std::get<1>(i),
  146. std::get<2>(i), std::get<3>(i));
  147. motionEvents.pop_front();
  148. }
  149. }
  150. while (!keyboardEvents.empty()) {
  151. auto i = keyboardEvents.front();
  152. if (!(visible || Console::isVisible() || Menu::isVisible())) {
  153. for (int n = forwardAction; n < ActionEventCount; n++) {
  154. auto ae = static_cast<ActionEvents>(n);
  155. if (RunTime::getKeyBinding(ae) == std::get<0>(i))
  156. Game::handleAction(ae, !std::get<1>(i));
  157. }
  158. }
  159. if (std::get<1>(i)) {
  160. if ((!io.WantCaptureKeyboard) || (!(visible || Console::isVisible() || Menu::isVisible()))) {
  161. if (!metaKeyIsActive) {
  162. if (RunTime::getKeyBinding(debugAction) == std::get<0>(i)) {
  163. visible = !visible;
  164. }
  165. if (RunTime::getKeyBinding(consoleAction) == std::get<0>(i)) {
  166. Console::setVisible(!Console::isVisible());
  167. }
  168. if (RunTime::getKeyBinding(menuAction) == std::get<0>(i)) {
  169. Menu::setVisible(!Menu::isVisible());
  170. }
  171. }
  172. }
  173. }
  174. keyboardEvents.pop_front();
  175. }
  176. bool clicked = !clickEvents.empty();
  177. clickEvents.clear();
  178. motionEvents.clear();
  179. scrollEvents.clear();
  180. // Allow clicking into the game to hide debug UI
  181. if ((visible || Console::isVisible()) && ((!io.WantCaptureMouse) && clicked)) {
  182. visible = false;
  183. Console::setVisible(false);
  184. }
  185. if (Window::getTextInput() != (visible || Console::isVisible() || Menu::isVisible()))
  186. Window::setTextInput(visible || Console::isVisible() || Menu::isVisible());
  187. bool input = !(visible || Console::isVisible() || Menu::isVisible());
  188. if (Window::getMousegrab() != input)
  189. Window::setMousegrab(input);
  190. io.MouseWheel = 0;
  191. }
  192. void UI::display() {
  193. if (RunTime::getShowFPS() && (!Menu::isVisible())) {
  194. if (ImGui::Begin("Debug Overlay", nullptr, ImVec2(0, 0), -1.0f,
  195. ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize
  196. | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings
  197. | ImGuiWindowFlags_AlwaysAutoResize)) {
  198. #ifdef DEBUG
  199. ImGui::Text("%d FPS %lu CPF", RunTime::getFPS(), RunTime::getCallCount());
  200. #else
  201. ImGui::Text("%d FPS", RunTime::getFPS());
  202. #endif
  203. ImGui::Text("X: %.1f (%.2f)", Camera::getPosition().x, Camera::getRotation().x);
  204. ImGui::Text("Y: %.2f (%.2f)", Camera::getPosition().y, Camera::getRotation().y);
  205. ImGui::Text("Z: %.2f (%d)", Camera::getPosition().z, Camera::getRoom());
  206. auto window = ImGui::GetWindowSize();
  207. auto screen = Window::getSize();
  208. //ImGui::SetWindowPos(ImVec2(10, screen.y - window.y - 10));
  209. }
  210. ImGui::End();
  211. }
  212. if (Game::isLoaded())
  213. Camera::displayUI();
  214. Console::display();
  215. Menu::display();
  216. if (!visible) {
  217. ImGui::Render();
  218. return;
  219. }
  220. static bool showTestWindow = false;
  221. static bool showStyleWindow = false;
  222. if (ImGui::Begin("Engine", &visible, ImVec2(500, 600))) {
  223. Render::displayUI();
  224. RunTime::display();
  225. TextureManager::display();
  226. SoundManager::display();
  227. World::displayUI();
  228. if (ImGui::CollapsingHeader("Library Versions")) {
  229. ImGui::TextWrapped("%s", VERSION);
  230. ImGui::Separator();
  231. ImGui::TextWrapped("ImGui v%s", IMGUI_VERSION);
  232. ImGui::TextWrapped("%s", Window::getVersion(false).c_str());
  233. ImGui::TextWrapped("%s", Shader::getVersion(false).c_str());
  234. ImGui::TextWrapped("%s", Sound::getVersion(false).c_str());
  235. ImGui::TextWrapped("GLM v%d.%d.%d", (GLM_VERSION / 100),
  236. ((GLM_VERSION % 100) / 10), (GLM_VERSION % 10));
  237. ImGui::Separator();
  238. ImGui::TextWrapped("ImGui v%s", ImGui::GetVersion());
  239. ImGui::TextWrapped("%s", Window::getVersion(true).c_str());
  240. ImGui::TextWrapped("%s", Shader::getVersion(true).c_str());
  241. ImGui::TextWrapped("%s", Sound::getVersion(true).c_str());
  242. }
  243. if (ImGui::CollapsingHeader("ImGui/Debug UI Help")) {
  244. ImGui::ShowUserGuide();
  245. ImGui::Separator();
  246. if (ImGui::Button("Show/Hide Test Window")) {
  247. showTestWindow = !showTestWindow;
  248. }
  249. ImGui::SameLine();
  250. if (ImGui::Button("Show/Hide Style Editor")) {
  251. showStyleWindow = !showStyleWindow;
  252. }
  253. }
  254. if (ImGui::CollapsingHeader("ShaderTexture Test")) {
  255. static ShaderTexture* st = nullptr;
  256. static int index = 0;
  257. ImGui::SliderInt("SkeletalModel", &index, 0, World::sizeSkeletalModel() - 1);
  258. static glm::mat4 MVP(1.0f);
  259. static bool dirty = true, redraw = false;
  260. static float zoom = 1.0f;
  261. static float pos[3];
  262. static float rot[3];
  263. if (ImGui::SliderFloat3("Position", pos, -100.0f, 100.0f)) {
  264. //dirty = true;
  265. }
  266. if (ImGui::SliderFloat3("Rotation", rot, -6.0f, 6.0f)) {
  267. //dirty = true;
  268. }
  269. if (ImGui::SliderFloat("Zoom", &zoom, -1.0f, 2.0f)) {
  270. //dirty = true;
  271. }
  272. if (dirty) {
  273. static glm::mat4 projection = glm::perspective(45.0f, 1.0f, 0.1f, 2000.0f);
  274. glm::mat4 rotateX = glm::rotate(glm::mat4(1.0f), rot[0], glm::vec3(1.0f, 0.0f, 0.0f));
  275. glm::mat4 rotateY = glm::rotate(glm::mat4(1.0f), rot[1], glm::vec3(0.0f, 1.0f, 0.0f));
  276. glm::mat4 rotateZ = glm::rotate(glm::mat4(1.0f), rot[2], glm::vec3(0.0f, 0.0f, 1.0f));
  277. glm::mat4 rotate = rotateZ * rotateX * rotateY;
  278. glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(pos[0], pos[1], pos[2]));
  279. //glm::mat4 view = glm::inverse(rotate * translate);
  280. glm::mat4 view = rotate * translate;
  281. glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(zoom, zoom, zoom));
  282. MVP = projection * view * scale;
  283. redraw = true;
  284. dirty = false;
  285. }
  286. if ((index >= 0) && (index < World::sizeSkeletalModel())) {
  287. auto& sm = World::getSkeletalModel(index);
  288. if ((sm.size() > 0) && (sm.get(0).size() > 0)) {
  289. if (ImGui::Button("(Re)Create ShaderTexture...")) {
  290. if (st != nullptr) {
  291. delete st;
  292. st = nullptr;
  293. }
  294. if (st == nullptr) {
  295. st = new ShaderTexture();
  296. redraw = true;
  297. }
  298. }
  299. if ((st != nullptr) && redraw) {
  300. st->clear();
  301. sm.display(MVP, 0, 0, st);
  302. redraw = false;
  303. Log::get(LOG_DEBUG) << "Rendered new ShaderTexture!" << Log::endl;
  304. }
  305. } else {
  306. ImGui::Text("Selected SkeletalModel has no animation/frame!");
  307. }
  308. } else {
  309. ImGui::Text("No SkeletalModels loaded!");
  310. }
  311. if (st != nullptr) {
  312. auto bm = TextureManager::getBufferManager(st->getTexture(), TextureStorage::SYSTEM);
  313. ImGui::Image(bm, ImVec2(ImGui::GetColumnWidth() * 2 / 3,
  314. ImGui::GetColumnWidth() * 2 / 3));
  315. }
  316. }
  317. }
  318. ImGui::End();
  319. if (showTestWindow)
  320. ImGui::ShowTestWindow();
  321. if (showStyleWindow)
  322. ImGui::ShowStyleEditor();
  323. ImGui::Render();
  324. }
  325. void UI::shutdown() {
  326. ImGui::Shutdown();
  327. }
  328. void UI::handleKeyboard(KeyboardButton key, bool pressed) {
  329. ImGuiIO& io = ImGui::GetIO();
  330. io.KeysDown[key] = pressed;
  331. io.KeyCtrl = io.KeysDown[leftctrlKey] | io.KeysDown[rightctrlKey];
  332. io.KeyShift = io.KeysDown[leftshiftKey] | io.KeysDown[rightshiftKey];
  333. io.KeyAlt = io.KeysDown[leftaltKey] | io.KeysDown[rightaltKey];
  334. keyboardEvents.push_back(std::make_tuple(key, pressed));
  335. if ((key == leftguiKey) || (key == rightguiKey))
  336. metaKeyIsActive = pressed;
  337. }
  338. void UI::handleText(char* text, bool notFinished) {
  339. if (notFinished)
  340. return;
  341. ImGuiIO& io = ImGui::GetIO();
  342. while (*text != '\0') {
  343. io.AddInputCharacter(*text);
  344. text++;
  345. }
  346. }
  347. void UI::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  348. ImGuiIO& io = ImGui::GetIO();
  349. io.MousePos = ImVec2(x, y);
  350. if (button == leftmouseKey) {
  351. io.MouseDown[0] = !released;
  352. } else if (button == rightmouseKey) {
  353. io.MouseDown[1] = !released;
  354. } else if (button == middlemouseKey) {
  355. io.MouseDown[2] = !released;
  356. } else if (button == fourthmouseKey) {
  357. io.MouseDown[3] = !released;
  358. } else if (button == fifthmouseKey) {
  359. io.MouseDown[4] = !released;
  360. }
  361. clickEvents.push_back(std::make_tuple(x, y, button, released));
  362. }
  363. void UI::handleMouseMotion(int xrel, int yrel, int xabs, int yabs) {
  364. ImGuiIO& io = ImGui::GetIO();
  365. io.MousePos = ImVec2(xabs, yabs);
  366. motionEvents.push_back(std::make_tuple(xrel, yrel, xabs, yabs));
  367. }
  368. void UI::handleMouseScroll(int xrel, int yrel) {
  369. ImGuiIO& io = ImGui::GetIO();
  370. io.MouseWheel += yrel;
  371. scrollEvents.push_back(std::make_tuple(xrel, yrel));
  372. }
  373. void UI::handleControllerAxis(float value, KeyboardButton axis) {
  374. Game::handleControllerAxis(value, axis);
  375. }
  376. void UI::handleControllerButton(KeyboardButton button, bool released) {
  377. if (visible || Console::isVisible())
  378. return;
  379. if (Menu::isVisible()) {
  380. if (button == aButton) {
  381. handleKeyboard(enterKey, !released);
  382. } else if (button == padUp) {
  383. handleKeyboard(upKey, !released);
  384. } else if (button == padDown) {
  385. handleKeyboard(downKey, !released);
  386. } else if (button == padLeft) {
  387. handleKeyboard(leftKey, !released);
  388. } else if (button == padRight) {
  389. handleKeyboard(rightKey, !released);
  390. } else if (button == startButton) {
  391. if (!released)
  392. Menu::setVisible(false);
  393. }
  394. } else {
  395. if (button == aButton) {
  396. Game::handleAction(jumpAction, released);
  397. } else if (button == bButton) {
  398. Game::handleAction(crouchAction, released);
  399. } else if (button == xButton) {
  400. Game::handleAction(useAction, released);
  401. } else if (button == yButton) {
  402. Game::handleAction(holsterAction, released);
  403. } else if (button == padUp) {
  404. Game::handleAction(forwardAction, released);
  405. } else if (button == padDown) {
  406. Game::handleAction(backwardAction, released);
  407. } else if (button == padLeft) {
  408. Game::handleAction(leftAction, released);
  409. } else if (button == padRight) {
  410. Game::handleAction(rightAction, released);
  411. } else if (button == leftShoulder) {
  412. Game::handleAction(walkAction, released);
  413. } else if (button == startButton) {
  414. if (!released)
  415. Menu::setVisible(true);
  416. }
  417. }
  418. }
  419. void UI::renderImGui(ImDrawList** const cmd_lists, int cmd_lists_count) {
  420. if (cmd_lists_count == 0)
  421. return;
  422. static ShaderBuffer vert, uv, col;
  423. gl::glEnable(gl::GL_SCISSOR_TEST);
  424. Shader::set2DState(true);
  425. imguiShader.use();
  426. imguiShader.loadUniform(0, Window::getSize());
  427. vert.bindBuffer(0, 2);
  428. uv.bindBuffer(1, 2);
  429. col.bindBuffer(2, 4);
  430. /*! \fixme Don't copy data
  431. * The GL calls and the shaders can probably be slightly altered
  432. * to avoid copying all the vertices, uvs and colors again here.
  433. */
  434. for (int i = 0; i < cmd_lists_count; i++) {
  435. auto& commands = cmd_lists[i]->commands;
  436. auto& buffer = cmd_lists[i]->vtx_buffer;
  437. int offset = 0;
  438. for (int n = 0; n < commands.size(); n++) {
  439. std::vector<glm::vec2> vertices;
  440. std::vector<glm::vec2> uvs;
  441. std::vector<glm::vec4> colors;
  442. for (int v = 0; v < commands[n].vtx_count; v++) {
  443. vertices.push_back(glm::vec2(buffer[offset + v].pos.x, buffer[offset + v].pos.y));
  444. uvs.push_back(glm::vec2(buffer[offset + v].uv.x, buffer[offset + v].uv.y));
  445. float r, g, b, a;
  446. a = ((buffer[offset + v].col & 0xFF000000) >> 24) / 255.0f;
  447. b = ((buffer[offset + v].col & 0x00FF0000) >> 16) / 255.0f;
  448. g = ((buffer[offset + v].col & 0x0000FF00) >> 8) / 255.0f;
  449. r = (buffer[offset + v].col & 0x000000FF) / 255.0f;
  450. colors.push_back(glm::vec4(r, g, b, a));
  451. }
  452. offset += commands[n].vtx_count;
  453. vert.bufferData(vertices);
  454. uv.bufferData(uvs);
  455. col.bufferData(colors);
  456. auto bm = static_cast<BufferManager*>(commands[n].texture_id);
  457. orAssert(bm != nullptr);
  458. imguiShader.loadUniform(1, bm->getTextureID(), bm->getTextureStorage());
  459. gl::glScissor(commands[n].clip_rect.x,
  460. Window::getSize().y - commands[n].clip_rect.w,
  461. commands[n].clip_rect.z - commands[n].clip_rect.x,
  462. commands[n].clip_rect.w - commands[n].clip_rect.y);
  463. gl::glDrawArrays(gl::GL_TRIANGLES, 0, vertices.size());
  464. }
  465. }
  466. vert.unbind(0);
  467. uv.unbind(1);
  468. col.unbind(2);
  469. Shader::set2DState(false);
  470. gl::glDisable(gl::GL_SCISSOR_TEST);
  471. }
  472. // --------------------------------------
  473. // *INDENT-OFF*
  474. const char* UI::imguiShaderVertex = R"!?!(
  475. #version 330 core
  476. layout(location = 0) in vec2 vertexPosition_screen;
  477. layout(location = 1) in vec2 vertexUV;
  478. layout(location = 2) in vec4 vertexColor;
  479. out vec2 UV;
  480. out vec4 FragColor;
  481. uniform vec2 screen;
  482. void main() {
  483. vec2 halfScreen = screen / 2;
  484. vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
  485. gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
  486. UV = vertexUV;
  487. FragColor = vertexColor;
  488. }
  489. )!?!";
  490. const char* UI::imguiShaderFragment = R"!?!(
  491. #version 330 core
  492. in vec2 UV;
  493. in vec4 FragColor;
  494. out vec4 color;
  495. uniform sampler2D textureSampler;
  496. void main() {
  497. color = texture(textureSampler, UV) * FragColor;
  498. }
  499. )!?!";
  500. // --------------------------------------
  501. // *INDENT-ON*