// dear imgui: Platform Binding for GLFW // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (Requires: GLFW 3.1+) // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW. // [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them. // 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls. // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. // 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()). // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set. // 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). // 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. #include "imgui.h" #include "imgui_impl_glfw.h" // GLFW #include #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 #include // for glfwGetWin32Window #endif #define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING #define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED #define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity #define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale #define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface #pragma comment(lib,"legacy_stdio_definitions.lib") // Data enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, GlfwClientApi_Vulkan }; static GLFWwindow* g_Window = NULL; // Main window static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static double g_Time = 0.0; static bool g_MouseJustPressed[5] = { false, false, false, false, false }; static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL; static GLFWscrollfun g_PrevUserCallbackScroll = NULL; static GLFWkeyfun g_PrevUserCallbackKey = NULL; static GLFWcharfun g_PrevUserCallbackChar = NULL; static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) { return glfwGetClipboardString((GLFWwindow*)user_data); } static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) { glfwSetClipboardString((GLFWwindow*)user_data, text); } void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { if (g_PrevUserCallbackMousebutton != NULL) g_PrevUserCallbackMousebutton(window, button, action, mods); if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed)) g_MouseJustPressed[button] = true; } void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { if (g_PrevUserCallbackScroll != NULL) g_PrevUserCallbackScroll(window, xoffset, yoffset); ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset; io.MouseWheel += (float)yoffset; } enum EUSBMod { MOD_LCTRL=1, MOD_LSHIFT=2, MOD_LALT=4, MOD_LGUI=8, MOD_RCTRL=16, MOD_RSHIFT=32, MOD_RALT=64, MOD_RGUI=128, MOD_LRSHIFT=MOD_LSHIFT+MOD_RSHIFT, MOD_LRCTRL=MOD_LCTRL+MOD_RCTRL, MOD_LRALT=MOD_LALT+MOD_RALT, MOD_LRGUI=MOD_LGUI+MOD_RGUI }; unsigned char glfwkey2usb(int glfwkey) { switch (glfwkey) { case GLFW_KEY_A: return 4; case GLFW_KEY_B: return 5; case GLFW_KEY_C: return 6; case GLFW_KEY_D: return 7; case GLFW_KEY_E: return 8; case GLFW_KEY_F: return 9; case GLFW_KEY_G: return 10; case GLFW_KEY_H: return 11; case GLFW_KEY_I: return 12; case GLFW_KEY_J: return 13; case GLFW_KEY_K: return 14; case GLFW_KEY_L: return 15; case GLFW_KEY_M: return 16; case GLFW_KEY_N: return 17; case GLFW_KEY_O: return 18; case GLFW_KEY_P: return 19; case GLFW_KEY_Q: return 20; case GLFW_KEY_R: return 21; case GLFW_KEY_S: return 22; case GLFW_KEY_T: return 23; case GLFW_KEY_U: return 24; case GLFW_KEY_V: return 25; case GLFW_KEY_W: return 26; case GLFW_KEY_X: return 27; case GLFW_KEY_Y: return 28; case GLFW_KEY_Z: return 29; case GLFW_KEY_1: return 30; case GLFW_KEY_2: return 31; case GLFW_KEY_3: return 32; case GLFW_KEY_4: return 33; case GLFW_KEY_5: return 34; case GLFW_KEY_6: return 35; case GLFW_KEY_7: return 36; case GLFW_KEY_8: return 37; case GLFW_KEY_9: return 38; case GLFW_KEY_0: return 39; case GLFW_KEY_ENTER: return 40; case GLFW_KEY_ESCAPE: return 41; case GLFW_KEY_BACKSPACE: return 42; case GLFW_KEY_TAB: return 43; case GLFW_KEY_SPACE: return 44; case GLFW_KEY_MINUS: return 45; case GLFW_KEY_EQUAL: return 46; case GLFW_KEY_LEFT_BRACKET: return 47; case GLFW_KEY_RIGHT_BRACKET: return 48; case GLFW_KEY_WORLD_2: return 50; // on uk its \ | case GLFW_KEY_BACKSLASH: return 49; // on uk its #~ case GLFW_KEY_SEMICOLON: return 51; case GLFW_KEY_APOSTROPHE: return 52; case GLFW_KEY_GRAVE_ACCENT: return 53; case GLFW_KEY_COMMA: return 54; case GLFW_KEY_PERIOD: return 55; case GLFW_KEY_SLASH: return 56; case GLFW_KEY_CAPS_LOCK: return 57; case GLFW_KEY_F1: return 58; case GLFW_KEY_F2: return 59; case GLFW_KEY_F3: return 60; case GLFW_KEY_F4: return 61; case GLFW_KEY_F5: return 62; case GLFW_KEY_F6: return 63; case GLFW_KEY_F7: return 64; case GLFW_KEY_F8: return 65; case GLFW_KEY_F9: return 66; case GLFW_KEY_F10: return 67; case GLFW_KEY_F11: return 68; case GLFW_KEY_F12: return 69; case GLFW_KEY_PRINT_SCREEN: return 70; case GLFW_KEY_SCROLL_LOCK: return 71; case GLFW_KEY_PAUSE: return 72; case GLFW_KEY_INSERT: return 73; case GLFW_KEY_HOME: return 74; case GLFW_KEY_PAGE_UP: return 75; case GLFW_KEY_DELETE: return 76; case GLFW_KEY_END: return 77; case GLFW_KEY_PAGE_DOWN: return 78; case GLFW_KEY_RIGHT: return 79; case GLFW_KEY_LEFT: return 80; case GLFW_KEY_DOWN: return 81; case GLFW_KEY_UP: return 82; case GLFW_KEY_NUM_LOCK: return 83; case GLFW_KEY_KP_DIVIDE: return 84; case GLFW_KEY_KP_MULTIPLY: return 85; case GLFW_KEY_KP_SUBTRACT: return 86; case GLFW_KEY_KP_ADD: return 87; case GLFW_KEY_KP_ENTER: return 88; case GLFW_KEY_KP_1: return 89; case GLFW_KEY_KP_2: return 90; case GLFW_KEY_KP_3: return 91; case GLFW_KEY_KP_4: return 92; case GLFW_KEY_KP_5: return 93; case GLFW_KEY_KP_6: return 94; case GLFW_KEY_KP_7: return 95; case GLFW_KEY_KP_8: return 96; case GLFW_KEY_KP_9: return 97; case GLFW_KEY_KP_0: return 98; case GLFW_KEY_KP_DECIMAL: return 99; default: return 0; } }; //extern "C" void USBKeyEvent(unsigned char mods, unsigned char keys[6]); void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (g_PrevUserCallbackKey != NULL) g_PrevUserCallbackKey(window, key, scancode, action, mods); ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) io.KeysDown[key] = true; if (action == GLFW_RELEASE) io.KeysDown[key] = false; // Modifiers are not reliable across systems io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; if (action==GLFW_REPEAT) return; // usb emulation mods=0; if (io.KeysDown[GLFW_KEY_LEFT_CONTROL]) mods|=1; if (io.KeysDown[GLFW_KEY_LEFT_SHIFT]) mods|=2; if (io.KeysDown[GLFW_KEY_LEFT_ALT]) mods|=4; if (io.KeysDown[GLFW_KEY_LEFT_SUPER]) mods|=8; if (io.KeysDown[GLFW_KEY_RIGHT_CONTROL]) mods|=16; if (io.KeysDown[GLFW_KEY_RIGHT_SHIFT]) mods|=32; if (io.KeysDown[GLFW_KEY_RIGHT_ALT]) mods|=64; if (io.KeysDown[GLFW_KEY_RIGHT_SUPER]) mods|=128; unsigned char keys[6]={}; int n=0; for (int i=0;i BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; } #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; } int axes_count = 0, buttons_count = 0; const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f); MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); #undef MAP_BUTTON #undef MAP_ANALOG if (axes_count > 0 && buttons_count > 0) io.BackendFlags |= ImGuiBackendFlags_HasGamepad; else io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; } void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h; glfwGetWindowSize(g_Window, &w, &h); glfwGetFramebufferSize(g_Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); // Setup time step double current_time = glfwGetTime(); io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); g_Time = current_time; ImGui_ImplGlfw_UpdateMousePosAndButtons(); ImGui_ImplGlfw_UpdateMouseCursor(); // Update game controllers (if enabled and available) ImGui_ImplGlfw_UpdateGamepads(); }