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.

410 lignes
14 KiB

  1. //
  2. // imGui integration in lolengine
  3. //
  4. // Copyright © 2009—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include "imgui.cpp"
  14. #include <cstdio>
  15. using namespace lol;
  16. #define Line(s) ((s) + "\n")
  17. //-----------------------------------------------------------------------------
  18. LolImGui::LolImGui()
  19. {
  20. m_gamegroup = GAMEGROUP_IMGUI;
  21. m_drawgroup = DRAWGROUP_IMGUI;
  22. //Build shader code -------------------------------------------------------
  23. ShaderVar out_vertex = ShaderVar::GetShaderOut(ShaderProgram::Vertex);
  24. ShaderVar out_pixel = ShaderVar::GetShaderOut(ShaderProgram::Pixel);
  25. ShaderVar pass_texcoord = ShaderVar(ShaderVariable::Varying, ShaderVariableType::Vec2, "texcoord");
  26. ShaderVar pass_color = ShaderVar(ShaderVariable::Varying, ShaderVariableType::Vec4, "color");
  27. ShaderVar in_position = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec2, "position");
  28. ShaderVar in_texcoord = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec2, "texcoord");
  29. ShaderVar in_color = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec4, "color");
  30. m_ortho.m_var = ShaderVar(ShaderVariable::Uniform, ShaderVariableType::Mat4, "ortho");
  31. m_texture.m_var = ShaderVar(ShaderVariable::Uniform, ShaderVariableType::sampler2D, "texture");
  32. ShaderBlock imgui_vertex("imgui_vertex");
  33. imgui_vertex
  34. << out_vertex << m_ortho << in_position
  35. << pass_texcoord << in_texcoord
  36. << pass_color << in_color;
  37. imgui_vertex.SetMainCode(String() +
  38. Line(out_vertex + " = .5 *" + m_ortho + " * vec4(" + in_position + ", -1.0, 1.0);")
  39. + Line(pass_texcoord + " = " + in_texcoord + ";")
  40. + Line(pass_color + " = " + in_color + ";")
  41. );
  42. ShaderBlock imgui_pixel("imgui_pixel");
  43. imgui_pixel << m_texture << pass_texcoord << pass_color << out_pixel;
  44. imgui_pixel.SetMainCode(String() +
  45. Line(String()
  46. + "vec4 col = " + pass_color + " * texture2D(" + m_texture + ", " + pass_texcoord + ");")
  47. + Line(String()
  48. + "if (col.a == 0.0) discard; ")
  49. + Line(out_pixel + " = col;")
  50. );
  51. m_builder
  52. << ShaderProgram::Vertex << imgui_vertex
  53. << ShaderProgram::Pixel << imgui_pixel;
  54. //Input Setup -------------------------------------------------------------
  55. InputProfile& ip = m_profile;
  56. ip.AddBindings<LolImGuiKey, LolImGuiKey::KEY_START, LolImGuiKey::KEY_END>(InputProfileType::Keyboard);
  57. //for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i)
  58. // m_profile << InputProfile::Keyboard(i, LolImGuiKey(i).ToString());
  59. for (int i = LolImGuiKey::MOUSE_KEY_START; i < LolImGuiKey::MOUSE_KEY_END; ++i)
  60. m_profile << InputProfile::MouseKey(i, LolImGuiKey(i).ToString());
  61. for (int i = LolImGuiAxis::MOUSE_AXIS_START; i < LolImGuiAxis::MOUSE_AXIS_END; ++i)
  62. m_profile << InputProfile::MouseAxis(i, LolImGuiAxis(i).ToString());
  63. Ticker::Ref(m_controller = new Controller("ImGui_Controller"));
  64. m_controller->Init(m_profile);
  65. //InputDevice::CaptureMouse(true);
  66. m_mouse = InputDevice::GetMouse();
  67. m_keyboard = InputDevice::GetKeyboard();
  68. //m_controller->Get
  69. //# define KB InputProfile::Keyboard
  70. // m_profile
  71. // << InputProfile::Keyboard(idx, g_name_key_Left);
  72. //# undef KB
  73. }
  74. LolImGui::~LolImGui()
  75. {
  76. ImGui::GetIO().Fonts->TexID = nullptr;
  77. Ticker::Unref(m_font);
  78. m_font = nullptr;
  79. Shader::Destroy(m_shader);
  80. delete m_vdecl;
  81. }
  82. //-----------------------------------------------------------------------------
  83. LolImGui* g_lolimgui = nullptr;
  84. void LolImGui::Init()
  85. {
  86. Ticker::Ref(g_lolimgui = new LolImGui());
  87. ImGuiIO& io = ImGui::GetIO();
  88. //ImFont* font0 = io.Fonts->AddFontDefault();
  89. // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
  90. io.KeyMap[ImGuiKey_Tab] = LolImGuiKey::Tab;
  91. io.KeyMap[ImGuiKey_LeftArrow] = LolImGuiKey::LeftArrow;
  92. io.KeyMap[ImGuiKey_RightArrow] = LolImGuiKey::RightArrow;
  93. io.KeyMap[ImGuiKey_UpArrow] = LolImGuiKey::UpArrow;
  94. io.KeyMap[ImGuiKey_DownArrow] = LolImGuiKey::DownArrow;
  95. io.KeyMap[ImGuiKey_Home] = LolImGuiKey::Home;
  96. io.KeyMap[ImGuiKey_End] = LolImGuiKey::End;
  97. io.KeyMap[ImGuiKey_Delete] = LolImGuiKey::Delete;
  98. io.KeyMap[ImGuiKey_Backspace] = LolImGuiKey::Backspace;
  99. io.KeyMap[ImGuiKey_Enter] = LolImGuiKey::Enter;
  100. io.KeyMap[ImGuiKey_Escape] = LolImGuiKey::Escape;
  101. io.KeyMap[ImGuiKey_A] = LolImGuiKey::A;
  102. io.KeyMap[ImGuiKey_C] = LolImGuiKey::C;
  103. io.KeyMap[ImGuiKey_V] = LolImGuiKey::V;
  104. io.KeyMap[ImGuiKey_X] = LolImGuiKey::X;
  105. io.KeyMap[ImGuiKey_Y] = LolImGuiKey::Y;
  106. io.KeyMap[ImGuiKey_Z] = LolImGuiKey::Z;
  107. //Func pointer
  108. io.RenderDrawListsFn = LolImGui::RenderDrawLists;
  109. io.SetClipboardTextFn = LolImGui::SetClipboard;
  110. io.GetClipboardTextFn = LolImGui::GetClipboard;
  111. }
  112. /* CALLBACKS
  113. void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
  114. {
  115. ImGuiIO& io = ImGui::GetIO();
  116. if (c > 0 && c < 0x10000)
  117. io.AddInputCharacter((unsigned short)c);
  118. }
  119. */
  120. void LolImGui::Shutdown()
  121. {
  122. Ticker::Unref(g_lolimgui);
  123. ImGui::Shutdown();
  124. }
  125. //-----------------------------------------------------------------------------
  126. static String g_clipboard;
  127. void LolImGui::SetClipboard(const char* text)
  128. {
  129. g_clipboard = text;
  130. }
  131. const char* LolImGui::GetClipboard()
  132. {
  133. return g_clipboard.C();
  134. }
  135. //-----------------------------------------------------------------------------
  136. void LolImGui::TickGame(float seconds)
  137. {
  138. super::TickGame(seconds);
  139. ImGuiIO& io = ImGui::GetIO();
  140. //Init Texture
  141. if (!m_font)
  142. {
  143. // Build texture
  144. unsigned char* pixels;
  145. ivec2 size;
  146. io.Fonts->GetTexDataAsRGBA32(&pixels, &size.x, &size.y);
  147. Image* image = new Image();
  148. image->Copy(pixels, size, PixelFormat::RGBA_8);
  149. Ticker::Ref(m_font = new TextureImage("", image));
  150. }
  151. //Texture has been created
  152. if (m_font && m_font->GetTexture())
  153. {
  154. io.Fonts->TexID = (void *)(intptr_t)m_font;
  155. }
  156. // Setup display size (every frame to accommodate for window resizing)
  157. vec2 video_size = vec2(0);
  158. video_size = vec2(Video::GetSize());
  159. io.DisplaySize = ImVec2(video_size.x, video_size.y);
  160. //Setup time step
  161. io.DeltaTime = seconds;
  162. io.MouseDrawCursor = true;
  163. //Update Keyboard
  164. io.KeyCtrl = false;
  165. io.KeyShift = false;
  166. for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i)
  167. {
  168. switch (i)
  169. {
  170. default:
  171. io.KeysDown[i] = m_controller->IsKeyPressed(i);
  172. break;
  173. case LolImGuiKey::LShift:
  174. case LolImGuiKey::RShift:
  175. io.KeyShift = (io.KeyShift || m_controller->IsKeyPressed(i));
  176. break;
  177. case LolImGuiKey::LCtrl:
  178. case LolImGuiKey::RCtrl:
  179. io.KeyCtrl = (io.KeyCtrl || m_controller->IsKeyPressed(i));
  180. break;
  181. }
  182. }
  183. //Update text input
  184. String text = m_keyboard->GetText();
  185. //text.case_change(io.KeyShift);
  186. for (int i = 0; i < text.count(); ++i)
  187. io.AddInputCharacter(text[i]);
  188. //Update mouse
  189. if (m_mouse)
  190. {
  191. vec2 cursor = m_mouse->GetCursor(0);
  192. cursor.y = 1.f - cursor.y;
  193. cursor *= video_size;
  194. io.MousePos = ImVec2(cursor.x, cursor.y);
  195. msg::debug("%.2f/%.2f\n", io.MousePos.x, io.MousePos.y);
  196. io.MouseWheel = m_controller->GetAxisValue(LolImGuiAxis::Scroll);
  197. for (int i = LolImGuiKey::MOUSE_KEY_START; i < LolImGuiKey::MOUSE_KEY_END; ++i)
  198. {
  199. switch (i)
  200. {
  201. default:
  202. io.MouseDown[i - LolImGuiKey::MOUSE_KEY_START] = m_controller->IsKeyPressed(i);
  203. break;
  204. case LolImGuiKey::Focus:
  205. if (m_controller->IsKeyReleased(i))
  206. {
  207. msg::debug("Not focused .....\n");
  208. io.MousePos = ImVec2(-1.f, -1.f);
  209. }
  210. else
  211. msg::debug("Focused !!\n");
  212. break;
  213. }
  214. }
  215. }
  216. // Start the frame
  217. ImGui::NewFrame();
  218. }
  219. //-----------------------------------------------------------------------------
  220. void LolImGui::TickDraw(float seconds, Scene &scene)
  221. {
  222. super::TickDraw(seconds, scene);
  223. scene.AddPrimitiveRenderer(this, new PrimitiveLolImGui());
  224. }
  225. void PrimitiveLolImGui::Render(Scene& scene, PrimitiveSource* primitive)
  226. {
  227. ImGuiIO& io = ImGui::GetIO();
  228. if (io.Fonts->TexID)
  229. ImGui::Render();
  230. }
  231. //// Data
  232. //static GLFWwindow* g_Window = NULL;
  233. //static double g_Time = 0.0f;
  234. //static bool g_MousePressed[3] = { false, false, false };
  235. //static float g_MouseWheel = 0.0f;
  236. //static GLuint g_FontTexture = 0;
  237. //-------------------------------------------------------------------------
  238. // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
  239. // If text or lines are blurry when integrating ImGui in your engine:
  240. // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
  241. //-------------------------------------------------------------------------
  242. void LolImGui::RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
  243. {
  244. g_lolimgui->RenderDrawListsMethod(cmd_lists, cmd_lists_count);
  245. }
  246. void LolImGui::RenderDrawListsMethod(ImDrawList** const cmd_lists, int cmd_lists_count)
  247. {
  248. if (cmd_lists_count == 0)
  249. return;
  250. vec2 size = vec2(Video::GetSize());
  251. float alpha = 1.f;
  252. mat4 ortho = mat4::ortho(size.x * alpha, size.y * alpha, -1000.f, 1000.f)
  253. * mat4::lookat(vec3::axis_z, vec3::zero, vec3::axis_y)
  254. * mat4::scale(vec3::axis_x - vec3::axis_y - vec3::axis_z)
  255. * mat4::translate(-size.x * .5f * alpha, -size.y * .5f * alpha, 0.f);
  256. //Create shader
  257. if (!m_shader)
  258. {
  259. String code;
  260. m_builder.Build(code);
  261. m_shader = Shader::Create(m_builder.GetName(), code);
  262. ASSERT(m_shader);
  263. m_ortho.m_uniform = m_shader->GetUniformLocation(m_ortho.m_var);
  264. m_texture.m_uniform = m_shader->GetUniformLocation(m_texture.m_var);
  265. m_attribs
  266. << m_shader->GetAttribLocation(VertexUsage::Position, 0)
  267. << m_shader->GetAttribLocation(VertexUsage::TexCoord, 0)
  268. << m_shader->GetAttribLocation(VertexUsage::Color, 0);
  269. m_vdecl = new VertexDeclaration(
  270. VertexStream<vec2, vec2, u8vec4>(
  271. VertexUsage::Position,
  272. VertexUsage::TexCoord,
  273. VertexUsage::Color));
  274. }
  275. //Do not render without shader
  276. if (!m_shader)
  277. return;
  278. RenderContext rc;
  279. rc.SetCullMode(CullMode::Disabled);
  280. rc.SetDepthFunc(DepthFunc::Disabled);
  281. m_shader->Bind();
  282. for (int n = 0; n < cmd_lists_count; n++)
  283. {
  284. const ImDrawList* cmd_list = cmd_lists[n];
  285. const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front();
  286. //Register uniforms
  287. m_shader->SetUniform(m_ortho, ortho);
  288. m_shader->SetUniform(m_texture, m_font->GetTexture()->GetTextureUniform(), 0);
  289. int vtx_offset = 0;
  290. for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
  291. {
  292. const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
  293. struct Vertex
  294. {
  295. vec2 pos, tex;
  296. u8vec4 color;
  297. };
  298. VertexBuffer* vbo = new VertexBuffer(pcmd->vtx_count * sizeof(Vertex));
  299. Vertex *vert = (Vertex *)vbo->Lock(0, 0);
  300. #ifdef SHOW_IMGUI_DEBUG
  301. //-----------------------------------------------------------------
  302. //<Debug render> --------------------------------------------------
  303. //-----------------------------------------------------------------
  304. float mod = -200.f;
  305. vec3 off = vec3(vec2(-size.x, -size.y), 0.f);
  306. vec3 pos[4] = {
  307. (1.f / mod) * (off + vec3(0.f)),
  308. (1.f / mod) * (off + size.x * vec3::axis_x),
  309. (1.f / mod) * (off + size.x * vec3::axis_x + size.y * vec3::axis_y),
  310. (1.f / mod) * (off + size.y * vec3::axis_y)
  311. };
  312. for (int i = 0; i < 4; ++i)
  313. Debug::DrawLine(pos[i], pos[(i + 1) % 4], Color::white);
  314. ImDrawVert* buf = (ImDrawVert*)(vtx_buffer + vtx_offset);
  315. for (uint16_t i = 0; i < pcmd->vtx_count; i += 3)
  316. {
  317. vec2 pos[3];
  318. pos[0] = vec2(buf[i + 0].pos.x, buf[i + 0].pos.y);
  319. pos[1] = vec2(buf[i + 1].pos.x, buf[i + 1].pos.y);
  320. pos[2] = vec2(buf[i + 2].pos.x, buf[i + 2].pos.y);
  321. vec4 col[3];
  322. col[0] = vec4(Color::FromRGBA32(buf[i + 0].col).arg, 1.f);
  323. col[1] = vec4(Color::FromRGBA32(buf[i + 1].col).arg, 1.f);
  324. col[2] = vec4(Color::FromRGBA32(buf[i + 2].col).arg, 1.f);
  325. Debug::DrawLine((off + vec3(pos[0], 0.f)) / mod, (off + vec3(pos[1], 0.f)) / mod, col[0]);
  326. Debug::DrawLine((off + vec3(pos[1], 0.f)) / mod, (off + vec3(pos[2], 0.f)) / mod, col[1]);
  327. Debug::DrawLine((off + vec3(pos[2], 0.f)) / mod, (off + vec3(pos[0], 0.f)) / mod, col[2]);
  328. }
  329. //-----------------------------------------------------------------
  330. //<\Debug render> -------------------------------------------------
  331. //-----------------------------------------------------------------
  332. #endif //SHOW_IMGUI_DEBUG
  333. memcpy(vert, vtx_buffer + vtx_offset, pcmd->vtx_count * sizeof(Vertex));
  334. vbo->Unlock();
  335. m_font->Bind();
  336. m_vdecl->Bind();
  337. m_vdecl->SetStream(vbo, m_attribs[0], m_attribs[1], m_attribs[2]);
  338. m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, pcmd->vtx_count);
  339. m_vdecl->Unbind();
  340. m_font->Unbind();
  341. vtx_offset += pcmd->vtx_count * sizeof(Vertex);
  342. delete vbo;
  343. }
  344. }
  345. m_shader->Unbind();
  346. }