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

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