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

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