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 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*!
  2. * \file src/UI.cpp
  3. * \brief UI interface manager
  4. *
  5. * \author xythobuz
  6. */
  7. #include <algorithm>
  8. #include "global.h"
  9. #include "Console.h"
  10. #include "Game.h"
  11. #include "Log.h"
  12. #include "Menu.h"
  13. #include "RunTime.h"
  14. #include "TextureManager.h"
  15. #include "Window.h"
  16. #include "commands/Command.h"
  17. #include "utils/time.h"
  18. #include "UI.h"
  19. #define STB_IMAGE_IMPLEMENTATION
  20. #include "imgui/stb_image.h"
  21. bool UI::visible = false;
  22. unsigned int UI::fontTex;
  23. std::string UI::iniFilename;
  24. std::string UI::logFilename;
  25. std::list<std::tuple<KeyboardButton, bool>> UI::keyboardEvents;
  26. std::list<std::tuple<unsigned int, unsigned int, KeyboardButton, bool>> UI::clickEvents;
  27. std::list<std::tuple<int, int, int, int>> UI::motionEvents;
  28. std::list<std::tuple<int, int>> UI::scrollEvents;
  29. int UI::initialize() {
  30. iniFilename = getRunTime().getBaseDir() + "/imgui.ini";
  31. logFilename = getRunTime().getBaseDir() + "/imgui_log.txt";
  32. ImGuiIO& io = ImGui::GetIO();
  33. io.DisplaySize = ImVec2((float)getWindow().getWidth(), (float)getWindow().getHeight());
  34. io.DeltaTime = 1.0f / 60.0f;
  35. io.IniFilename = iniFilename.c_str();
  36. io.LogFilename = logFilename.c_str();
  37. io.KeyMap[ImGuiKey_Tab] = tabKey;
  38. io.KeyMap[ImGuiKey_LeftArrow] = leftKey;
  39. io.KeyMap[ImGuiKey_RightArrow] = rightKey;
  40. io.KeyMap[ImGuiKey_UpArrow] = upKey;
  41. io.KeyMap[ImGuiKey_DownArrow] = downKey;
  42. io.KeyMap[ImGuiKey_Home] = homeKey;
  43. io.KeyMap[ImGuiKey_End] = endKey;
  44. io.KeyMap[ImGuiKey_Delete] = delKey;
  45. io.KeyMap[ImGuiKey_Backspace] = backspaceKey;
  46. io.KeyMap[ImGuiKey_Enter] = enterKey;
  47. io.KeyMap[ImGuiKey_Escape] = escapeKey;
  48. io.KeyMap[ImGuiKey_A] = aKey;
  49. io.KeyMap[ImGuiKey_C] = cKey;
  50. io.KeyMap[ImGuiKey_V] = vKey;
  51. io.KeyMap[ImGuiKey_X] = xKey;
  52. io.KeyMap[ImGuiKey_Y] = yKey;
  53. io.KeyMap[ImGuiKey_Z] = zKey;
  54. io.RenderDrawListsFn = UI::renderImGui;
  55. // Load font texture
  56. //! \todo Use our own font subsystem instead of this?
  57. const void* png_data;
  58. unsigned int png_size;
  59. ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
  60. int tex_x, tex_y, tex_comp;
  61. void* tex_data = stbi_load_from_memory((const unsigned char*)png_data,
  62. (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
  63. //! \fixme TODO use proper slot
  64. fontTex = getTextureManager().loadBufferSlot((unsigned char *)tex_data,
  65. tex_x, tex_y, RGBA, 32, 0, false);
  66. stbi_image_free(tex_data);
  67. return 0;
  68. }
  69. void UI::eventsFinished() {
  70. ImGuiIO& io = ImGui::GetIO();
  71. io.DisplaySize = ImVec2((float)getWindow().getWidth(), (float)getWindow().getHeight());
  72. static unsigned long lastTime = 0;
  73. io.DeltaTime = ((float)(systemTimerGet() - lastTime)) / 1000.0f;
  74. lastTime = systemTimerGet();
  75. if (io.DeltaTime <= 0.0f)
  76. io.DeltaTime = 1.0f / 60.0f;
  77. ImGui::NewFrame();
  78. bool clicked = !clickEvents.empty();
  79. if (!visible) {
  80. while (!clickEvents.empty()) {
  81. auto i = clickEvents.front();
  82. if (getMenu().isVisible()) {
  83. getMenu().handleMouseClick(std::get<0>(i), std::get<1>(i),
  84. std::get<2>(i), std::get<3>(i));
  85. }
  86. clickEvents.pop_front();
  87. }
  88. while (!motionEvents.empty()) {
  89. auto i = motionEvents.front();
  90. if (!getMenu().isVisible()) {
  91. getGame().handleMouseMotion(std::get<0>(i), std::get<1>(i),
  92. std::get<2>(i), std::get<3>(i));
  93. }
  94. motionEvents.pop_front();
  95. }
  96. while (!scrollEvents.empty()) {
  97. auto i = scrollEvents.front();
  98. if (getMenu().isVisible()) {
  99. getMenu().handleMouseScroll(std::get<0>(i), std::get<1>(i));
  100. }
  101. scrollEvents.pop_front();
  102. }
  103. }
  104. if ((!io.WantCaptureKeyboard) || (!visible)) {
  105. while (!keyboardEvents.empty()) {
  106. auto i = keyboardEvents.front();
  107. if (getMenu().isVisible()) {
  108. getMenu().handleKeyboard(std::get<0>(i), std::get<1>(i));
  109. } else {
  110. for (int n = forwardAction; n < ActionEventCount; n++) {
  111. if (getRunTime().getKeyBinding((ActionEvents)n) == std::get<0>(i))
  112. getGame().handleAction((ActionEvents)n, !std::get<1>(i));
  113. }
  114. }
  115. if (std::get<1>(i)) {
  116. if (getRunTime().getKeyBinding(menuAction) == std::get<0>(i)) {
  117. getMenu().setVisible(!getMenu().isVisible());
  118. visible = false;
  119. } else if (getRunTime().getKeyBinding(debugAction) == std::get<0>(i)) {
  120. visible = !visible;
  121. }
  122. }
  123. keyboardEvents.pop_front();
  124. }
  125. }
  126. if ((!io.WantCaptureKeyboard) && (!io.WantCaptureMouse) && visible && clicked) {
  127. visible = false;
  128. }
  129. keyboardEvents.clear();
  130. clickEvents.clear();
  131. motionEvents.clear();
  132. scrollEvents.clear();
  133. if (getWindow().getTextInput() != visible)
  134. getWindow().setTextInput(visible);
  135. bool input = !(visible || getMenu().isVisible());
  136. if (getWindow().getMousegrab() != input)
  137. getWindow().setMousegrab(input);
  138. }
  139. void UI::display() {
  140. if (!visible)
  141. return;
  142. Console::display();
  143. if (ImGui::Begin("Engine/RT")) {
  144. if (ImGui::CollapsingHeader("Engine", NULL, true, true)) {
  145. ImGui::Text("Uptime: %lums", systemTimerGet());
  146. }
  147. if (ImGui::CollapsingHeader("Debug")) {
  148. }
  149. if (ImGui::CollapsingHeader("UI Help")) {
  150. ImGui::ShowUserGuide();
  151. }
  152. }
  153. ImGui::End();
  154. ImGui::Render();
  155. }
  156. void UI::shutdown() {
  157. ImGui::Shutdown();
  158. }
  159. void UI::handleKeyboard(KeyboardButton key, bool pressed) {
  160. ImGuiIO& io = ImGui::GetIO();
  161. io.KeysDown[key] = pressed;
  162. io.KeyCtrl = io.KeysDown[leftctrlKey] | io.KeysDown[rightctrlKey];
  163. io.KeyShift = io.KeysDown[leftshiftKey] | io.KeysDown[rightshiftKey];
  164. keyboardEvents.push_back(std::make_tuple(key, pressed));
  165. }
  166. void UI::handleText(char *text, bool notFinished) {
  167. if (notFinished)
  168. return;
  169. ImGuiIO& io = ImGui::GetIO();
  170. while (*text != '\0') {
  171. io.AddInputCharacter(*text);
  172. text++;
  173. }
  174. }
  175. void UI::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  176. ImGuiIO& io = ImGui::GetIO();
  177. io.MousePos = ImVec2((float)x, (float)y);
  178. if (button == leftmouseKey) {
  179. io.MouseDown[0] = !released;
  180. } else if (button == rightmouseKey) {
  181. io.MouseDown[1] = !released;
  182. } else if (button == middlemouseKey) {
  183. io.MouseDown[2] = !released;
  184. } else if (button == fourthmouseKey) {
  185. io.MouseDown[3] = !released;
  186. } else if (button == fifthmouseKey) {
  187. io.MouseDown[4] = !released;
  188. }
  189. clickEvents.push_back(std::make_tuple(x, y, button, released));
  190. }
  191. void UI::handleMouseMotion(int xrel, int yrel, int xabs, int yabs) {
  192. ImGuiIO& io = ImGui::GetIO();
  193. io.MousePos = ImVec2((float)xabs, (float)yabs);
  194. motionEvents.push_back(std::make_tuple(xrel, yrel, xabs, yabs));
  195. }
  196. void UI::handleMouseScroll(int xrel, int yrel) {
  197. ImGuiIO& io = ImGui::GetIO();
  198. io.MouseWheel = (yrel != 0) ? yrel > 0 ? 1 : -1 : 0;
  199. scrollEvents.push_back(std::make_tuple(xrel, yrel));
  200. }
  201. void UI::setVisible(bool v) {
  202. visible = v;
  203. }
  204. bool UI::isVisible() {
  205. return visible;
  206. }
  207. void UI::renderImGui(ImDrawList** const cmd_lists, int cmd_lists_count) {
  208. if (cmd_lists_count == 0)
  209. return;
  210. getWindow().glEnter2D();
  211. glDisable(GL_DEPTH_TEST);
  212. glEnable(GL_SCISSOR_TEST);
  213. glEnableClientState(GL_VERTEX_ARRAY);
  214. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  215. glEnableClientState(GL_COLOR_ARRAY);
  216. // Setup texture
  217. getTextureManager().bindTextureId(fontTex);
  218. // Render command lists
  219. for (int n = 0; n < cmd_lists_count; n++) {
  220. const ImDrawList* cmd_list = cmd_lists[n];
  221. const unsigned char* vtx_buffer = (const unsigned char*)cmd_list->vtx_buffer.begin();
  222. glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer));
  223. glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer+8));
  224. glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer+16));
  225. int vtx_offset = 0;
  226. const ImDrawCmd* pcmd_end = cmd_list->commands.end();
  227. for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++) {
  228. glScissor((int)pcmd->clip_rect.x, (int)(ImGui::GetIO().DisplaySize.y - pcmd->clip_rect.w),
  229. (int)(pcmd->clip_rect.z - pcmd->clip_rect.x),
  230. (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
  231. glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
  232. vtx_offset += pcmd->vtx_count;
  233. }
  234. }
  235. glEnable(GL_DEPTH_TEST);
  236. glDisable(GL_SCISSOR_TEST);
  237. glDisableClientState(GL_VERTEX_ARRAY);
  238. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  239. glDisableClientState(GL_COLOR_ARRAY);
  240. getWindow().glExit2D();
  241. }