#ifdef _MSC_VER #include #include #include #endif #ifdef MACOSX #include #endif #include #include #include #include "imgui_impl_sdl.h" // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) static void ImGui_ImplSdl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) { if (cmd_lists_count == 0) return; // We are using the OpenGL fixed pipeline to make the example code simpler to read! // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer. // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context // Setup orthographic projection matrix const float width = ImGui::GetIO().DisplaySize.x; const float height = ImGui::GetIO().DisplaySize.y; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // Render command lists #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front(); glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos))); glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv))); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col))); int vtx_offset = 0; for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i]; if (pcmd->user_callback) { pcmd->user_callback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id); glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y)); glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count); } vtx_offset += pcmd->vtx_count; } } #undef OFFSETOF // Restore modified state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glBindTexture(GL_TEXTURE_2D, 0); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } static const char* ImGui_ImplSdl_GetClipboardText() { return SDL_GetClipboardText(); } static void ImGui_ImplSdl_SetClipboardText(const char* text) { SDL_SetClipboardText(text); } void ImGui_ImplSdl_KeyCallback(int key, bool down) { ImGuiIO& io = ImGui::GetIO(); if (down) io.KeysDown[key] = true; else io.KeysDown[key] = false; io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); } void ImGui_ImplSdl_CharCallback(unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) io.AddInputCharacter((unsigned short)c); } bool ImGui_ImplSdl_CreateDeviceObjects() { ImGuiIO& io = ImGui::GetIO(); // Build texture unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); // Create texture glGenTextures(1, &g_FontTexture); glBindTexture(GL_TEXTURE_2D, g_FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); // Store our identifier io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; io.Fonts->ClearInputData(); io.Fonts->ClearTexData(); return true; } void ImGui_ImplSdl_InvalidateDeviceObjects() { if (g_FontTexture) { glDeleteTextures(1, &g_FontTexture); ImGui::GetIO().Fonts->TexID = 0; g_FontTexture = 0; } } bool ImGui_ImplSdl_Init(SDL_Window *window) { ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; io.KeyMap[ImGuiKey_A] = SDLK_a; io.KeyMap[ImGuiKey_C] = SDLK_c; io.KeyMap[ImGuiKey_V] = SDLK_v; io.KeyMap[ImGuiKey_X] = SDLK_x; io.KeyMap[ImGuiKey_Y] = SDLK_y; io.KeyMap[ImGuiKey_Z] = SDLK_z; io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText; #ifdef _MSC_VER SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window, &wmInfo); io.ImeWindowHandle = wmInfo.info.win.window; #endif return true; } void ImGui_ImplSdl_Shutdown() { ImGui_ImplSdl_InvalidateDeviceObjects(); ImGui::Shutdown(); } bool ImGui_ImplSdl_NewFrame(SDL_Window *window) { if (!g_FontTexture) ImGui_ImplSdl_CreateDeviceObjects(); ImGuiIO& io = ImGui::GetIO(); bool done(false); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: done = true; break; case SDL_MOUSEWHEEL: if (event.wheel.y>0 ) { g_MouseWheel = 1; } if (event.wheel.y<0 ) { g_MouseWheel = -1; } break; case SDL_TEXTINPUT: ImGui_ImplSdl_CharCallback(event.text.text[0]); break; case SDL_KEYUP: ImGui_ImplSdl_KeyCallback(event.key.keysym.sym&~SDLK_SCANCODE_MASK, false); break; case SDL_KEYDOWN: ImGui_ImplSdl_KeyCallback(event.key.keysym.sym&~SDLK_SCANCODE_MASK, true); break; default: break; } } // Setup display size (every frame to accommodate for window resizing) int w, h; SDL_GetWindowSize(window, &w, &h); io.DisplaySize = ImVec2((float)w, (float)h); // Time Uint32 time = SDL_GetTicks(); double current_time = time / 1000.0; io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); g_Time = current_time; int mx, my; Uint32 mouseMask = SDL_GetMouseState(&mx, &my); // Setup inputs // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) Uint32 windowFlags = SDL_GetWindowFlags(window); if (windowFlags&SDL_WINDOW_MOUSE_FOCUS) { io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) } else { io.MousePos = ImVec2(-1,-1); } for (int i = 0; i < 3; i++) { io.MouseDown[i] = g_MousePressed[i] || (mouseMask&(1<