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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*!
  2. * \file src/UI.cpp
  3. * \brief UI interface manager
  4. *
  5. * \author xythobuz
  6. */
  7. #include "imgui/imgui.h"
  8. #include "stb/stb_image.h"
  9. #include "global.h"
  10. #include "Camera.h"
  11. #include "Console.h"
  12. #include "Game.h"
  13. #include "Log.h"
  14. #include "Menu.h"
  15. #include "Render.h"
  16. #include "RunTime.h"
  17. #include "SoundManager.h"
  18. #include "TextureManager.h"
  19. #include "World.h"
  20. #include "commands/Command.h"
  21. #include "system/Sound.h"
  22. #include "system/Window.h"
  23. #include "utils/time.h"
  24. #include "UI.h"
  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. // Load font texture
  72. //! \todo Use our own font subsystem instead of this?
  73. const void* png_data;
  74. unsigned int png_size;
  75. ImGui::GetDefaultFontData(nullptr, nullptr, &png_data, &png_size);
  76. int tex_x, tex_y, tex_comp;
  77. void* tex_data = stbi_load_from_memory((const unsigned char*)png_data,
  78. (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
  79. fontTex = TextureManager::loadBufferSlot((unsigned char*)tex_data,
  80. tex_x, tex_y, ColorMode::RGBA, 32,
  81. TextureStorage::SYSTEM, -1, false);
  82. stbi_image_free(tex_data);
  83. return 0;
  84. }
  85. void UI::eventsFinished() {
  86. ImGuiIO& io = ImGui::GetIO();
  87. io.DisplaySize = ImVec2(Window::getSize().x, Window::getSize().y);
  88. static unsigned long lastTime = 0;
  89. io.DeltaTime = ((float)(systemTimerGet() - lastTime)) / 1000.0f;
  90. lastTime = systemTimerGet();
  91. if (io.DeltaTime <= 0.0f)
  92. io.DeltaTime = 1.0f / 60.0f;
  93. ImGui::NewFrame();
  94. if (!(visible || Console::isVisible())) {
  95. while (!clickEvents.empty()) {
  96. auto i = clickEvents.front();
  97. if (getMenu().isVisible()) {
  98. getMenu().handleMouseClick(std::get<0>(i), std::get<1>(i),
  99. std::get<2>(i), std::get<3>(i));
  100. }
  101. clickEvents.pop_front();
  102. }
  103. while (!motionEvents.empty()) {
  104. auto i = motionEvents.front();
  105. if (!getMenu().isVisible()) {
  106. getGame().handleMouseMotion(std::get<0>(i), std::get<1>(i),
  107. std::get<2>(i), std::get<3>(i));
  108. }
  109. motionEvents.pop_front();
  110. }
  111. while (!scrollEvents.empty()) {
  112. auto i = scrollEvents.front();
  113. if (getMenu().isVisible()) {
  114. getMenu().handleMouseScroll(std::get<0>(i), std::get<1>(i));
  115. }
  116. scrollEvents.pop_front();
  117. }
  118. }
  119. while (!keyboardEvents.empty()) {
  120. auto i = keyboardEvents.front();
  121. if (!(visible || Console::isVisible())) {
  122. if (getMenu().isVisible()) {
  123. getMenu().handleKeyboard(std::get<0>(i), std::get<1>(i));
  124. } else {
  125. for (int n = forwardAction; n < ActionEventCount; n++) {
  126. if (RunTime::getKeyBinding((ActionEvents)n) == std::get<0>(i))
  127. getGame().handleAction((ActionEvents)n, !std::get<1>(i));
  128. }
  129. }
  130. }
  131. if (std::get<1>(i)) {
  132. if (!(visible || Console::isVisible())) {
  133. if (RunTime::getKeyBinding(menuAction) == std::get<0>(i)) {
  134. getMenu().setVisible(!getMenu().isVisible());
  135. }
  136. }
  137. if ((!io.WantCaptureKeyboard) || (!(visible || Console::isVisible()))) {
  138. if (!metaKeyIsActive) {
  139. if (RunTime::getKeyBinding(debugAction) == std::get<0>(i)) {
  140. visible = !visible;
  141. }
  142. if (RunTime::getKeyBinding(consoleAction) == std::get<0>(i)) {
  143. Console::setVisible(!Console::isVisible());
  144. }
  145. }
  146. }
  147. }
  148. keyboardEvents.pop_front();
  149. }
  150. bool clicked = !clickEvents.empty();
  151. clickEvents.clear();
  152. motionEvents.clear();
  153. scrollEvents.clear();
  154. if ((visible || Console::isVisible()) && (
  155. ((!io.WantCaptureKeyboard) && io.KeysDown[escapeKey])
  156. || ((!io.WantCaptureMouse) && clicked)
  157. )) {
  158. visible = false;
  159. Console::setVisible(false);
  160. }
  161. if (Window::getTextInput() != (visible || Console::isVisible()))
  162. Window::setTextInput(visible || Console::isVisible());
  163. bool input = !(visible || Console::isVisible() || getMenu().isVisible());
  164. if (Window::getMousegrab() != input)
  165. Window::setMousegrab(input);
  166. io.MouseWheel = 0;
  167. }
  168. void UI::display() {
  169. if (RunTime::getShowFPS()) {
  170. if (ImGui::Begin("Debug Overlay", nullptr, ImVec2(0,0), 0.3f,
  171. ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize
  172. | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings
  173. | ImGuiWindowFlags_AlwaysAutoResize)) {
  174. ImGui::Text("%d FPS", RunTime::getFPS());
  175. ImGui::Text("X: %.1f (%.2f)", Camera::getPosition().x, Camera::getRotation().x);
  176. ImGui::Text("Y: %.2f (%.2f)", Camera::getPosition().y, Camera::getRotation().y);
  177. ImGui::Text("Z: %.2f", Camera::getPosition().z);
  178. auto window = ImGui::GetWindowSize();
  179. auto screen = Window::getSize();
  180. ImGui::SetWindowPos(ImVec2(10, screen.y - window.y - 10));
  181. }
  182. ImGui::End();
  183. }
  184. Console::display();
  185. if (!visible) {
  186. ImGui::Render();
  187. return;
  188. }
  189. static bool showTestWindow = false;
  190. if (ImGui::Begin("Engine", &visible, ImVec2(400, 400))) {
  191. Render::displayUI();
  192. RunTime::display();
  193. SoundManager::display();
  194. /*
  195. static bool visibleTex = false;
  196. static bool visibleTile = false;
  197. static bool visibleAnim = false;
  198. static bool visibleSprite = false;
  199. if (ImGui::CollapsingHeader("Texture Viewer")) {
  200. static bool game = getGame().isLoaded();
  201. static int index = 0;
  202. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
  203. ImGui::SliderInt("##texslide", &index, 0, TextureManager::.numTextures(
  204. game ? TextureStorage::GAME : TextureStorage::SYSTEM) - 1);
  205. ImGui::PopItemWidth();
  206. ImGui::SameLine();
  207. if (ImGui::Button("+##texplus", ImVec2(0, 0), true)) {
  208. if (index < (TextureManager::numTextures(
  209. game ? TextureStorage::GAME : TextureStorage::SYSTEM) - 1))
  210. index++;
  211. else
  212. index = 0;
  213. }
  214. ImGui::SameLine();
  215. if (ImGui::Button("-##texminus", ImVec2(0, 0), true)) {
  216. if (index > 0)
  217. index--;
  218. else
  219. index = TextureManager::numTextures(
  220. game ? TextureStorage::GAME : TextureStorage::SYSTEM) - 1;
  221. }
  222. ImGui::SameLine();
  223. if ((TextureManager::numTextures() > 0)) {
  224. ImGui::Checkbox("Game##texgame", &game);
  225. } else {
  226. game = false;
  227. }
  228. ImGui::SameLine();
  229. if (ImGui::Button("Show##texshow")) {
  230. visibleTex = true;
  231. visibleTile = false;
  232. visibleAnim = false;
  233. visibleSprite = false;
  234. }
  235. ImGui::SameLine();
  236. if (ImGui::Button("Clear##texclear")) {
  237. getRender().debugDisplayTexture();
  238. visibleTex = false;
  239. }
  240. if (visibleTex) {
  241. getRender().debugDisplayTexture(index,
  242. game ? TextureStorage::GAME : TextureStorage::SYSTEM,
  243. ImGui::GetWindowPos().x - ImGui::GetWindowWidth(),
  244. ImGui::GetWindowPos().y,
  245. ImGui::GetWindowWidth(), ImGui::GetWindowWidth());
  246. }
  247. }
  248. if (ImGui::CollapsingHeader("Textile Viewer")) {
  249. if (TextureManager::numTiles() > 0) {
  250. static int index = 0;
  251. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
  252. ImGui::SliderInt("##tileslide", &index, 0, TextureManager::numTiles() - 1);
  253. ImGui::PopItemWidth();
  254. ImGui::SameLine();
  255. if (ImGui::Button("+##tileplus", ImVec2(0, 0), true)) {
  256. if (index < (TextureManager::numTiles() - 1))
  257. index++;
  258. else
  259. index = 0;
  260. }
  261. ImGui::SameLine();
  262. if (ImGui::Button("-##tileminus", ImVec2(0, 0), true)) {
  263. if (index > 0)
  264. index--;
  265. else
  266. index = TextureManager::numTiles() - 1;
  267. }
  268. ImGui::SameLine();
  269. if (ImGui::Button("Show##tileshow")) {
  270. visibleTile = true;
  271. visibleTex = false;
  272. visibleAnim = false;
  273. visibleSprite = false;
  274. }
  275. ImGui::SameLine();
  276. if (ImGui::Button("Clear##tileclear")) {
  277. getRender().debugDisplayTextile();
  278. visibleTile = false;
  279. }
  280. if (visibleTile && (index < TextureManager::numTiles())) {
  281. ImGui::Text(TextureManager::.getTile(index).isTriangle() ? "Triangle" : "Rectangle");
  282. }
  283. if (visibleTile) {
  284. getRender().debugDisplayTextile(index,
  285. ImGui::GetWindowPos().x - (ImGui::GetWindowWidth() / 2),
  286. ImGui::GetWindowPos().y,
  287. (ImGui::GetWindowWidth() / 2), (ImGui::GetWindowWidth() / 2));
  288. }
  289. } else {
  290. ImGui::Text("Please load a level using the new loader!");
  291. }
  292. }
  293. if (ImGui::CollapsingHeader("Animated Textile Viewer")) {
  294. if (TextureManager::.numAnimatedTiles() > 0) {
  295. static int index = 0;
  296. static int tile = TextureManager::.getFirstTileAnimation(index);
  297. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
  298. if (ImGui::SliderInt("##animslide", &index, 0, TextureManager::.numAnimatedTiles() - 1)) {
  299. tile = TextureManager::.getFirstTileAnimation(index);
  300. }
  301. ImGui::PopItemWidth();
  302. ImGui::SameLine();
  303. if (ImGui::Button("+##animplus", ImVec2(0, 0), true)) {
  304. if (index < (TextureManager::.numAnimatedTiles() - 1))
  305. index++;
  306. else
  307. index = 0;
  308. tile = TextureManager::.getFirstTileAnimation(index);
  309. }
  310. ImGui::SameLine();
  311. if (ImGui::Button("-##animminus", ImVec2(0, 0), true)) {
  312. if (index > 0)
  313. index--;
  314. else
  315. index = TextureManager::.numAnimatedTiles() - 1;
  316. tile = TextureManager::.getFirstTileAnimation(index);
  317. }
  318. ImGui::SameLine();
  319. if (ImGui::Button("Show##animshow")) {
  320. visibleAnim = true;
  321. visibleTex = false;
  322. visibleTile = false;
  323. visibleSprite = false;
  324. }
  325. ImGui::SameLine();
  326. if (ImGui::Button("Clear##animclear")) {
  327. getRender().debugDisplayTextile();
  328. visibleAnim = false;
  329. }
  330. if (visibleAnim) {
  331. static int fr = 0;
  332. if (fr > 0) {
  333. fr--;
  334. } else {
  335. getRender().debugDisplayTextile(tile,
  336. ImGui::GetWindowPos().x - (ImGui::GetWindowWidth() / 2),
  337. ImGui::GetWindowPos().y,
  338. (ImGui::GetWindowWidth() / 2), (ImGui::GetWindowWidth() / 2));
  339. fr = RunTime::getFPS() / 2;
  340. tile = TextureManager::.getNextTileAnimation(tile);
  341. }
  342. ImGui::Text("Current Tile: %d", tile);
  343. }
  344. } else {
  345. ImGui::Text("Please load a level with animated textures!");
  346. }
  347. }
  348. if (ImGui::CollapsingHeader("Sprite Sequence Viewer")) {
  349. if (getWorld().sizeSprite() <= 0) {
  350. ImGui::Text("Please load a level containing sprites!");
  351. } else {
  352. static int index = 0;
  353. static int sprite = 0;
  354. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
  355. if (ImGui::SliderInt("##spriteslide", &index, 0, getWorld().sizeSprite() - 1))
  356. sprite = 0;
  357. ImGui::PopItemWidth();
  358. ImGui::SameLine();
  359. if (ImGui::Button("+##spriteplus", ImVec2(0, 0), true)) {
  360. if (index < (getWorld().sizeSprite() - 1))
  361. index++;
  362. else
  363. index = 0;
  364. sprite = 0;
  365. }
  366. ImGui::SameLine();
  367. if (ImGui::Button("-##spriteminus", ImVec2(0, 0), true)) {
  368. if (index > 0)
  369. index--;
  370. else
  371. index = getWorld().sizeSprite() - 1;
  372. sprite = 0;
  373. }
  374. ImGui::SameLine();
  375. if (ImGui::Button("Show##spriteshow")) {
  376. visibleSprite = true;
  377. visibleTex = false;
  378. visibleTile = false;
  379. visibleAnim = false;
  380. sprite = 0;
  381. }
  382. ImGui::SameLine();
  383. if (ImGui::Button("Clear##spriteclear")) {
  384. getRender().debugDisplaySprite();
  385. visibleSprite = false;
  386. }
  387. if (visibleSprite) {
  388. static int fr = 0;
  389. if (fr > 0) {
  390. fr--;
  391. } else {
  392. getRender().debugDisplaySprite(index, sprite,
  393. ImGui::GetWindowPos().x - (ImGui::GetWindowWidth() / 2),
  394. ImGui::GetWindowPos().y,
  395. (ImGui::GetWindowWidth() / 2), (ImGui::GetWindowWidth() / 2));
  396. fr = RunTime::getFPS() / 10;
  397. if (sprite < (getWorld().getSprite(index).size() - 1))
  398. sprite++;
  399. else
  400. sprite = 0;
  401. }
  402. ImGui::Text("Sprite %d/%d", sprite + 1, getWorld().getSprite(index).size());
  403. }
  404. }
  405. }
  406. */
  407. if (ImGui::CollapsingHeader("ImGui/Debug UI Help")) {
  408. //ImGui::TextWrapped("DebugViewer Textures/Textiles/Sprites will be drawn on"
  409. // " the left side and scale with the size of this window!");
  410. //ImGui::Separator();
  411. ImGui::ShowUserGuide();
  412. ImGui::Separator();
  413. if (ImGui::Button("Show/Hide Test Window")) {
  414. showTestWindow = !showTestWindow;
  415. }
  416. }
  417. }
  418. ImGui::End();
  419. if (showTestWindow)
  420. ImGui::ShowTestWindow();
  421. ImGui::Render();
  422. }
  423. void UI::shutdown() {
  424. ImGui::Shutdown();
  425. }
  426. void UI::handleKeyboard(KeyboardButton key, bool pressed) {
  427. ImGuiIO& io = ImGui::GetIO();
  428. io.KeysDown[key] = pressed;
  429. io.KeyCtrl = io.KeysDown[leftctrlKey] | io.KeysDown[rightctrlKey];
  430. io.KeyShift = io.KeysDown[leftshiftKey] | io.KeysDown[rightshiftKey];
  431. keyboardEvents.push_back(std::make_tuple(key, pressed));
  432. if ((key == leftguiKey) || (key == rightguiKey))
  433. metaKeyIsActive = pressed;
  434. }
  435. void UI::handleText(char* text, bool notFinished) {
  436. if (notFinished)
  437. return;
  438. ImGuiIO& io = ImGui::GetIO();
  439. while (*text != '\0') {
  440. io.AddInputCharacter(*text);
  441. text++;
  442. }
  443. }
  444. void UI::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  445. ImGuiIO& io = ImGui::GetIO();
  446. io.MousePos = ImVec2((float)x, (float)y);
  447. if (button == leftmouseKey) {
  448. io.MouseDown[0] = !released;
  449. } else if (button == rightmouseKey) {
  450. io.MouseDown[1] = !released;
  451. } else if (button == middlemouseKey) {
  452. io.MouseDown[2] = !released;
  453. } else if (button == fourthmouseKey) {
  454. io.MouseDown[3] = !released;
  455. } else if (button == fifthmouseKey) {
  456. io.MouseDown[4] = !released;
  457. }
  458. clickEvents.push_back(std::make_tuple(x, y, button, released));
  459. }
  460. void UI::handleMouseMotion(int xrel, int yrel, int xabs, int yabs) {
  461. ImGuiIO& io = ImGui::GetIO();
  462. io.MousePos = ImVec2((float)xabs, (float)yabs);
  463. motionEvents.push_back(std::make_tuple(xrel, yrel, xabs, yabs));
  464. }
  465. void UI::handleMouseScroll(int xrel, int yrel) {
  466. ImGuiIO& io = ImGui::GetIO();
  467. io.MouseWheel += yrel;
  468. scrollEvents.push_back(std::make_tuple(xrel, yrel));
  469. }
  470. void UI::handleControllerAxis(float value, KeyboardButton axis) {
  471. getGame().handleControllerAxis(value, axis);
  472. }
  473. void UI::handleControllerButton(KeyboardButton button, bool released) {
  474. getGame().handleControllerButton(button, released);
  475. }
  476. void UI::renderImGui(ImDrawList** const cmd_lists, int cmd_lists_count) {
  477. if (cmd_lists_count == 0)
  478. return;
  479. static ShaderBuffer vert, uv, col;
  480. glEnable(GL_SCISSOR_TEST);
  481. glDisable(GL_DEPTH_TEST);
  482. imguiShader.use();
  483. imguiShader.loadUniform(0, Window::getSize());
  484. imguiShader.loadUniform(1, fontTex, TextureStorage::SYSTEM);
  485. vert.bindBuffer(0, 2);
  486. uv.bindBuffer(1, 2);
  487. col.bindBuffer(2, 4);
  488. /*! \fixme Don't copy data
  489. * The GL calls and the shaders can probably be slightly altered
  490. * to avoid copying all the vertices, uvs and colors again here.
  491. */
  492. for (int i = 0; i < cmd_lists_count; i++) {
  493. auto& commands = cmd_lists[i]->commands;
  494. auto& buffer = cmd_lists[i]->vtx_buffer;
  495. int offset = 0;
  496. for (int n = 0; n < commands.size(); n++) {
  497. std::vector<glm::vec2> vertices;
  498. std::vector<glm::vec2> uvs;
  499. std::vector<glm::vec4> colors;
  500. for (int v = 0; v < commands[n].vtx_count; v++) {
  501. vertices.push_back(glm::vec2(buffer[offset + v].pos.x, buffer[offset + v].pos.y));
  502. uvs.push_back(glm::vec2(buffer[offset + v].uv.x, buffer[offset + v].uv.y));
  503. float r, g, b, a;
  504. a = ((buffer[offset + v].col & 0xFF000000) >> 24) / 255.0f;
  505. b = ((buffer[offset + v].col & 0x00FF0000) >> 16) / 255.0f;
  506. g = ((buffer[offset + v].col & 0x0000FF00) >> 8) / 255.0f;
  507. r = (buffer[offset + v].col & 0x000000FF) / 255.0f;
  508. colors.push_back(glm::vec4(r, g, b, a));
  509. }
  510. offset += commands[n].vtx_count;
  511. vert.bufferData(vertices);
  512. uv.bufferData(uvs);
  513. col.bufferData(colors);
  514. glScissor(commands[n].clip_rect.x,
  515. Window::getSize().y - commands[n].clip_rect.w,
  516. commands[n].clip_rect.z - commands[n].clip_rect.x,
  517. commands[n].clip_rect.w - commands[n].clip_rect.y);
  518. glDrawArrays(GL_TRIANGLES, 0, vertices.size());
  519. }
  520. }
  521. vert.unbind(0);
  522. uv.unbind(1);
  523. col.unbind(2);
  524. glEnable(GL_DEPTH_TEST);
  525. glDisable(GL_SCISSOR_TEST);
  526. }
  527. // --------------------------------------
  528. // *INDENT-OFF*
  529. const char* UI::imguiShaderVertex = R"!?!(
  530. #version 330 core
  531. layout(location = 0) in vec2 vertexPosition_screen;
  532. layout(location = 1) in vec2 vertexUV;
  533. layout(location = 2) in vec4 vertexColor;
  534. out vec2 UV;
  535. out vec4 FragColor;
  536. uniform vec2 screen;
  537. void main() {
  538. vec2 halfScreen = screen / 2;
  539. vec2 vertexPosition_homogenous = (vertexPosition_screen - halfScreen) / halfScreen;
  540. gl_Position = vec4(vertexPosition_homogenous.x, -vertexPosition_homogenous.y, 0, 1);
  541. UV = vertexUV;
  542. FragColor = vertexColor;
  543. }
  544. )!?!";
  545. const char* UI::imguiShaderFragment = R"!?!(
  546. #version 330 core
  547. in vec2 UV;
  548. in vec4 FragColor;
  549. out vec4 color;
  550. uniform sampler2D textureSampler;
  551. void main() {
  552. color = texture(textureSampler, UV) * FragColor;
  553. }
  554. )!?!";
  555. // --------------------------------------
  556. // *INDENT-ON*