From b1375e88076be6310ad68475ed121adae4756711 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Wed, 7 Jun 2017 23:03:23 -0400 Subject: [PATCH] added imgui implementation --- CMakeLists.txt | 12 ++++ src/emulator.c | 8 +++ src/render/imgui.cc | 170 ++++++++++++++++++++++++++++++++++++++++++++ src/render/imgui.h | 18 +++++ 4 files changed, 208 insertions(+) create mode 100644 src/render/imgui.cc create mode 100644 src/render/imgui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c0f5356e..5673c23a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,17 @@ list(APPEND REDREAM_INCLUDE_DIRS deps/glew-1.13.0/include) list(APPEND REDREAM_LIBS glew_s) list(APPEND REDREAM_DEFS GLEW_STATIC) +# imgui +add_library(imgui STATIC + deps/cimgui/imgui/imgui.cpp + deps/cimgui/imgui/imgui_draw.cpp + deps/cimgui/cimgui/cimgui.cpp + deps/cimgui/cimgui/drawList.cpp + deps/cimgui/cimgui/fontAtlas.cpp + deps/cimgui/cimgui/listClipper.cpp) +list(APPEND REDREAM_INCLUDE_DIRS deps/cimgui) +list(APPEND REDREAM_LIBS imgui) + # inih add_library(inih STATIC deps/inih/ini.c) list(APPEND REDREAM_INCLUDE_DIRS deps/inih) @@ -208,6 +219,7 @@ set(REDREAM_SOURCES src/jit/jit.c src/jit/pass_stats.c src/render/gl_backend.c + src/render/imgui.cc src/render/microprofile.cc src/render/nuklear.c src/sys/exception_handler.c diff --git a/src/emulator.c b/src/emulator.c index dba3152e..de8b0406 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -27,6 +27,7 @@ #include "hw/pvr/trace.h" #include "hw/scheduler.h" #include "hw/sh4/sh4.h" +#include "render/imgui.h" #include "render/microprofile.h" #include "render/nuklear.h" #include "render/render_backend.h" @@ -58,6 +59,7 @@ struct emu { volatile int video_resized; struct render_backend *r, *r2; + struct imgui *imgui; struct microprofile *mp; struct nuklear *nk; struct trace_writer *trace_writer; @@ -406,6 +408,7 @@ static void emu_paint(struct emu *emu) { float fwidth = (float)emu->video_width; float fheight = (float)emu->video_height; + imgui_update_input(emu->imgui); nk_update_input(emu->nk); r_viewport(emu->r, emu->video_width, emu->video_height); @@ -517,6 +520,7 @@ static void emu_paint(struct emu *emu) { nk_end(ctx); } + imgui_render(emu->imgui); mp_render(emu->mp); nk_render(emu->nk); @@ -604,6 +608,7 @@ static void emu_guest_push_audio(void *userdata, const int16_t *data, static void emu_host_mousemove(void *userdata, int port, int x, int y) { struct emu *emu = userdata; + imgui_mousemove(emu->imgui, x, y); mp_mousemove(emu->mp, x, y); nk_mousemove(emu->nk, x, y); } @@ -615,6 +620,7 @@ static void emu_host_keydown(void *userdata, int port, enum keycode key, if (key == K_F1 && value > 0) { emu->debug_menu = emu->debug_menu ? 0 : 1; } else { + imgui_keydown(emu->imgui, key, value); mp_keydown(emu->mp, key, value); nk_keydown(emu->nk, key, value); } @@ -668,6 +674,7 @@ static void emu_host_context_destroyed(void *userdata) { nk_destroy(emu->nk); mp_destroy(emu->mp); + imgui_destroy(emu->imgui); r_destroy(emu->r); } @@ -680,6 +687,7 @@ static void emu_host_context_reset(void *userdata) { /* create primary renderer */ emu->r = r_create(emu->host); + emu->imgui = imgui_create(emu->r); emu->mp = mp_create(emu->r); emu->nk = nk_create(emu->r); diff --git a/src/render/imgui.cc b/src/render/imgui.cc new file mode 100644 index 00000000..7edc031f --- /dev/null +++ b/src/render/imgui.cc @@ -0,0 +1,170 @@ +#include + +extern "C" { +#include "core/assert.h" +#include "render/imgui.h" +#include "render/render_backend.h" +} + +struct imgui { + struct render_backend *r; + bool alt[2]; + bool ctrl[2]; + bool shift[2]; +}; + +void imgui_render(struct imgui *imgui) { + ImGuiIO &io = ImGui::GetIO(); + + /* update draw batches. note, this doesn't _actually_ render anything because + io.RenderDrawListsFn is null */ + ImGui::Render(); + + /* get the latest draw batches, and pass them off out the render backend */ + ImDrawData *draw_data = ImGui::GetDrawData(); + + for (int i = 0; i < draw_data->CmdListsCount; ++i) { + const auto cmd_list = draw_data->CmdLists[i]; + + struct ui_vertex *verts = + reinterpret_cast(cmd_list->VtxBuffer.Data); + int num_verts = cmd_list->VtxBuffer.size(); + + uint16_t *indices = cmd_list->IdxBuffer.Data; + int num_indices = cmd_list->IdxBuffer.size(); + + r_begin_ui_surfaces(imgui->r, verts, num_verts, indices, num_indices); + + int index_offset = 0; + + for (int j = 0; j < cmd_list->CmdBuffer.size(); ++j) { + const auto &cmd = cmd_list->CmdBuffer[j]; + + struct ui_surface surf; + surf.prim_type = PRIM_TRIANGLES; + surf.texture = static_cast( + reinterpret_cast(cmd.TextureId)); + surf.src_blend = BLEND_SRC_ALPHA; + surf.dst_blend = BLEND_ONE_MINUS_SRC_ALPHA; + surf.scissor = true; + surf.scissor_rect[0] = cmd.ClipRect.x; + surf.scissor_rect[1] = io.DisplaySize.y - cmd.ClipRect.w; + surf.scissor_rect[2] = cmd.ClipRect.z - cmd.ClipRect.x; + surf.scissor_rect[3] = cmd.ClipRect.w - cmd.ClipRect.y; + surf.first_vert = index_offset; + surf.num_verts = cmd.ElemCount; + + r_draw_ui_surface(imgui->r, &surf); + + index_offset += cmd.ElemCount; + } + + r_end_ui_surfaces(imgui->r); + } +} + +void imgui_update_input(struct imgui *imgui) { + ImGuiIO &io = ImGui::GetIO(); + + int width = r_viewport_width(imgui->r); + int height = r_viewport_height(imgui->r); + io.DisplaySize = + ImVec2(static_cast(width), static_cast(height)); + + ImGui::NewFrame(); + + /* reset mouse scroll state */ + io.MouseWheel = 0.0; +} + +void imgui_keydown(struct imgui *imgui, enum keycode code, int16_t value) { + ImGuiIO &io = ImGui::GetIO(); + + if (code == K_MWHEELUP) { + io.MouseWheel = 1.0f; + } else if (code == K_MWHEELDOWN) { + io.MouseWheel = -1.0f; + } else if (code == K_MOUSE1) { + io.MouseDown[0] = value > 0; + } else if (code == K_MOUSE2) { + io.MouseDown[1] = value > 0; + } else if (code == K_MOUSE3) { + io.MouseDown[2] = value > 0; + ; + } else if (code == K_LALT || code == K_RALT) { + imgui->alt[code == K_LALT ? 0 : 1] = !!value; + io.KeyAlt = imgui->alt[0] || imgui->alt[1]; + } else if (code == K_LCTRL || code == K_RCTRL) { + imgui->ctrl[code == K_LCTRL ? 0 : 1] = !!value; + io.KeyCtrl = imgui->ctrl[0] || imgui->ctrl[1]; + } else if (code == K_LSHIFT || code == K_RSHIFT) { + imgui->shift[code == K_LSHIFT ? 0 : 1] = !!value; + io.KeyShift = imgui->shift[0] || imgui->shift[1]; + } else { + io.KeysDown[code] = value > 0; + } +} + +void imgui_mousemove(struct imgui *imgui, int x, int y) { + ImGuiIO &io = ImGui::GetIO(); + + io.MousePos = ImVec2((float)x, (float)y); +} + +void imgui_destroy(struct imgui *imgui) { + ImGui::Shutdown(); + + free(imgui); +} + +struct imgui *imgui_create(struct render_backend *r) { + struct imgui *imgui = + reinterpret_cast(calloc(1, sizeof(struct imgui))); + + imgui->r = r; + + /* initialize imgui */ + ImGuiIO &io = ImGui::GetIO(); + + /* don't really care if this is accurate */ + io.DeltaTime = 1.0f / 60.0f; + + /* don't save settings */ + io.IniSavingRate = 0.0f; + + /* setup key mapping */ + io.KeyMap[ImGuiKey_Tab] = K_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = K_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = K_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = K_UP; + io.KeyMap[ImGuiKey_DownArrow] = K_DOWN; + io.KeyMap[ImGuiKey_PageUp] = K_PAGEUP; + io.KeyMap[ImGuiKey_PageDown] = K_PAGEDOWN; + io.KeyMap[ImGuiKey_Delete] = K_DELETE; + io.KeyMap[ImGuiKey_Backspace] = K_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = K_RETURN; + io.KeyMap[ImGuiKey_Escape] = K_ESCAPE; + io.KeyMap[ImGuiKey_A] = 'a'; + io.KeyMap[ImGuiKey_C] = 'c'; + io.KeyMap[ImGuiKey_V] = 'v'; + io.KeyMap[ImGuiKey_X] = 'x'; + io.KeyMap[ImGuiKey_Y] = 'y'; + io.KeyMap[ImGuiKey_Z] = 'z'; + + /* setup misc callbacks ImGui relies on */ + io.RenderDrawListsFn = nullptr; + io.SetClipboardTextFn = nullptr; + io.GetClipboardTextFn = nullptr; + + /* register font in backend */ + uint8_t *pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + texture_handle_t handle = + r_create_texture(imgui->r, PXL_RGBA, FILTER_BILINEAR, WRAP_REPEAT, + WRAP_REPEAT, 0, width, height, pixels); + io.Fonts->TexID = reinterpret_cast(static_cast(handle)); + + return imgui; +} diff --git a/src/render/imgui.h b/src/render/imgui.h new file mode 100644 index 00000000..8b15818f --- /dev/null +++ b/src/render/imgui.h @@ -0,0 +1,18 @@ +#ifndef IMGUI_H +#define IMGUI_H + +#include "keycode.h" + +struct imgui; +struct render_backend; + +struct imgui *imgui_create(struct render_backend *r); +void imgui_destroy(struct imgui *imgui); + +void imgui_mousemove(struct imgui *imgui, int x, int y); +void imgui_keydown(struct imgui *imgui, enum keycode key, int16_t value); + +void imgui_update_input(struct imgui *imgui); +void imgui_render(struct imgui *imgui); + +#endif