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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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 "Menu.h"
  11. #include "OpenRaider.h"
  12. #include "TextureManager.h"
  13. #include "Window.h"
  14. #define STB_IMAGE_IMPLEMENTATION
  15. #include "imgui/stb_image.h"
  16. std::vector<UI*> UI::windows;
  17. std::list<std::tuple<KeyboardButton, bool>> UI::keyboardEvents;
  18. std::list<std::tuple<char *, bool>> UI::textEvents;
  19. std::list<std::tuple<unsigned int, unsigned int, KeyboardButton, bool>> UI::clickEvents;
  20. std::list<std::tuple<int, int>> UI::motionEvents;
  21. std::list<std::tuple<int, int>> UI::scrollEvents;
  22. static GLuint fontTex;
  23. UI::~UI() {
  24. }
  25. void UI::display() { }
  26. void UI::handleKeyboard(KeyboardButton key, bool pressed) { }
  27. void UI::handleText(char *text, bool notFinished) { }
  28. void UI::handleAction(ActionEvents action, bool isFinished) { }
  29. void UI::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) { }
  30. void UI::handleMouseMotion(int xrel, int yrel) { }
  31. void UI::handleMouseScroll(int xrel, int yrel) { }
  32. int UI::initialize() {
  33. ImGuiIO& io = ImGui::GetIO();
  34. io.DisplaySize = ImVec2((float)getWindow().getWidth(), (float)getWindow().getHeight());
  35. io.DeltaTime = 1.0f/60.0f;
  36. io.PixelCenterOffset = 0.0f;
  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. //glGenTextures(1, &fontTex);
  57. //glBindTexture(GL_TEXTURE_2D, fontTex);
  58. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  59. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  60. const void* png_data;
  61. unsigned int png_size;
  62. ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
  63. int tex_x, tex_y, tex_comp;
  64. void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
  65. //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
  66. fontTex = getTextureManager().loadBufferSlot((unsigned char *)tex_data, tex_x, tex_y, RGBA, 32, 0);
  67. stbi_image_free(tex_data);
  68. return 0;
  69. }
  70. void UI::eventsFinished() {
  71. ImGui::NewFrame();
  72. ImGuiIO& io = ImGui::GetIO();
  73. if (!io.WantCaptureKeyboard) {
  74. while (keyboardEvents.size() > 0) {
  75. sendKeyboard(std::get<0>(keyboardEvents.front()), std::get<1>(keyboardEvents.front()));
  76. keyboardEvents.pop_front();
  77. }
  78. while (textEvents.size() > 0) {
  79. sendText(std::get<0>(textEvents.front()), std::get<1>(textEvents.front()));
  80. textEvents.pop_front();
  81. }
  82. }
  83. if (!io.WantCaptureMouse) {
  84. while (clickEvents.size() > 0) {
  85. sendMouseClick(std::get<0>(clickEvents.front()), std::get<1>(clickEvents.front()),
  86. std::get<2>(clickEvents.front()), std::get<3>(clickEvents.front()));
  87. clickEvents.pop_front();
  88. }
  89. while (motionEvents.size() > 0) {
  90. sendMouseMotion(std::get<0>(motionEvents.front()), std::get<1>(motionEvents.front()));
  91. motionEvents.pop_front();
  92. }
  93. while (scrollEvents.size() > 0) {
  94. sendMouseScroll(std::get<0>(scrollEvents.front()), std::get<1>(scrollEvents.front()));
  95. scrollEvents.pop_front();
  96. }
  97. }
  98. keyboardEvents.clear();
  99. textEvents.clear();
  100. clickEvents.clear();
  101. motionEvents.clear();
  102. scrollEvents.clear();
  103. ImGui::SetNewWindowDefaultPos(ImVec2(50, 50));
  104. bool show_test_window = true;
  105. ImGui::ShowTestWindow(&show_test_window);
  106. }
  107. void UI::renderImGui(ImDrawList** const cmd_lists, int cmd_lists_count) {
  108. if (cmd_lists_count == 0)
  109. return;
  110. glDisable(GL_CULL_FACE);
  111. glDisable(GL_DEPTH_TEST);
  112. glEnable(GL_SCISSOR_TEST);
  113. //glEnableClientState(GL_VERTEX_ARRAY);
  114. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  115. glEnableClientState(GL_COLOR_ARRAY);
  116. // Setup texture
  117. //glBindTexture(GL_TEXTURE_2D, fontTex);
  118. //glEnable(GL_TEXTURE_2D);
  119. getTextureManager().bindTextureId(fontTex);
  120. const float width = ImGui::GetIO().DisplaySize.x;
  121. const float height = ImGui::GetIO().DisplaySize.y;
  122. /*
  123. // Setup orthographic projection matrix
  124. glMatrixMode(GL_PROJECTION);
  125. glLoadIdentity();
  126. glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
  127. glMatrixMode(GL_MODELVIEW);
  128. glLoadIdentity();
  129. */
  130. // Render command lists
  131. for (int n = 0; n < cmd_lists_count; n++) {
  132. const ImDrawList* cmd_list = cmd_lists[n];
  133. const unsigned char* vtx_buffer = (const unsigned char*)cmd_list->vtx_buffer.begin();
  134. glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer));
  135. glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer+8));
  136. glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer+16));
  137. int vtx_offset = 0;
  138. const ImDrawCmd* pcmd_end = cmd_list->commands.end();
  139. for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++) {
  140. glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w),
  141. (int)(pcmd->clip_rect.z - pcmd->clip_rect.x),
  142. (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
  143. glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
  144. vtx_offset += pcmd->vtx_count;
  145. }
  146. }
  147. glEnable(GL_CULL_FACE);
  148. glEnable(GL_DEPTH_TEST);
  149. glDisable(GL_SCISSOR_TEST);
  150. glDisableClientState(GL_COLOR_ARRAY);
  151. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  152. //glDisableClientState(GL_VERTEX_ARRAY);
  153. }
  154. void UI::passKeyboard(KeyboardButton key, bool pressed) {
  155. keyboardEvents.push_back(std::make_tuple(key, pressed));
  156. ImGuiIO& io = ImGui::GetIO();
  157. io.KeysDown[key] = pressed;
  158. io.KeyCtrl = io.KeysDown[leftctrlKey] | io.KeysDown[rightctrlKey];
  159. io.KeyShift = io.KeysDown[leftshiftKey] | io.KeysDown[rightshiftKey];
  160. }
  161. void UI::passText(char *text, bool notFinished) {
  162. textEvents.push_back(std::make_tuple(text, notFinished));
  163. // TODO
  164. }
  165. void UI::passMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  166. clickEvents.push_back(std::make_tuple(x, y, button, released));
  167. // TODO
  168. }
  169. void UI::passMouseMotion(int xrel, int yrel) {
  170. motionEvents.push_back(std::make_tuple(xrel, yrel));
  171. // TODO
  172. }
  173. void UI::passMouseScroll(int xrel, int yrel) {
  174. scrollEvents.push_back(std::make_tuple(xrel, yrel));
  175. ImGuiIO& io = ImGui::GetIO();
  176. io.MouseWheel = (yrel != 0) ? yrel > 0 ? 1 : -1 : 0;
  177. }
  178. void UI::addWindow(UI* window) {
  179. windows.push_back(window);
  180. }
  181. void UI::removeWindow(UI *window) {
  182. findInList(window, [](unsigned long i){
  183. windows.erase(windows.begin() + i);
  184. });
  185. }
  186. bool UI::compareUIs(UI* a, UI* b) {
  187. return a->zPos < b->zPos;
  188. }
  189. bool UI::isOnTop(unsigned long windowID) {
  190. assert(windowID < windows.size());
  191. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  192. unsigned long maxPos = (unsigned long)(maxIterator - windows.begin());
  193. return (maxPos == windowID);
  194. }
  195. void UI::moveToTop(unsigned long windowID) {
  196. assert(windowID < windows.size());
  197. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  198. long max = (*maxIterator)->zPos;
  199. unsigned long maxPos = (unsigned long)(maxIterator - windows.begin());
  200. if (maxPos != windowID) {
  201. windows.at(windowID)->zPos = max + 1;
  202. }
  203. }
  204. void UI::makeInvisible(unsigned long windowID) {
  205. assert(windowID < windows.size());
  206. windows.at(windowID)->zPos = -1;
  207. }
  208. void UI::findInList(UI *w, std::function<void (unsigned long i)> func) {
  209. for (unsigned long i = 0; i < windows.size(); i++) {
  210. auto UIptr = &(*windows.at(i));
  211. if (w == UIptr) {
  212. func(i);
  213. return;
  214. }
  215. }
  216. assert(false); // called UI was not registered
  217. }
  218. bool UI::isOnTop() {
  219. bool top = false;
  220. findInList(this, [&](unsigned long i) {
  221. top = UI::isOnTop(i);
  222. });
  223. return top;
  224. }
  225. void UI::moveToTop() {
  226. findInList(this, [](unsigned long i) {
  227. UI::moveToTop(i);
  228. });
  229. }
  230. void UI::makeInvisible() {
  231. findInList(this, [](unsigned long i) {
  232. UI::makeInvisible(i);
  233. });
  234. }
  235. void UI::displayInOrder() {
  236. std::sort(windows.begin(), windows.end(), compareUIs);
  237. for (auto &x : windows) {
  238. if (x->zPos >= 0) {
  239. x->display();
  240. }
  241. }
  242. ImGui::Render();
  243. }
  244. void UI::sendKeyboard(KeyboardButton key, bool pressed) {
  245. if (pressed) {
  246. if (getOpenRaider().keyBindings[menuAction] == key) {
  247. if (getMenu().isOnTop()) {
  248. getMenu().makeInvisible();
  249. } else {
  250. getMenu().moveToTop();
  251. }
  252. } else if (getOpenRaider().keyBindings[consoleAction] == key) {
  253. if (getConsole().isOnTop()) {
  254. getConsole().makeInvisible();
  255. } else {
  256. getConsole().moveToTop();
  257. }
  258. }
  259. }
  260. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  261. (*maxIterator)->handleKeyboard(key, pressed);
  262. for (int i = forwardAction; i < ActionEventCount; i++) {
  263. if (getOpenRaider().keyBindings[i] == key) {
  264. (*maxIterator)->handleAction((ActionEvents)i, !pressed);
  265. }
  266. }
  267. bool mousegrab = (*maxIterator)->zPos == 0;
  268. if (mousegrab != getWindow().getMousegrab())
  269. getWindow().setMousegrab(mousegrab);
  270. }
  271. void UI::sendText(char *text, bool notFinished) {
  272. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  273. (*maxIterator)->handleText(text, notFinished);
  274. }
  275. void UI::sendMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  276. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  277. (*maxIterator)->handleMouseClick(x, y, button, released);
  278. for (int i = forwardAction; i < ActionEventCount; i++) {
  279. if (getOpenRaider().keyBindings[i] == button) {
  280. (*maxIterator)->handleAction((ActionEvents)i, released);
  281. }
  282. }
  283. }
  284. void UI::sendMouseMotion(int xrel, int yrel) {
  285. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  286. (*maxIterator)->handleMouseMotion(xrel, yrel);
  287. }
  288. void UI::sendMouseScroll(int xrel, int yrel) {
  289. auto maxIterator = std::max_element(windows.begin(), windows.end(), compareUIs);
  290. (*maxIterator)->handleMouseScroll(xrel, yrel);
  291. }