#include "imgui-SFML.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__APPLE__) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif #ifdef ANDROID #ifdef USE_JNI #include #include #include int openKeyboardIME() { ANativeActivity* activity = sf::getNativeActivity(); JavaVM* vm = activity->vm; JNIEnv* env = activity->env; JavaVMAttachArgs attachargs; attachargs.version = JNI_VERSION_1_6; attachargs.name = "NativeThread"; attachargs.group = nullptr; jint res = vm->AttachCurrentThread(&env, &attachargs); if (res == JNI_ERR) return EXIT_FAILURE; jclass natact = env->FindClass("android/app/NativeActivity"); jclass context = env->FindClass("android/content/Context"); jfieldID fid = env->GetStaticFieldID(context, "INPUT_METHOD_SERVICE", "Ljava/lang/String;"); jobject svcstr = env->GetStaticObjectField(context, fid); jmethodID getss = env->GetMethodID(natact, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); jobject imm_obj = env->CallObjectMethod(activity->clazz, getss, svcstr); jclass imm_cls = env->GetObjectClass(imm_obj); jmethodID toggleSoftInput = env->GetMethodID(imm_cls, "toggleSoftInput", "(II)V"); env->CallVoidMethod(imm_obj, toggleSoftInput, 2, 0); env->DeleteLocalRef(imm_obj); env->DeleteLocalRef(imm_cls); env->DeleteLocalRef(svcstr); env->DeleteLocalRef(context); env->DeleteLocalRef(natact); vm->DetachCurrentThread(); return EXIT_SUCCESS; } int closeKeyboardIME() { ANativeActivity* activity = sf::getNativeActivity(); JavaVM* vm = activity->vm; JNIEnv* env = activity->env; JavaVMAttachArgs attachargs; attachargs.version = JNI_VERSION_1_6; attachargs.name = "NativeThread"; attachargs.group = nullptr; jint res = vm->AttachCurrentThread(&env, &attachargs); if (res == JNI_ERR) return EXIT_FAILURE; jclass natact = env->FindClass("android/app/NativeActivity"); jclass context = env->FindClass("android/content/Context"); jfieldID fid = env->GetStaticFieldID(context, "INPUT_METHOD_SERVICE", "Ljava/lang/String;"); jobject svcstr = env->GetStaticObjectField(context, fid); jmethodID getss = env->GetMethodID(natact, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); jobject imm_obj = env->CallObjectMethod(activity->clazz, getss, svcstr); jclass imm_cls = env->GetObjectClass(imm_obj); jmethodID toggleSoftInput = env->GetMethodID(imm_cls, "toggleSoftInput", "(II)V"); env->CallVoidMethod(imm_obj, toggleSoftInput, 1, 0); env->DeleteLocalRef(imm_obj); env->DeleteLocalRef(imm_cls); env->DeleteLocalRef(svcstr); env->DeleteLocalRef(context); env->DeleteLocalRef(natact); vm->DetachCurrentThread(); return EXIT_SUCCESS; } #endif #endif static_assert(sizeof(GLuint) <= sizeof(ImTextureID), "ImTextureID is not large enough to fit GLuint."); namespace { // various helper functions [[nodiscard]] ImColor toImColor(sf::Color c) { return {int{c.r}, int{c.g}, int{c.b}, int{c.a}}; } [[nodiscard]] ImVec2 toImVec2(const sf::Vector2f& v) { return {v.x, v.y}; } [[nodiscard]] sf::Vector2f toSfVector2f(const ImVec2& v) { return {v.x, v.y}; } [[nodiscard]] ImVec2 getTopLeftAbsolute(const sf::FloatRect& rect) { return toImVec2(toSfVector2f(ImGui::GetCursorScreenPos()) + rect.position); } [[nodiscard]] ImVec2 getDownRightAbsolute(const sf::FloatRect& rect) { return toImVec2(toSfVector2f(ImGui::GetCursorScreenPos()) + rect.position + rect.size); } [[nodiscard]] ImTextureID convertGLTextureHandleToImTextureID(GLuint glTextureHandle) { ImTextureID textureID{}; std::memcpy(&textureID, &glTextureHandle, sizeof(GLuint)); return textureID; } [[nodiscard]] GLuint convertImTextureIDToGLTextureHandle(ImTextureID textureID) { GLuint glTextureHandle = 0; std::memcpy(&glTextureHandle, &textureID, sizeof(GLuint)); return glTextureHandle; } struct SpriteTextureData { ImVec2 uv0; ImVec2 uv1; ImTextureID textureID{}; }; [[nodiscard]] SpriteTextureData getSpriteTextureData(const sf::Sprite& sprite) { const sf::Texture& texture(sprite.getTexture()); const sf::Vector2f textureSize(texture.getSize()); const sf::FloatRect textureRect(sprite.getTextureRect()); return {toImVec2(textureRect.position.componentWiseDiv(textureSize)), toImVec2((textureRect.position + textureRect.size).componentWiseDiv(textureSize)), convertGLTextureHandleToImTextureID(texture.getNativeHandle())}; } void RenderDrawLists(ImDrawData* draw_data); // rendering callback function prototype // Default mapping is XInput gamepad mapping void initDefaultJoystickMapping(); // data constexpr unsigned int NULL_JOYSTICK_ID = sf::Joystick::Count; // Returns first id of connected joystick [[nodiscard]] unsigned int getConnectedJoystickId() { for (unsigned int i = 0; i < sf::Joystick::Count; ++i) { if (sf::Joystick::isConnected(i)) return i; } return NULL_JOYSTICK_ID; } void updateJoystickButtonState(ImGuiIO& io); void updateJoystickDPadState(ImGuiIO& io); void updateJoystickAxisState(ImGuiIO& io); // clipboard functions void setClipboardText(ImGuiContext* /*ctx*/, const char* text) { sf::Clipboard::setString(sf::String::fromUtf8(text, text + std::strlen(text))); } [[nodiscard]] const char* getClipboardText(ImGuiContext* /*ctx*/) { static std::string s_clipboardText; auto tmp = sf::Clipboard::getString().toUtf8(); s_clipboardText.assign(tmp.begin(), tmp.end()); return s_clipboardText.c_str(); } // mouse cursors void updateMouseCursor(sf::Window& window); // Key mappings [[nodiscard]] ImGuiKey keycodeToImGuiKey(sf::Keyboard::Key code); [[nodiscard]] ImGuiKey keycodeToImGuiMod(sf::Keyboard::Key code); struct StickInfo { sf::Joystick::Axis xAxis{sf::Joystick::Axis::X}; sf::Joystick::Axis yAxis{sf::Joystick::Axis::Y}; bool xInverted{false}; bool yInverted{false}; float threshold{15}; }; struct TriggerInfo { sf::Joystick::Axis axis{sf::Joystick::Axis::Z}; float threshold{0}; }; struct WindowContext { const sf::Window* window; ImGuiContext* imContext{ImGui::CreateContext()}; std::optional fontTexture; // internal font atlas which is used if user doesn't set // a custom sf::Texture. bool windowHasFocus; bool mouseMoved{false}; bool mousePressed[3] = {false}; ImGuiMouseCursor lastCursor{ImGuiMouseCursor_COUNT}; bool touchDown[3] = {false}; sf::Vector2i touchPos; unsigned int joystickId{getConnectedJoystickId()}; ImGuiKey joystickMapping[sf::Joystick::ButtonCount] = {ImGuiKey_None}; StickInfo dPadInfo; StickInfo lStickInfo; StickInfo rStickInfo; TriggerInfo lTriggerInfo; TriggerInfo rTriggerInfo; std::optional mouseCursors[ImGuiMouseCursor_COUNT]; #ifdef ANDROID #ifdef USE_JNI bool wantTextInput{false}; #endif #endif WindowContext(const sf::Window* w) : window(w), windowHasFocus(window->hasFocus()) { } ~WindowContext() { ImGui::DestroyContext(imContext); } WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable }; std::vector> s_windowContexts; WindowContext* s_currWindowCtx = nullptr; } // end of anonymous namespace namespace ImGui { namespace SFML { bool Init(sf::RenderWindow& window, bool loadDefaultFont) { return Init(window, window, loadDefaultFont); } bool Init(sf::Window& window, sf::RenderTarget& target, bool loadDefaultFont) { return Init(window, sf::Vector2f(target.getSize()), loadDefaultFont); } bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultFont) { s_currWindowCtx = s_windowContexts.emplace_back(std::make_unique(&window)).get(); ImGui::SetCurrentContext(s_currWindowCtx->imContext); ImGuiIO& io = ImGui::GetIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); // tell ImGui which features we support io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; io.BackendPlatformName = "imgui_impl_sfml"; s_currWindowCtx->joystickId = getConnectedJoystickId(); initDefaultJoystickMapping(); // init rendering io.DisplaySize = toImVec2(displaySize); // clipboard platform_io.Platform_SetClipboardTextFn = setClipboardText; platform_io.Platform_GetClipboardTextFn = getClipboardText; // load mouse cursors const auto loadMouseCursor = [](ImGuiMouseCursor imguiCursorType, sf::Cursor::Type sfmlCursorType) { s_currWindowCtx->mouseCursors[imguiCursorType] = sf::Cursor::createFromSystem(sfmlCursorType); }; loadMouseCursor(ImGuiMouseCursor_Arrow, sf::Cursor::Type::Arrow); loadMouseCursor(ImGuiMouseCursor_TextInput, sf::Cursor::Type::Text); loadMouseCursor(ImGuiMouseCursor_ResizeAll, sf::Cursor::Type::SizeAll); loadMouseCursor(ImGuiMouseCursor_ResizeNS, sf::Cursor::Type::SizeVertical); loadMouseCursor(ImGuiMouseCursor_ResizeEW, sf::Cursor::Type::SizeHorizontal); loadMouseCursor(ImGuiMouseCursor_ResizeNESW, sf::Cursor::Type::SizeBottomLeftTopRight); loadMouseCursor(ImGuiMouseCursor_ResizeNWSE, sf::Cursor::Type::SizeTopLeftBottomRight); loadMouseCursor(ImGuiMouseCursor_Hand, sf::Cursor::Type::Hand); if (loadDefaultFont) { // this will load default font automatically // No need to call AddDefaultFont return UpdateFontTexture(); } return true; } void SetCurrentWindow(const sf::Window& window) { auto found = std::find_if(s_windowContexts.begin(), s_windowContexts.end(), [&](std::unique_ptr& ctx) { return ctx->window->getNativeHandle() == window.getNativeHandle(); }); assert(found != s_windowContexts.end() && "Failed to find the window. Forgot to call ImGui::SFML::Init for the window?"); s_currWindowCtx = found->get(); ImGui::SetCurrentContext(s_currWindowCtx->imContext); } void ProcessEvent(const sf::Window& window, const sf::Event& event) { SetCurrentWindow(window); assert(s_currWindowCtx && "No current window is set - forgot to call ImGui::SFML::Init?"); ImGuiIO& io = ImGui::GetIO(); if (s_currWindowCtx->windowHasFocus) { if (const auto* resized = event.getIf()) { io.DisplaySize = toImVec2(sf::Vector2f(resized->size)); } else if (const auto* mouseMoved = event.getIf()) { const auto [x, y] = sf::Vector2f(mouseMoved->position); io.AddMousePosEvent(x, y); s_currWindowCtx->mouseMoved = true; } else if (const auto* mouseButtonPressed = event.getIf()) { const int button = static_cast(mouseButtonPressed->button); if (button >= 0 && button < 3) { s_currWindowCtx->mousePressed[static_cast(mouseButtonPressed->button)] = true; io.AddMouseButtonEvent(button, true); } } else if (const auto* mouseButtonReleased = event.getIf()) { const int button = static_cast(mouseButtonReleased->button); if (button >= 0 && button < 3) io.AddMouseButtonEvent(button, false); } else if (const auto* touchBegan = event.getIf()) { s_currWindowCtx->mouseMoved = false; const unsigned int button = touchBegan->finger; if (button < 3) s_currWindowCtx->touchDown[touchBegan->finger] = true; } else if (event.is()) { s_currWindowCtx->mouseMoved = false; } else if (const auto* mouseWheelScrolled = event.getIf()) { if (mouseWheelScrolled->wheel == sf::Mouse::Wheel::Vertical || (mouseWheelScrolled->wheel == sf::Mouse::Wheel::Horizontal && io.KeyShift)) { io.AddMouseWheelEvent(0, mouseWheelScrolled->delta); } else if (mouseWheelScrolled->wheel == sf::Mouse::Wheel::Horizontal) { io.AddMouseWheelEvent(mouseWheelScrolled->delta, 0); } } const auto handleKeyChanged = [&io](const auto& keyChanged, bool down) { const ImGuiKey mod = keycodeToImGuiMod(keyChanged.code); // The modifier booleans are not reliable when it's the modifier // itself that's being pressed. Detect these presses directly. if (mod != ImGuiKey_None) { io.AddKeyEvent(mod, down); } else { io.AddKeyEvent(ImGuiMod_Ctrl, keyChanged.control); io.AddKeyEvent(ImGuiMod_Shift, keyChanged.shift); io.AddKeyEvent(ImGuiMod_Alt, keyChanged.alt); io.AddKeyEvent(ImGuiMod_Super, keyChanged.system); } const ImGuiKey key = keycodeToImGuiKey(keyChanged.code); io.AddKeyEvent(key, down); io.SetKeyEventNativeData(key, static_cast(keyChanged.code), -1); }; if (const auto* keyPressed = event.getIf()) { handleKeyChanged(*keyPressed, true); } else if (const auto* keyReleased = event.getIf()) { handleKeyChanged(*keyReleased, false); } else if (const auto* textEntered = event.getIf()) { // Don't handle the event for unprintable characters if (textEntered->unicode >= ' ' && textEntered->unicode != 127) io.AddInputCharacter(textEntered->unicode); } else if (const auto* joystickConnected = event.getIf()) { if (s_currWindowCtx->joystickId == NULL_JOYSTICK_ID) s_currWindowCtx->joystickId = joystickConnected->joystickId; } else if (const auto* joystickDisconnected = event.getIf()) { if (s_currWindowCtx->joystickId == joystickDisconnected->joystickId) // used gamepad was disconnected s_currWindowCtx->joystickId = getConnectedJoystickId(); } } if (event.is()) { io.AddFocusEvent(false); s_currWindowCtx->windowHasFocus = false; } if (event.is()) { io.AddFocusEvent(true); s_currWindowCtx->windowHasFocus = true; } } void Update(sf::RenderWindow& window, sf::Time dt) { Update(window, window, dt); } void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { SetCurrentWindow(window); assert(s_currWindowCtx); // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor const ImGuiMouseCursor mouse_cursor = ImGui::GetIO().MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (s_currWindowCtx->lastCursor != mouse_cursor) { s_currWindowCtx->lastCursor = mouse_cursor; updateMouseCursor(window); } if (!s_currWindowCtx->mouseMoved) { if (sf::Touch::isDown(0)) s_currWindowCtx->touchPos = sf::Touch::getPosition(0, window); Update(s_currWindowCtx->touchPos, sf::Vector2f(target.getSize()), dt); } else { Update(sf::Mouse::getPosition(window), sf::Vector2f(target.getSize()), dt); } } void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::Time dt) { assert(s_currWindowCtx && "No current window is set - forgot to call ImGui::SFML::Init?"); ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = toImVec2(displaySize); io.DeltaTime = dt.asSeconds(); if (s_currWindowCtx->windowHasFocus) { if (io.WantSetMousePos) { sf::Mouse::setPosition(sf::Vector2i(toSfVector2f(io.MousePos))); } else { io.MousePos = toImVec2(sf::Vector2f(mousePos)); } for (unsigned int i = 0; i < 3; i++) { io.MouseDown[i] = s_currWindowCtx->touchDown[i] || sf::Touch::isDown(i) || s_currWindowCtx->mousePressed[i] || sf::Mouse::isButtonPressed((sf::Mouse::Button)i); s_currWindowCtx->mousePressed[i] = false; s_currWindowCtx->touchDown[i] = false; } } #ifdef ANDROID #ifdef USE_JNI if (io.WantTextInput && !s_currWindowCtx->wantTextInput) { openKeyboardIME(); s_currWindowCtx->wantTextInput = true; } if (!io.WantTextInput && s_currWindowCtx->wantTextInput) { closeKeyboardIME(); s_currWindowCtx->wantTextInput = false; } #endif #endif assert(io.Fonts->Fonts.Size > 0); // You forgot to create and set up font // atlas (see createFontTexture) // gamepad navigation if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) && s_currWindowCtx->joystickId != NULL_JOYSTICK_ID) { updateJoystickButtonState(io); updateJoystickDPadState(io); updateJoystickAxisState(io); } ImGui::NewFrame(); } void Render(sf::RenderWindow& window) { SetCurrentWindow(window); Render(static_cast(window)); } void Render(sf::RenderTarget& target) { target.resetGLStates(); target.pushGLStates(); ImGui::Render(); RenderDrawLists(ImGui::GetDrawData()); target.popGLStates(); } void Render() { ImGui::Render(); RenderDrawLists(ImGui::GetDrawData()); } void Shutdown(const sf::Window& window) { const bool needReplacement = (s_currWindowCtx->window->getNativeHandle() == window.getNativeHandle()); // remove window's context auto found = std::find_if(s_windowContexts.begin(), s_windowContexts.end(), [&](std::unique_ptr& ctx) { return ctx->window->getNativeHandle() == window.getNativeHandle(); }); assert(found != s_windowContexts.end() && "Window wasn't inited properly: forgot to call ImGui::SFML::Init(window)?"); s_windowContexts.erase(found); // s_currWindowCtx can become invalid here! // set current context to some window for convenience if needed if (needReplacement) { auto it = s_windowContexts.begin(); if (it != s_windowContexts.end()) { // set to some other window s_currWindowCtx = it->get(); ImGui::SetCurrentContext(s_currWindowCtx->imContext); } else { // no alternatives... s_currWindowCtx = nullptr; ImGui::SetCurrentContext(nullptr); } } } void Shutdown() { s_currWindowCtx = nullptr; ImGui::SetCurrentContext(nullptr); s_windowContexts.clear(); } bool UpdateFontTexture() { assert(s_currWindowCtx); ImGuiIO& io = ImGui::GetIO(); unsigned char* pixels = nullptr; int width = 0; int height = 0; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); sf::Texture newTexture; if (!newTexture.resize(sf::Vector2u(sf::Vector2(width, height)))) { return false; } newTexture.update(pixels); ImTextureID texID = convertGLTextureHandleToImTextureID(newTexture.getNativeHandle()); io.Fonts->SetTexID(texID); s_currWindowCtx->fontTexture = std::move(newTexture); return true; } std::optional& GetFontTexture() { assert(s_currWindowCtx); return s_currWindowCtx->fontTexture; } void SetActiveJoystickId(unsigned int joystickId) { assert(s_currWindowCtx); assert(joystickId < sf::Joystick::Count); s_currWindowCtx->joystickId = joystickId; } void SetJoystickDPadThreshold(float threshold) { assert(s_currWindowCtx); assert(threshold >= 0.f && threshold <= 100.f); s_currWindowCtx->dPadInfo.threshold = threshold; } void SetJoystickLStickThreshold(float threshold) { assert(s_currWindowCtx); assert(threshold >= 0.f && threshold <= 100.f); s_currWindowCtx->lStickInfo.threshold = threshold; } void SetJoystickRStickThreshold(float threshold) { assert(s_currWindowCtx); assert(threshold >= 0.f && threshold <= 100.f); s_currWindowCtx->rStickInfo.threshold = threshold; } void SetJoystickLTriggerThreshold(float threshold) { assert(s_currWindowCtx); assert(threshold >= -100.f && threshold <= 100.f); s_currWindowCtx->lTriggerInfo.threshold = threshold; } void SetJoystickRTriggerThreshold(float threshold) { assert(s_currWindowCtx); assert(threshold >= -100.f && threshold <= 100.f); s_currWindowCtx->rTriggerInfo.threshold = threshold; } void SetJoystickMapping(int key, unsigned int joystickButton) { assert(s_currWindowCtx); assert(key >= ImGuiKey_NamedKey_BEGIN); assert(key < ImGuiKey_NamedKey_END); assert(joystickButton < sf::Joystick::ButtonCount); s_currWindowCtx->joystickMapping[joystickButton] = static_cast(key); } void SetDPadXAxis(sf::Joystick::Axis dPadXAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->dPadInfo.xAxis = dPadXAxis; s_currWindowCtx->dPadInfo.xInverted = inverted; } void SetDPadYAxis(sf::Joystick::Axis dPadYAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->dPadInfo.yAxis = dPadYAxis; s_currWindowCtx->dPadInfo.yInverted = inverted; } void SetLStickXAxis(sf::Joystick::Axis lStickXAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->lStickInfo.xAxis = lStickXAxis; s_currWindowCtx->lStickInfo.xInverted = inverted; } void SetLStickYAxis(sf::Joystick::Axis lStickYAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->lStickInfo.yAxis = lStickYAxis; s_currWindowCtx->lStickInfo.yInverted = inverted; } void SetRStickXAxis(sf::Joystick::Axis rStickXAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->rStickInfo.xAxis = rStickXAxis; s_currWindowCtx->rStickInfo.xInverted = inverted; } void SetRStickYAxis(sf::Joystick::Axis rStickYAxis, bool inverted) { assert(s_currWindowCtx); s_currWindowCtx->rStickInfo.yAxis = rStickYAxis; s_currWindowCtx->rStickInfo.yInverted = inverted; } void SetLTriggerAxis(sf::Joystick::Axis lTriggerAxis) { assert(s_currWindowCtx); s_currWindowCtx->rTriggerInfo.axis = lTriggerAxis; } void SetRTriggerAxis(sf::Joystick::Axis rTriggerAxis) { assert(s_currWindowCtx); s_currWindowCtx->rTriggerInfo.axis = rTriggerAxis; } } // end of namespace SFML /////////////// Image Overloads for sf::Texture void Image(const sf::Texture& texture, const sf::Color& tintColor, const sf::Color& borderColor) { Image(texture, sf::Vector2f(texture.getSize()), tintColor, borderColor); } void Image(const sf::Texture& texture, const sf::Vector2f& size, const sf::Color& tintColor, const sf::Color& borderColor) { ImTextureID textureID = convertGLTextureHandleToImTextureID(texture.getNativeHandle()); ImGui::Image(textureID, toImVec2(size), ImVec2(0, 0), ImVec2(1, 1), toImColor(tintColor), toImColor(borderColor)); } /////////////// Image Overloads for sf::RenderTexture void Image(const sf::RenderTexture& texture, const sf::Color& tintColor, const sf::Color& borderColor) { Image(texture, sf::Vector2f(texture.getSize()), tintColor, borderColor); } void Image(const sf::RenderTexture& texture, const sf::Vector2f& size, const sf::Color& tintColor, const sf::Color& borderColor) { ImTextureID textureID = convertGLTextureHandleToImTextureID(texture.getTexture().getNativeHandle()); ImGui::Image(textureID, toImVec2(size), ImVec2(0, 1), ImVec2(1, 0), // flipped vertically, // because textures in // sf::RenderTexture are // stored this way toImColor(tintColor), toImColor(borderColor)); } /////////////// Image Overloads for sf::Sprite void Image(const sf::Sprite& sprite, const sf::Color& tintColor, const sf::Color& borderColor) { Image(sprite, sprite.getGlobalBounds().size, tintColor, borderColor); } void Image(const sf::Sprite& sprite, const sf::Vector2f& size, const sf::Color& tintColor, const sf::Color& borderColor) { auto [uv0, uv1, textureID] = getSpriteTextureData(sprite); ImGui::Image(textureID, toImVec2(size), uv0, uv1, toImColor(tintColor), toImColor(borderColor)); } /////////////// Image Button Overloads for sf::Texture bool ImageButton(const char* id, const sf::Texture& texture, const sf::Vector2f& size, const sf::Color& bgColor, const sf::Color& tintColor) { ImTextureID textureID = convertGLTextureHandleToImTextureID(texture.getNativeHandle()); return ImGui::ImageButton(id, textureID, toImVec2(size), ImVec2(0, 0), ImVec2(1, 1), toImColor(bgColor), toImColor(tintColor)); } /////////////// Image Button Overloads for sf::RenderTexture bool ImageButton(const char* id, const sf::RenderTexture& texture, const sf::Vector2f& size, const sf::Color& bgColor, const sf::Color& tintColor) { ImTextureID textureID = convertGLTextureHandleToImTextureID(texture.getTexture().getNativeHandle()); return ImGui::ImageButton(id, textureID, toImVec2(size), ImVec2(0, 1), ImVec2(1, 0), // flipped vertically, because textures in // sf::RenderTexture are stored this way toImColor(bgColor), toImColor(tintColor)); } /////////////// Image Button Overloads for sf::Sprite bool ImageButton(const char* id, const sf::Sprite& sprite, const sf::Vector2f& size, const sf::Color& bgColor, const sf::Color& tintColor) { auto [uv0, uv1, textureID] = getSpriteTextureData(sprite); return ImGui::ImageButton(id, textureID, toImVec2(size), uv0, uv1, toImColor(bgColor), toImColor(tintColor)); } /////////////// Draw_list Overloads void DrawLine(const sf::Vector2f& a, const sf::Vector2f& b, const sf::Color& color, float thickness) { ImDrawList* draw_list = ImGui::GetWindowDrawList(); const ImVec2 pos = ImGui::GetCursorScreenPos(); draw_list->AddLine(ImVec2(a.x + pos.x, a.y + pos.y), ImVec2(b.x + pos.x, b.y + pos.y), ColorConvertFloat4ToU32(toImColor(color)), thickness); } void DrawRect(const sf::FloatRect& rect, const sf::Color& color, float rounding, int rounding_corners, float thickness) { ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->AddRect(getTopLeftAbsolute(rect), getDownRightAbsolute(rect), ColorConvertFloat4ToU32(toImColor(color)), rounding, rounding_corners, thickness); } void DrawRectFilled(const sf::FloatRect& rect, const sf::Color& color, float rounding, int rounding_corners) { ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->AddRectFilled(getTopLeftAbsolute(rect), getDownRightAbsolute(rect), ColorConvertFloat4ToU32(toImColor(color)), rounding, rounding_corners); } } // end of namespace ImGui namespace { // copied from imgui/backends/imgui_impl_opengl2.cpp void SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height) { // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor // enabled, vertex/texcoord/color pointers, polygon fill. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // // In order to composite our output buffer we need to preserve alpha glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glShadeModel(GL_SMOOTH); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to // draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single // viewport apps. glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); #ifdef GL_VERSION_ES_CL_1_1 glOrthof(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f); #else glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f); #endif glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } // Rendering callback void RenderDrawLists(ImDrawData* draw_data) { ImGui::GetDrawData(); if (draw_data->CmdListsCount == 0) { return; } const ImGuiIO& io = ImGui::GetIO(); assert(io.Fonts->TexID != (ImTextureID) nullptr); // You forgot to create and set font texture // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != // framebuffer coordinates) const int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); const int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); // Backup GL state // Backup GL state GLint last_texture = 0; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLint last_shade_model = 0; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model); GLint last_tex_env_mode = 0; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); #ifdef GL_VERSION_ES_CL_1_1 GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); #else glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); #endif // Setup desired GL state SetupRenderState(draw_data, fb_width, fb_height); // Will project scissor/clipping rectangles into framebuffer space const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display // which are often (2,2) // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos))); glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, uv))); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to // request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) SetupRenderState(draw_data, fb_width, fb_height); else pcmd->UserCallback(cmd_list, pcmd); } else { // Project scissor/clipping rectangles into framebuffer space ImVec4 clip_rect; clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; if (clip_rect.x < static_cast(fb_width) && clip_rect.y < static_cast(fb_height) && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) { // Apply scissor/clipping rectangle glScissor((int)clip_rect.x, (int)(static_cast(fb_height) - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); // Bind texture, Draw const GLuint textureHandle = convertImTextureIDToGLTextureHandle(pcmd->TextureId); glBindTexture(GL_TEXTURE_2D, textureHandle); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset); } } } } // Restore modified GL state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); glShadeModel((GLenum)last_shade_model); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); #ifdef GL_VERSION_ES_CL_1_1 glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glDisable(GL_SCISSOR_TEST); #endif } void initDefaultJoystickMapping() { ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadFaceDown, 0); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadFaceRight, 1); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadFaceLeft, 2); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadFaceUp, 3); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadL1, 4); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadR1, 5); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadBack, 6); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadStart, 7); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadL3, 9); ImGui::SFML::SetJoystickMapping(ImGuiKey_GamepadR3, 10); ImGui::SFML::SetDPadXAxis(sf::Joystick::Axis::PovX); // D-pad Y axis is inverted on Windows #ifdef _WIN32 ImGui::SFML::SetDPadYAxis(sf::Joystick::Axis::PovY, true); #else ImGui::SFML::SetDPadYAxis(sf::Joystick::Axis::PovY); #endif ImGui::SFML::SetLStickXAxis(sf::Joystick::Axis::X); ImGui::SFML::SetLStickYAxis(sf::Joystick::Axis::Y); ImGui::SFML::SetRStickXAxis(sf::Joystick::Axis::U); ImGui::SFML::SetRStickYAxis(sf::Joystick::Axis::V); ImGui::SFML::SetLTriggerAxis(sf::Joystick::Axis::Z); ImGui::SFML::SetRTriggerAxis(sf::Joystick::Axis::R); ImGui::SFML::SetJoystickDPadThreshold(5.f); ImGui::SFML::SetJoystickLStickThreshold(5.f); ImGui::SFML::SetJoystickRStickThreshold(15.f); ImGui::SFML::SetJoystickLTriggerThreshold(0.f); ImGui::SFML::SetJoystickRTriggerThreshold(0.f); } void updateJoystickButtonState(ImGuiIO& io) { for (int i = 0; i < static_cast(sf::Joystick::ButtonCount); ++i) { const ImGuiKey key = s_currWindowCtx->joystickMapping[i]; if (key != ImGuiKey_None) { const bool isPressed = sf::Joystick::isButtonPressed(s_currWindowCtx->joystickId, static_cast(i)); if (s_currWindowCtx->windowHasFocus || !isPressed) { io.AddKeyEvent(key, isPressed); } } } } void updateJoystickAxis(ImGuiIO& io, ImGuiKey key, sf::Joystick::Axis axis, float threshold, float maxThreshold, bool inverted) { float pos = sf::Joystick::getAxisPosition(s_currWindowCtx->joystickId, axis); if (inverted) { pos = -pos; } const bool passedThreshold = (pos > threshold) == (maxThreshold > threshold); if (passedThreshold && s_currWindowCtx->windowHasFocus) { io.AddKeyAnalogEvent(key, true, std::abs(pos / 100.f)); } else { io.AddKeyAnalogEvent(key, false, 0); } } void updateJoystickAxisPair(ImGuiIO& io, ImGuiKey key1, ImGuiKey key2, sf::Joystick::Axis axis, float threshold, bool inverted) { updateJoystickAxis(io, key1, axis, -threshold, -100, inverted); updateJoystickAxis(io, key2, axis, threshold, 100, inverted); } void updateJoystickDPadState(ImGuiIO& io) { updateJoystickAxisPair(io, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight, s_currWindowCtx->dPadInfo.xAxis, s_currWindowCtx->dPadInfo.threshold, s_currWindowCtx->dPadInfo.xInverted); updateJoystickAxisPair(io, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown, s_currWindowCtx->dPadInfo.yAxis, s_currWindowCtx->dPadInfo.threshold, s_currWindowCtx->dPadInfo.yInverted); } void updateJoystickAxisState(ImGuiIO& io) { updateJoystickAxisPair(io, ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, s_currWindowCtx->lStickInfo.xAxis, s_currWindowCtx->lStickInfo.threshold, s_currWindowCtx->lStickInfo.xInverted); updateJoystickAxisPair(io, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown, s_currWindowCtx->lStickInfo.yAxis, s_currWindowCtx->lStickInfo.threshold, s_currWindowCtx->lStickInfo.yInverted); updateJoystickAxisPair(io, ImGuiKey_GamepadRStickLeft, ImGuiKey_GamepadRStickRight, s_currWindowCtx->rStickInfo.xAxis, s_currWindowCtx->rStickInfo.threshold, s_currWindowCtx->rStickInfo.xInverted); updateJoystickAxisPair(io, ImGuiKey_GamepadRStickUp, ImGuiKey_GamepadRStickDown, s_currWindowCtx->rStickInfo.yAxis, s_currWindowCtx->rStickInfo.threshold, s_currWindowCtx->rStickInfo.yInverted); updateJoystickAxis(io, ImGuiKey_GamepadL2, s_currWindowCtx->lTriggerInfo.axis, s_currWindowCtx->lTriggerInfo.threshold, 100, false); updateJoystickAxis(io, ImGuiKey_GamepadR2, s_currWindowCtx->rTriggerInfo.axis, s_currWindowCtx->rTriggerInfo.threshold, 100, false); } void updateMouseCursor(sf::Window& window) { const ImGuiIO& io = ImGui::GetIO(); if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) { const ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { window.setMouseCursorVisible(false); } else { window.setMouseCursorVisible(true); const sf::Cursor& c = s_currWindowCtx->mouseCursors[cursor] ? *s_currWindowCtx->mouseCursors[cursor] : *s_currWindowCtx->mouseCursors[ImGuiMouseCursor_Arrow]; window.setMouseCursor(c); } } } ImGuiKey keycodeToImGuiKey(sf::Keyboard::Key code) { switch (code) { case sf::Keyboard::Key::Tab: return ImGuiKey_Tab; case sf::Keyboard::Key::Left: return ImGuiKey_LeftArrow; case sf::Keyboard::Key::Right: return ImGuiKey_RightArrow; case sf::Keyboard::Key::Up: return ImGuiKey_UpArrow; case sf::Keyboard::Key::Down: return ImGuiKey_DownArrow; case sf::Keyboard::Key::PageUp: return ImGuiKey_PageUp; case sf::Keyboard::Key::PageDown: return ImGuiKey_PageDown; case sf::Keyboard::Key::Home: return ImGuiKey_Home; case sf::Keyboard::Key::End: return ImGuiKey_End; case sf::Keyboard::Key::Insert: return ImGuiKey_Insert; case sf::Keyboard::Key::Delete: return ImGuiKey_Delete; case sf::Keyboard::Key::Backspace: return ImGuiKey_Backspace; case sf::Keyboard::Key::Space: return ImGuiKey_Space; case sf::Keyboard::Key::Enter: return ImGuiKey_Enter; case sf::Keyboard::Key::Escape: return ImGuiKey_Escape; case sf::Keyboard::Key::Apostrophe: return ImGuiKey_Apostrophe; case sf::Keyboard::Key::Comma: return ImGuiKey_Comma; case sf::Keyboard::Key::Hyphen: return ImGuiKey_Minus; case sf::Keyboard::Key::Period: return ImGuiKey_Period; case sf::Keyboard::Key::Slash: return ImGuiKey_Slash; case sf::Keyboard::Key::Semicolon: return ImGuiKey_Semicolon; case sf::Keyboard::Key::Equal: return ImGuiKey_Equal; case sf::Keyboard::Key::LBracket: return ImGuiKey_LeftBracket; case sf::Keyboard::Key::Backslash: return ImGuiKey_Backslash; case sf::Keyboard::Key::RBracket: return ImGuiKey_RightBracket; case sf::Keyboard::Key::Grave: return ImGuiKey_GraveAccent; // case : return ImGuiKey_CapsLock; // case : return ImGuiKey_ScrollLock; // case : return ImGuiKey_NumLock; // case : return ImGuiKey_PrintScreen; case sf::Keyboard::Key::Pause: return ImGuiKey_Pause; case sf::Keyboard::Key::Numpad0: return ImGuiKey_Keypad0; case sf::Keyboard::Key::Numpad1: return ImGuiKey_Keypad1; case sf::Keyboard::Key::Numpad2: return ImGuiKey_Keypad2; case sf::Keyboard::Key::Numpad3: return ImGuiKey_Keypad3; case sf::Keyboard::Key::Numpad4: return ImGuiKey_Keypad4; case sf::Keyboard::Key::Numpad5: return ImGuiKey_Keypad5; case sf::Keyboard::Key::Numpad6: return ImGuiKey_Keypad6; case sf::Keyboard::Key::Numpad7: return ImGuiKey_Keypad7; case sf::Keyboard::Key::Numpad8: return ImGuiKey_Keypad8; case sf::Keyboard::Key::Numpad9: return ImGuiKey_Keypad9; // case : return ImGuiKey_KeypadDecimal; case sf::Keyboard::Key::Divide: return ImGuiKey_KeypadDivide; case sf::Keyboard::Key::Multiply: return ImGuiKey_KeypadMultiply; case sf::Keyboard::Key::Subtract: return ImGuiKey_KeypadSubtract; case sf::Keyboard::Key::Add: return ImGuiKey_KeypadAdd; // case : return ImGuiKey_KeypadEnter; // case : return ImGuiKey_KeypadEqual; case sf::Keyboard::Key::LControl: return ImGuiKey_LeftCtrl; case sf::Keyboard::Key::LShift: return ImGuiKey_LeftShift; case sf::Keyboard::Key::LAlt: return ImGuiKey_LeftAlt; case sf::Keyboard::Key::LSystem: return ImGuiKey_LeftSuper; case sf::Keyboard::Key::RControl: return ImGuiKey_RightCtrl; case sf::Keyboard::Key::RShift: return ImGuiKey_RightShift; case sf::Keyboard::Key::RAlt: return ImGuiKey_RightAlt; case sf::Keyboard::Key::RSystem: return ImGuiKey_RightSuper; case sf::Keyboard::Key::Menu: return ImGuiKey_Menu; case sf::Keyboard::Key::Num0: return ImGuiKey_0; case sf::Keyboard::Key::Num1: return ImGuiKey_1; case sf::Keyboard::Key::Num2: return ImGuiKey_2; case sf::Keyboard::Key::Num3: return ImGuiKey_3; case sf::Keyboard::Key::Num4: return ImGuiKey_4; case sf::Keyboard::Key::Num5: return ImGuiKey_5; case sf::Keyboard::Key::Num6: return ImGuiKey_6; case sf::Keyboard::Key::Num7: return ImGuiKey_7; case sf::Keyboard::Key::Num8: return ImGuiKey_8; case sf::Keyboard::Key::Num9: return ImGuiKey_9; case sf::Keyboard::Key::A: return ImGuiKey_A; case sf::Keyboard::Key::B: return ImGuiKey_B; case sf::Keyboard::Key::C: return ImGuiKey_C; case sf::Keyboard::Key::D: return ImGuiKey_D; case sf::Keyboard::Key::E: return ImGuiKey_E; case sf::Keyboard::Key::F: return ImGuiKey_F; case sf::Keyboard::Key::G: return ImGuiKey_G; case sf::Keyboard::Key::H: return ImGuiKey_H; case sf::Keyboard::Key::I: return ImGuiKey_I; case sf::Keyboard::Key::J: return ImGuiKey_J; case sf::Keyboard::Key::K: return ImGuiKey_K; case sf::Keyboard::Key::L: return ImGuiKey_L; case sf::Keyboard::Key::M: return ImGuiKey_M; case sf::Keyboard::Key::N: return ImGuiKey_N; case sf::Keyboard::Key::O: return ImGuiKey_O; case sf::Keyboard::Key::P: return ImGuiKey_P; case sf::Keyboard::Key::Q: return ImGuiKey_Q; case sf::Keyboard::Key::R: return ImGuiKey_R; case sf::Keyboard::Key::S: return ImGuiKey_S; case sf::Keyboard::Key::T: return ImGuiKey_T; case sf::Keyboard::Key::U: return ImGuiKey_U; case sf::Keyboard::Key::V: return ImGuiKey_V; case sf::Keyboard::Key::W: return ImGuiKey_W; case sf::Keyboard::Key::X: return ImGuiKey_X; case sf::Keyboard::Key::Y: return ImGuiKey_Y; case sf::Keyboard::Key::Z: return ImGuiKey_Z; case sf::Keyboard::Key::F1: return ImGuiKey_F1; case sf::Keyboard::Key::F2: return ImGuiKey_F2; case sf::Keyboard::Key::F3: return ImGuiKey_F3; case sf::Keyboard::Key::F4: return ImGuiKey_F4; case sf::Keyboard::Key::F5: return ImGuiKey_F5; case sf::Keyboard::Key::F6: return ImGuiKey_F6; case sf::Keyboard::Key::F7: return ImGuiKey_F7; case sf::Keyboard::Key::F8: return ImGuiKey_F8; case sf::Keyboard::Key::F9: return ImGuiKey_F9; case sf::Keyboard::Key::F10: return ImGuiKey_F10; case sf::Keyboard::Key::F11: return ImGuiKey_F11; case sf::Keyboard::Key::F12: return ImGuiKey_F12; default: break; } return ImGuiKey_None; } ImGuiKey keycodeToImGuiMod(sf::Keyboard::Key code) { switch (code) { case sf::Keyboard::Key::LControl: case sf::Keyboard::Key::RControl: return ImGuiMod_Ctrl; case sf::Keyboard::Key::LShift: case sf::Keyboard::Key::RShift: return ImGuiMod_Shift; case sf::Keyboard::Key::LAlt: case sf::Keyboard::Key::RAlt: return ImGuiMod_Alt; case sf::Keyboard::Key::LSystem: case sf::Keyboard::Key::RSystem: return ImGuiMod_Super; default: break; } return ImGuiKey_None; } } // end of anonymous namespace