From ea39841fcd5338dc0b041c24ef81613d95b066e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Feb 2023 22:23:23 +0100 Subject: [PATCH 1/6] Examples: (Again, but better) made SDL+GL and GLFW+GL examples build with Emscripten. (#2492, #2494, #3699, #3705) --- docs/CHANGELOG.txt | 3 +- examples/example_glfw_opengl3/main.cpp | 16 ++++++++ examples/example_sdl_opengl3/main.cpp | 16 ++++++++ .../emscripten/emscripten_mainloop_stub.h | 37 +++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 examples/libs/emscripten/emscripten_mainloop_stub.h diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 264660d5..60c49b4e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -98,7 +98,8 @@ All changes: - Backends: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation). (#6117, #4116, #3632) [@tonygrue, @bfierz] - Examples: refactored SDL+GL and GLFW+GL examples to compile with Emscripten. - (the dedicated example_emscripten_opengl3/ has been removed) (#2492, #2494, #3699, #3705) + (#2492, #2494, #3699, #3705) [@ocornut, @nicolasnoble] + The dedicated example_emscripten_opengl3/ has been removed. - Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx] diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 78e67500..6c0ea101 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -20,6 +20,11 @@ #pragma comment(lib, "legacy_stdio_definitions") #endif +// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -85,6 +90,7 @@ int main(int, char**) // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. // - Read 'docs/FONTS.md' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); @@ -99,7 +105,14 @@ int main(int, char**) ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop +#ifdef __EMSCRIPTEN__ + // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. + // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. + io.IniFilename = NULL; + EMSCRIPTEN_MAINLOOP_BEGIN +#else while (!glfwWindowShouldClose(window)) +#endif { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. @@ -161,6 +174,9 @@ int main(int, char**) glfwSwapBuffers(window); } +#ifdef __EMSCRIPTEN__ + EMSCRIPTEN_MAINLOOP_END; +#endif // Cleanup ImGui_ImplOpenGL3_Shutdown(); diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 41b7aa1a..bc660a51 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -14,6 +14,11 @@ #include #endif +// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + // Main code int main(int, char**) { @@ -81,6 +86,7 @@ int main(int, char**) // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. // - Read 'docs/FONTS.md' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); @@ -96,7 +102,14 @@ int main(int, char**) // Main loop bool done = false; +#ifdef __EMSCRIPTEN__ + // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. + // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. + io.IniFilename = NULL; + EMSCRIPTEN_MAINLOOP_BEGIN +#else while (!done) +#endif { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. @@ -163,6 +176,9 @@ int main(int, char**) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(window); } +#ifdef __EMSCRIPTEN__ + EMSCRIPTEN_MAINLOOP_END; +#endif // Cleanup ImGui_ImplOpenGL3_Shutdown(); diff --git a/examples/libs/emscripten/emscripten_mainloop_stub.h b/examples/libs/emscripten/emscripten_mainloop_stub.h new file mode 100644 index 00000000..05cf60fe --- /dev/null +++ b/examples/libs/emscripten/emscripten_mainloop_stub.h @@ -0,0 +1,37 @@ +// What does this file solves? +// - Since Dear ImGui 1.00 we took pride that most of our examples applications had their entire +// main-loop inside the main() function. That's because: +// - It makes the examples easier to read, keeping the code sequential. +// - It permit the use of local variables, making it easier to try things and perform quick +// changes when someone needs to quickly test something (vs having to structure the example +// in order to pass data around). This is very important because people use those examples +// to craft easy-to-past repro when they want to discuss features or report issues. +// - It conveys at a glance that this is a no-BS framework, it won't take your main loop away from you. +// - It is generally nice and elegant. +// - However, comes Emscripten... it is a wonderful and magical tech but it requires a "main loop" function. +// - Only some of our examples would run on Emscripten. Typically the ones rendering with GL or WGPU ones. +// - I tried to refactor those examples but felt it was problematic that other examples didn't follow the +// same layout. Why would the SDL+GL example be structured one way and the SGL+DX11 be structured differently? +// Especially as we are trying hard to convey that using a Dear ImGui backend in an *existing application* +// should requires only a few dozens lines of code, and this should be consistent and symmetrical for all backends. +// - So the next logical step was to refactor all examples to follow that layout of using a "main loop" function. +// This worked, but it made us lose all the nice things we had... + +// Since only about 3 examples really need to run with Emscripten, here's our solution: +// - Use some weird macros and capturing lambda to turn a loop in main() into a function. +// - Hide all that crap in this file so it doesn't make our examples unusually ugly. +// As a stance and principle of Dear ImGui development we don't use C++ headers and we don't +// want to suggest to the newcomer that we would ever use C++ headers as this would affect +// the initial judgment of many of our target audience. +// - Technique is based on this idea: https://github.com/ocornut/imgui/pull/2492/ +#ifdef __EMSCRIPTEN__ +#include +#include +static std::function MainLoopForEmscriptenP; +static void MainLoopForEmscripten() { MainLoopForEmscriptenP(); } +#define EMSCRIPTEN_MAINLOOP_BEGIN MainLoopForEmscriptenP = [&]() +#define EMSCRIPTEN_MAINLOOP_END ; emscripten_set_main_loop(MainLoopForEmscripten, 0, true) +#else +#define EMSCRIPTEN_MAINLOOP_BEGIN +#define EMSCRIPTEN_MAINLOOP_END +#endif From d6ea56dfd97ac5d7caab2208b11e0e12fa2377d9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Feb 2023 22:50:43 +0100 Subject: [PATCH 2/6] Tables: amend f799a29 with a better solution + fix potential overflow (#6140) --- imgui.cpp | 9 +++++++++ imgui_internal.h | 1 + imgui_tables.cpp | 4 +--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b729f66d..e04d623f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7514,6 +7514,15 @@ ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) return id; } +ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed) +{ + ImGuiID id = ImHashData(&n, sizeof(n), seed); + ImGuiContext& g = *GImGui; + if (g.DebugHookIdInfo == id) + DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); + return id; +} + void ImGui::PopID() { ImGuiWindow* window = GImGui->CurrentWindow; diff --git a/imgui_internal.h b/imgui_internal.h index 73512921..021a24ec 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2802,6 +2802,7 @@ namespace ImGui IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function. IMGUI_API void PushOverrideID(ImGuiID id); // Push given value as-is at the top of the ID stack (whereas PushID combines old and new hashes) IMGUI_API ImGuiID GetIDWithSeed(const char* str_id_begin, const char* str_id_end, ImGuiID seed); + IMGUI_API ImGuiID GetIDWithSeed(int n, ImGuiID seed); // Basic Helpers for widget code IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 8452c06e..06a21ed8 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -366,9 +366,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); if (table->InstanceDataExtra.Size < instance_no) table->InstanceDataExtra.push_back(ImGuiTableInstanceData()); - char instance_desc[12]; - int instance_desc_len = ImFormatString(instance_desc, IM_ARRAYSIZE(instance_desc), "##Instance%d", instance_no); - instance_id = GetIDWithSeed(instance_desc, instance_desc + instance_desc_len, id); + instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instance" followed by (int)instance_no in ID stack. } else { From 1b27ac982f15f3083699c62cc0bba596b71282a7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Feb 2023 11:54:50 +0100 Subject: [PATCH 3/6] Backends+Examples: SDL2: renamed imgui_impl_sdl.cpp/.h to imgui_impl_sdl2.cpp/.h. (#6146) + CI: Update Windows CI to update SDL 2.26.3 instead of 2.0.10 --- .github/workflows/build.yml | 62 +++++++++---------- .gitignore | 10 +-- ...imgui_impl_sdl.cpp => imgui_impl_sdl2.cpp} | 5 +- .../{imgui_impl_sdl.h => imgui_impl_sdl2.h} | 0 docs/BACKENDS.md | 10 +-- docs/CHANGELOG.txt | 20 ++++-- docs/EXAMPLES.md | 30 ++++----- examples/example_apple_metal/README.md | 2 +- .../build_win32.bat | 4 +- .../example_sdl2_directx11.vcxproj} | 10 +-- .../example_sdl2_directx11.vcxproj.filters} | 10 +-- .../main.cpp | 2 +- .../Makefile | 4 +- .../main.mm | 2 +- .../Makefile | 4 +- examples/example_sdl2_opengl2/README.md | 29 +++++++++ .../build_win32.bat | 4 +- .../example_sdl2_opengl2.vcxproj} | 8 +-- .../example_sdl2_opengl2.vcxproj.filters} | 6 +- .../main.cpp | 6 +- .../Makefile | 4 +- .../Makefile.emscripten | 2 +- .../README.md | 10 +-- .../build_win32.bat | 4 +- .../example_sdl2_opengl3.vcxproj} | 6 +- .../example_sdl2_opengl3.vcxproj.filters} | 12 ++-- .../main.cpp | 2 +- .../Makefile | 4 +- examples/example_sdl2_sdlrenderer/README.md | 25 ++++++++ .../build_win32.bat | 4 +- .../example_sdl2_sdlrenderer.vcxproj} | 8 +-- .../example_sdl2_sdlrenderer.vcxproj.filters} | 6 +- .../main.cpp | 2 +- .../build_win32.bat | 4 +- .../example_sdl2_vulkan.vcxproj} | 8 +-- .../example_sdl2_vulkan.vcxproj.filters} | 6 +- .../main.cpp | 2 +- examples/example_sdl_opengl2/README.md | 29 --------- examples/example_sdl_sdlrenderer/README.md | 25 -------- examples/imgui_examples.sln | 10 +-- imgui.cpp | 1 + 41 files changed, 206 insertions(+), 196 deletions(-) rename backends/{imgui_impl_sdl.cpp => imgui_impl_sdl2.cpp} (99%) rename backends/{imgui_impl_sdl.h => imgui_impl_sdl2.h} (100%) rename examples/{example_sdl_directx11 => example_sdl2_directx11}/build_win32.bat (78%) rename examples/{example_sdl_directx11/example_sdl_directx11.vcxproj => example_sdl2_directx11/example_sdl2_directx11.vcxproj} (97%) rename examples/{example_sdl_directx11/example_sdl_directx11.vcxproj.filters => example_sdl2_directx11/example_sdl2_directx11.vcxproj.filters} (93%) rename examples/{example_sdl_directx11 => example_sdl2_directx11}/main.cpp (99%) rename examples/{example_sdl_metal => example_sdl2_metal}/Makefile (90%) rename examples/{example_sdl_metal => example_sdl2_metal}/main.mm (99%) rename examples/{example_sdl_opengl2 => example_sdl2_opengl2}/Makefile (94%) create mode 100644 examples/example_sdl2_opengl2/README.md rename examples/{example_sdl_opengl2 => example_sdl2_opengl2}/build_win32.bat (73%) rename examples/{example_sdl_opengl2/example_sdl_opengl2.vcxproj => example_sdl2_opengl2/example_sdl2_opengl2.vcxproj} (98%) rename examples/{example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters => example_sdl2_opengl2/example_sdl2_opengl2.vcxproj.filters} (93%) rename examples/{example_sdl_opengl2 => example_sdl2_opengl2}/main.cpp (98%) rename examples/{example_sdl_opengl3 => example_sdl2_opengl3}/Makefile (95%) rename examples/{example_sdl_opengl3 => example_sdl2_opengl3}/Makefile.emscripten (96%) rename examples/{example_sdl_opengl3 => example_sdl2_opengl3}/README.md (81%) rename examples/{example_sdl_opengl3 => example_sdl2_opengl3}/build_win32.bat (73%) rename examples/{example_sdl_opengl3/example_sdl_opengl3.vcxproj => example_sdl2_opengl3/example_sdl2_opengl3.vcxproj} (98%) rename examples/{example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters => example_sdl2_opengl3/example_sdl2_opengl3.vcxproj.filters} (93%) rename examples/{example_sdl_opengl3 => example_sdl2_opengl3}/main.cpp (99%) rename examples/{example_sdl_sdlrenderer => example_sdl2_sdlrenderer}/Makefile (93%) create mode 100644 examples/example_sdl2_sdlrenderer/README.md rename examples/{example_sdl_sdlrenderer => example_sdl2_sdlrenderer}/build_win32.bat (71%) rename examples/{example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj => example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj} (97%) rename examples/{example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters => example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj.filters} (93%) rename examples/{example_sdl_sdlrenderer => example_sdl2_sdlrenderer}/main.cpp (99%) rename examples/{example_sdl_vulkan => example_sdl2_vulkan}/build_win32.bat (77%) rename examples/{example_sdl_vulkan/example_sdl_vulkan.vcxproj => example_sdl2_vulkan/example_sdl2_vulkan.vcxproj} (98%) rename examples/{example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters => example_sdl2_vulkan/example_sdl2_vulkan.vcxproj.filters} (93%) rename examples/{example_sdl_vulkan => example_sdl2_vulkan}/main.cpp (99%) delete mode 100644 examples/example_sdl_opengl2/README.md delete mode 100644 examples/example_sdl_sdlrenderer/README.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3b758b6..bd0c4a56 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,9 +26,9 @@ jobs: - name: Install Dependencies shell: powershell run: | - Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip" -OutFile "SDL2-devel-2.0.10-VC.zip" - Expand-Archive -Path SDL2-devel-2.0.10-VC.zip - echo "SDL2_DIR=$(pwd)\SDL2-devel-2.0.10-VC\SDL2-2.0.10\" >>${env:GITHUB_ENV} + Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.26.3-VC.zip" -OutFile "SDL2-devel-2.26.3-VC.zip" + Expand-Archive -Path SDL2-devel-2.26.3-VC.zip + echo "SDL2_DIR=$(pwd)\SDL2-devel-2.26.3-VC\SDL2-2.26.3\" >>${env:GITHUB_ENV} Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip Expand-Archive -Path vulkan-sdk-1.1.121.2.zip @@ -123,23 +123,23 @@ jobs: run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build Win32 example_sdl_vulkan + - name: Build Win32 example_sdl2_vulkan shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build Win32 example_sdl_opengl2 + - name: Build Win32 example_sdl2_opengl2 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build Win32 example_sdl_opengl3 + - name: Build Win32 example_sdl2_opengl3 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' - - name: Build Win32 example_sdl_directx11 + - name: Build Win32 example_sdl2_directx11 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' if: github.event_name == 'workflow_run' - name: Build Win32 example_win32_directx9 @@ -168,24 +168,24 @@ jobs: shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' - - name: Build x64 example_sdl_vulkan + - name: Build x64 example_sdl2_vulkan shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build x64 example_sdl_opengl2 + - name: Build x64 example_sdl2_opengl2 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build x64 example_sdl_opengl3 + - name: Build x64 example_sdl2_opengl3 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' if: github.event_name == 'workflow_run' - - name: Build x64 example_sdl_directx11 + - name: Build x64 example_sdl2_directx11 shell: cmd - run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release' + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release' - name: Build x64 example_win32_directx9 shell: cmd @@ -389,12 +389,12 @@ jobs: run: make -C examples/example_glfw_opengl3 if: github.event_name == 'workflow_run' - - name: Build example_sdl_opengl2 - run: make -C examples/example_sdl_opengl2 + - name: Build example_sdl2_opengl2 + run: make -C examples/example_sdl2_opengl2 if: github.event_name == 'workflow_run' - - name: Build example_sdl_opengl3 - run: make -C examples/example_sdl_opengl3 + - name: Build example_sdl2_opengl3 + run: make -C examples/example_sdl2_opengl3 - name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp @@ -443,15 +443,15 @@ jobs: - name: Build example_glfw_metal run: make -C examples/example_glfw_metal - - name: Build example_sdl_metal - run: make -C examples/example_sdl_metal + - name: Build example_sdl2_metal + run: make -C examples/example_sdl2_metal - - name: Build example_sdl_opengl2 - run: make -C examples/example_sdl_opengl2 + - name: Build example_sdl2_opengl2 + run: make -C examples/example_sdl2_opengl2 if: github.event_name == 'workflow_run' - - name: Build example_sdl_opengl3 - run: make -C examples/example_sdl_opengl3 + - name: Build example_sdl2_opengl3 + run: make -C examples/example_sdl2_opengl3 - name: Build example_apple_metal run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos @@ -482,12 +482,12 @@ jobs: emsdk-master/emsdk install latest emsdk-master/emsdk activate latest - - name: Build example_sdl_opengl3 with Emscripten + - name: Build example_sdl2_opengl3 with Emscripten run: | pushd emsdk-master source ./emsdk_env.sh popd - make -C examples/example_sdl_opengl3 -f Makefile.emscripten + make -C examples/example_sdl2_opengl3 -f Makefile.emscripten - name: Build example_emscripten_wgpu run: | diff --git a/.gitignore b/.gitignore index 3fd051e4..dc716466 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,7 @@ examples/*.o.tmp examples/*.out.js examples/*.out.wasm examples/example_glfw_opengl3/web/* -examples/example_sdl_opengl3/web/* +examples/example_sdl2_opengl3/web/* examples/example_emscripten_wgpu/web/* ## JetBrains IDE artifacts @@ -54,7 +54,7 @@ examples/example_glfw_opengl2/example_glfw_opengl2 examples/example_glfw_opengl3/example_glfw_opengl3 examples/example_glut_opengl2/example_glut_opengl2 examples/example_null/example_null -examples/example_sdl_metal/example_sdl_metal -examples/example_sdl_opengl2/example_sdl_opengl2 -examples/example_sdl_opengl3/example_sdl_opengl3 -examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer +examples/example_sdl2_metal/example_sdl2_metal +examples/example_sdl2_opengl2/example_sdl2_opengl2 +examples/example_sdl2_opengl3/example_sdl2_opengl3 +examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl2.cpp similarity index 99% rename from backends/imgui_impl_sdl.cpp rename to backends/imgui_impl_sdl2.cpp index bdb4b491..9055b55d 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2023-02-07: *BREAKING CHANGE* Renamed this backend file from imgui_impl_sdl.cpp/.h to imgui_impl_sdl2.cpp/.h in prevision for the future release of SDL3. // 2023-02-02: Avoid calling SDL_SetCursor() when cursor has not changed, as the function is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version). // 2023-02-02: Added support for SDL 2.0.18+ preciseX/preciseY mouse wheel data for smooth scrolling + Scaling X value on Emscripten (bug?). (#4019, #6096) // 2023-02-02: Removed SDL_MOUSEWHEEL value clamping, as values seem correct in latest Emscripten. (#4019) @@ -68,7 +69,7 @@ // 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" // SDL #include @@ -349,7 +350,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer) // Setup backend capabilities flags ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)(); io.BackendPlatformUserData = (void*)bd; - io.BackendPlatformName = "imgui_impl_sdl"; + io.BackendPlatformName = "imgui_impl_sdl2"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) diff --git a/backends/imgui_impl_sdl.h b/backends/imgui_impl_sdl2.h similarity index 100% rename from backends/imgui_impl_sdl.h rename to backends/imgui_impl_sdl2.h diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 6a7fa720..c6edde0a 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -6,7 +6,7 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/BACKE your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h. - The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, and windowing.
- e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc. + e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl2.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl2.cpp)), etc. - The 'Renderer' backends are in charge of: creating atlas texture, and rendering imgui draw data.
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc. @@ -62,7 +62,7 @@ List of Platforms Backends: imgui_impl_android.cpp ; Android native app API imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) - imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org + imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_win32.cpp ; Win32 native API (Windows) imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!) @@ -83,8 +83,8 @@ List of high-level Frameworks Backends (combining Platform + Renderer): imgui_impl_allegro5.cpp -Emscripten is also supported. -The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible. +Emscripten is also supported! +The SDL+GL, GLFW+GL and SDL+WebGPU examples are all ready to build and run with Emscripten. ### Backends for third-party frameworks, graphics API or other languages @@ -97,7 +97,7 @@ If you are not sure which backend to use, the recommended platform/frameworks fo |Library |Website |Backend |Note | |--------|--------|--------|-----| | GLFW | https://github.com/glfw/glfw | imgui_impl_glfw.cpp | | -| SDL2 | https://www.libsdl.org | imgui_impl_sdl.cpp | | +| SDL2 | https://www.libsdl.org | imgui_impl_sdl2.cpp | | | Sokol | https://github.com/floooh/sokol | [util/sokol_imgui.h](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h) | Lower-level than GLFW/SDL | diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 60c49b4e..066e952a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,14 @@ HOW TO UPDATE? VERSION 1.89.3 (In Progress) ----------------------------------------------------------------------- +Breaking Changes: + +- Backends+Examples: SDL2: renamed all unnumbered references to "sdl" to "sdl2". + This is in prevision for the future release of SDL3 (#6146) + - imgui_impl_sdl.cpp -> imgui_impl_sdl2.cpp + - imgui_impl_sdl.h -> imgui_impl_sdl2.h + - example_sdl_xxxx/ -> example_sdl2_xxxx/ (folders and projects) + All changes: - Inputs, Scrolling: Made horizontal scroll wheel and horizontal scroll direction consistent @@ -83,12 +91,12 @@ All changes: hasPreciseScrollingDeltas==false (e.g. non-Apple mices). - Backends: Win32: flipping WM_MOUSEHWHEEL value to match other backends and offer consistent horizontal scrolling direction. (#4019) -- Backends: SDL: flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and +- Backends: SDL2: flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and offer consistent horizontal scrolling direction. (#4019) -- Backends: SDL: Removed SDL_MOUSEWHEEL value clamping. (#4019, #6096, #6081) -- Backends: SDL: Added support for SDL 2.0.18+ preciseX/preciseY mouse wheel data +- Backends: SDL2: Removed SDL_MOUSEWHEEL value clamping. (#4019, #6096, #6081) +- Backends: SDL2: Added support for SDL 2.0.18+ preciseX/preciseY mouse wheel data for smooth scrolling as reported by SDL. (#4019, #6096) -- Backends: SDL: Avoid calling SDL_SetCursor() when cursor has not changed, as the function +- Backends: SDL2: Avoid calling SDL_SetCursor() when cursor has not changed, as the function is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version). (#6113) - Backends: GLFW: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096) [@ocornut, @wolfpld, @tolopolarity] @@ -97,13 +105,13 @@ All changes: the 'window' parameter. (#6142) - Backends: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation). (#6117, #4116, #3632) [@tonygrue, @bfierz] -- Examples: refactored SDL+GL and GLFW+GL examples to compile with Emscripten. +- Examples: refactored SDL2+GL and GLFW+GL examples to compile with Emscripten. (#2492, #2494, #3699, #3705) [@ocornut, @nicolasnoble] The dedicated example_emscripten_opengl3/ has been removed. - Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx] -- Examples: SDL+SDL_Renderer: Added call to SDL_RenderSetScale() to display is correct on a +- Examples: SDL2+SDL_Renderer: Added call to SDL_RenderSetScale() to display is correct on a Retina display (albeit lower-res as our other unmodified examples). (#6121, #6065, #5931). diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 48203341..92f46846 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -107,7 +107,7 @@ OSX + OpenGL2 example.
[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/)
Emcripten + GLFW + WebGPU example.
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp -Note that the 'example_glfw_opengl3' and 'example_sdl_opengl3' examples also supports Emscripten! +Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten! [example_glfw_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_metal/)
GLFW (Mac) + Metal example.
@@ -146,40 +146,40 @@ Null example, compile and link imgui, create context, run headless with no input This is used to quickly test compilation of core imgui files in as many setups as possible. Because this application doesn't create a window nor a graphic context, there's no graphics output. -[example_sdl_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_directx11/)
+[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/)
SDL2 + DirectX11 example, Windows only.
-= main.cpp + imgui_impl_sdl.cpp + imgui_impl_dx11.cpp
-This to demonstrate usage of DirectX with SDL. += main.cpp + imgui_impl_sdl2.cpp + imgui_impl_dx11.cpp
+This to demonstrate usage of DirectX with SDL2. -[example_sdl_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_metal/)
-SDL2 (Mac) + Metal example.
-= main.mm + imgui_impl_sdl.cpp + imgui_impl_metal.mm +[example_sdl2_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_metal/)
+SDL2 + Metal example, Mac only.
+= main.mm + imgui_impl_sdl2.cpp + imgui_impl_metal.mm -[example_sdl_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl2/)
+[example_sdl2_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_opengl2/)
SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline).
-= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl2.cpp
+= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl2.cpp
**DO NOT USE OPENGL2 CODE IF YOUR CODE/ENGINE IS USING GL OR WEBGL (SHADERS, VBO, VAO, etc.)**
This code is mostly provided as a reference to learn about Dear ImGui integration, because it is shorter. If your code is using GL3+ context or any semi modern GL calls, using this renderer is likely to make things more complicated, will require your code to reset many GL attributes to their initial state, and might confuse your GPU driver. One star, not recommended. -[example_sdl_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl3/)
+[example_sdl2_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_opengl3/)
SDL2 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example.
-= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp
+= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp
This uses more modern GL calls and custom shaders.
This support building with Emscripten and targetting WebGL.
Prefer using that if you are using modern GL or WebGL in your application. -[example_sdl_sdlrenderer/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_sdlrenderer/)
+[example_sdl2_sdlrenderer/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_sdlrenderer/)
SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer (most graphics backends are supported underneath)
-= main.cpp + imgui_impl_sdl.cpp + imgui_impl_sdlrenderer.cpp
+= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer.cpp
This requires SDL 2.0.18+ (released November 2021)
We do not really recommend using SDL_Renderer as it is a rather primitive API. -[example_sdl_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_vulkan/)
+[example_sdl2_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/)
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example.
-= main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp
+= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_vulkan.cpp
This is quite long and tedious, because: Vulkan.
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. diff --git a/examples/example_apple_metal/README.md b/examples/example_apple_metal/README.md index c13df2f1..48a2b570 100644 --- a/examples/example_apple_metal/README.md +++ b/examples/example_apple_metal/README.md @@ -4,7 +4,7 @@ This example shows how to integrate Dear ImGui with Metal. It is based on the "cross-platform" game template provided with Xcode as of Xcode 9. -Consider basing your work off the example_glfw_metal/ or example_sdl_metal/ examples. They are better supported and will be portable unlike this one. +Consider basing your work off the example_glfw_metal/ or example_sdl2_metal/ examples. They are better supported and will be portable unlike this one. diff --git a/examples/example_sdl_directx11/build_win32.bat b/examples/example_sdl2_directx11/build_win32.bat similarity index 78% rename from examples/example_sdl_directx11/build_win32.bat rename to examples/example_sdl2_directx11/build_win32.bat index b9308270..54f30fc9 100644 --- a/examples/example_sdl_directx11/build_win32.bat +++ b/examples/example_sdl2_directx11/build_win32.bat @@ -1,8 +1,8 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. @set OUT_DIR=Debug -@set OUT_EXE=example_sdl_directx11 +@set OUT_EXE=example_sdl2_directx11 @set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" -@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp @set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib mkdir %OUT_DIR% cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj similarity index 97% rename from examples/example_sdl_directx11/example_sdl_directx11.vcxproj rename to examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj index ac636d2f..27da4835 100644 --- a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj +++ b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj @@ -20,9 +20,9 @@ {9E1987E3-1F19-45CA-B9C9-D31E791836D8} - example_sdl_directx11 + example_sdl2_directx11 8.1 - example_sdl_directx11 + example_sdl2_directx11 @@ -161,16 +161,16 @@ + - + - @@ -179,4 +179,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj.filters similarity index 93% rename from examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters rename to examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj.filters index b9e2b1e9..3476d843 100644 --- a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters +++ b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj.filters @@ -18,10 +18,10 @@ imgui - + sources - + sources @@ -44,10 +44,10 @@ imgui - + sources - + sources @@ -57,4 +57,4 @@ imgui - \ No newline at end of file + diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp similarity index 99% rename from examples/example_sdl_directx11/main.cpp rename to examples/example_sdl2_directx11/main.cpp index ba822c02..58711e3e 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -4,7 +4,7 @@ // Read online: https://github.com/ocornut/imgui/tree/master/docs #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_dx11.h" #include #include diff --git a/examples/example_sdl_metal/Makefile b/examples/example_sdl2_metal/Makefile similarity index 90% rename from examples/example_sdl_metal/Makefile rename to examples/example_sdl2_metal/Makefile index 2167a98f..53c5f75d 100644 --- a/examples/example_sdl_metal/Makefile +++ b/examples/example_sdl2_metal/Makefile @@ -6,11 +6,11 @@ #CXX = g++ #CXX = clang++ -EXE = example_sdl_metal +EXE = example_sdl2_metal IMGUI_DIR = ../.. SOURCES = main.mm SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_metal.mm +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_metal.mm OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore diff --git a/examples/example_sdl_metal/main.mm b/examples/example_sdl2_metal/main.mm similarity index 99% rename from examples/example_sdl_metal/main.mm rename to examples/example_sdl2_metal/main.mm index ff7c5086..01cf5fb7 100644 --- a/examples/example_sdl_metal/main.mm +++ b/examples/example_sdl2_metal/main.mm @@ -4,7 +4,7 @@ // Read online: https://github.com/ocornut/imgui/tree/master/docs #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_metal.h" #include #include diff --git a/examples/example_sdl_opengl2/Makefile b/examples/example_sdl2_opengl2/Makefile similarity index 94% rename from examples/example_sdl_opengl2/Makefile rename to examples/example_sdl2_opengl2/Makefile index 24790f18..a85ced02 100644 --- a/examples/example_sdl_opengl2/Makefile +++ b/examples/example_sdl2_opengl2/Makefile @@ -14,11 +14,11 @@ #CXX = g++ #CXX = clang++ -EXE = example_sdl_opengl2 +EXE = example_sdl2_opengl2 IMGUI_DIR = ../.. SOURCES = main.cpp SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) diff --git a/examples/example_sdl2_opengl2/README.md b/examples/example_sdl2_opengl2/README.md new file mode 100644 index 00000000..40a49e69 --- /dev/null +++ b/examples/example_sdl2_opengl2/README.md @@ -0,0 +1,29 @@ + +# How to Build + +- On Windows with Visual Studio's IDE + +Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) if necessary. + +- On Windows with Visual Studio's CLI + +``` +set SDL2_DIR=path_to_your_sdl2_folder +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries +# or for 64-bit: +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +``` + +- On Linux and similar Unixes + +``` +c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL +``` + +- On Mac OS X + +``` +brew install sdl2 +c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl +``` diff --git a/examples/example_sdl_opengl2/build_win32.bat b/examples/example_sdl2_opengl2/build_win32.bat similarity index 73% rename from examples/example_sdl_opengl2/build_win32.bat rename to examples/example_sdl2_opengl2/build_win32.bat index 47529e28..287a418b 100644 --- a/examples/example_sdl_opengl2/build_win32.bat +++ b/examples/example_sdl2_opengl2/build_win32.bat @@ -1,8 +1,8 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. @set OUT_DIR=Debug -@set OUT_EXE=example_sdl_opengl2 +@set OUT_EXE=example_sdl2_opengl2 @set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include -@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp @set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib mkdir %OUT_DIR% cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj similarity index 98% rename from examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj rename to examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj index d22a67ba..a5515113 100644 --- a/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj +++ b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj @@ -20,7 +20,7 @@ {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} - example_sdl_opengl2 + example_sdl2_opengl2 8.1 @@ -160,16 +160,16 @@ + - + - @@ -178,4 +178,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj.filters similarity index 93% rename from examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters rename to examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj.filters index 430ad73f..0419ea0d 100644 --- a/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters +++ b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj.filters @@ -28,7 +28,7 @@ imgui - + sources @@ -48,7 +48,7 @@ sources - + sources @@ -58,4 +58,4 @@ imgui - \ No newline at end of file + diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp similarity index 98% rename from examples/example_sdl_opengl2/main.cpp rename to examples/example_sdl2_opengl2/main.cpp index 2677a5e5..2c3ad748 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -4,11 +4,11 @@ // Read online: https://github.com/ocornut/imgui/tree/master/docs // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** -// **Prefer using the code in the example_sdl_opengl3/ folder** -// See imgui_impl_sdl.cpp for details. +// **Prefer using the code in the example_sdl2_opengl3/ folder** +// See imgui_impl_sdl2.cpp for details. #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_opengl2.h" #include #include diff --git a/examples/example_sdl_opengl3/Makefile b/examples/example_sdl2_opengl3/Makefile similarity index 95% rename from examples/example_sdl_opengl3/Makefile rename to examples/example_sdl2_opengl3/Makefile index ae22ce20..5b4f9419 100644 --- a/examples/example_sdl_opengl3/Makefile +++ b/examples/example_sdl2_opengl3/Makefile @@ -14,11 +14,11 @@ #CXX = g++ #CXX = clang++ -EXE = example_sdl_opengl3 +EXE = example_sdl2_opengl3 IMGUI_DIR = ../.. SOURCES = main.cpp SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) LINUX_GL_LIBS = -lGL diff --git a/examples/example_sdl_opengl3/Makefile.emscripten b/examples/example_sdl2_opengl3/Makefile.emscripten similarity index 96% rename from examples/example_sdl_opengl3/Makefile.emscripten rename to examples/example_sdl2_opengl3/Makefile.emscripten index 778f1265..da034843 100644 --- a/examples/example_sdl_opengl3/Makefile.emscripten +++ b/examples/example_sdl2_opengl3/Makefile.emscripten @@ -20,7 +20,7 @@ EXE = $(WEB_DIR)/index.html IMGUI_DIR = ../.. SOURCES = main.cpp SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) CPPFLAGS = diff --git a/examples/example_sdl_opengl3/README.md b/examples/example_sdl2_opengl3/README.md similarity index 81% rename from examples/example_sdl_opengl3/README.md rename to examples/example_sdl2_opengl3/README.md index ccd58088..9ecb9e90 100644 --- a/examples/example_sdl_opengl3/README.md +++ b/examples/example_sdl2_opengl3/README.md @@ -10,10 +10,10 @@ Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) i Use build_win32.bat or directly: ``` set SDL2_DIR=path_to_your_sdl2_folder -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console -# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries # or for 64-bit: -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console ``` ## Linux and similar Unixes @@ -21,7 +21,7 @@ cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_ Use our Makefile or directly: ``` c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends - main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp + main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -ldl ``` @@ -31,7 +31,7 @@ Use our Makefile or directly: ``` brew install sdl2 c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends - main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp + main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -framework CoreFoundation ``` diff --git a/examples/example_sdl_opengl3/build_win32.bat b/examples/example_sdl2_opengl3/build_win32.bat similarity index 73% rename from examples/example_sdl_opengl3/build_win32.bat rename to examples/example_sdl2_opengl3/build_win32.bat index 20851bff..abbf3c78 100644 --- a/examples/example_sdl_opengl3/build_win32.bat +++ b/examples/example_sdl2_opengl3/build_win32.bat @@ -1,8 +1,8 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. @set OUT_DIR=Debug -@set OUT_EXE=example_sdl_opengl3 +@set OUT_EXE=example_sdl2_opengl3 @set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include -@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp @set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib mkdir %OUT_DIR% cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj similarity index 98% rename from examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj rename to examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj index ace041df..d45705ea 100644 --- a/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj +++ b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj @@ -20,7 +20,7 @@ {BBAEB705-1669-40F3-8567-04CF6A991F4C} - example_sdl_opengl3 + example_sdl2_opengl3 8.1 @@ -160,17 +160,17 @@ + - + - diff --git a/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj.filters similarity index 93% rename from examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters rename to examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj.filters index 4ba79ff0..fbc39b1e 100644 --- a/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters +++ b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj.filters @@ -22,10 +22,10 @@ sources - + sources - + sources @@ -45,13 +45,13 @@ imgui - + sources - + sources - + sources @@ -61,4 +61,4 @@ imgui - \ No newline at end of file + diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp similarity index 99% rename from examples/example_sdl_opengl3/main.cpp rename to examples/example_sdl2_opengl3/main.cpp index bc660a51..3e63f7a2 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -4,7 +4,7 @@ // Read online: https://github.com/ocornut/imgui/tree/master/docs #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_opengl3.h" #include #include diff --git a/examples/example_sdl_sdlrenderer/Makefile b/examples/example_sdl2_sdlrenderer/Makefile similarity index 93% rename from examples/example_sdl_sdlrenderer/Makefile rename to examples/example_sdl2_sdlrenderer/Makefile index aa3b2d2e..0050f0e1 100644 --- a/examples/example_sdl_sdlrenderer/Makefile +++ b/examples/example_sdl2_sdlrenderer/Makefile @@ -14,11 +14,11 @@ #CXX = g++ #CXX = clang++ -EXE = example_sdl_sdlrenderer +EXE = example_sdl2_sdlrenderer IMGUI_DIR = ../.. SOURCES = main.cpp SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlrenderer.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlrenderer.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) diff --git a/examples/example_sdl2_sdlrenderer/README.md b/examples/example_sdl2_sdlrenderer/README.md new file mode 100644 index 00000000..4fa37433 --- /dev/null +++ b/examples/example_sdl2_sdlrenderer/README.md @@ -0,0 +1,25 @@ + +# How to Build + +- On Windows with Visual Studio's CLI + +``` +set SDL2_DIR=path_to_your_sdl2_folder +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /subsystem:console +# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries +# or for 64-bit: +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib /subsystem:console +``` + +- On Linux and similar Unixes + +``` +c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL +``` + +- On Mac OS X + +``` +brew install sdl2 +c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl +``` diff --git a/examples/example_sdl_sdlrenderer/build_win32.bat b/examples/example_sdl2_sdlrenderer/build_win32.bat similarity index 71% rename from examples/example_sdl_sdlrenderer/build_win32.bat rename to examples/example_sdl2_sdlrenderer/build_win32.bat index 6c1b5fde..1bae121b 100644 --- a/examples/example_sdl_sdlrenderer/build_win32.bat +++ b/examples/example_sdl2_sdlrenderer/build_win32.bat @@ -1,8 +1,8 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. @set OUT_DIR=Debug -@set OUT_EXE=example_sdl_sdlrenderer_ +@set OUT_EXE=example_sdl2_sdlrenderer_ @set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include -@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp @set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib mkdir %OUT_DIR% cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj b/examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj similarity index 97% rename from examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj rename to examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj index 911d9da2..df7e1442 100644 --- a/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj +++ b/examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj @@ -20,7 +20,7 @@ {0C0B2BEA-311F-473C-9652-87923EF639E3} - example_sdl_sdlrenderer + example_sdl2_sdlrenderer 8.1 @@ -160,16 +160,16 @@ + - + - @@ -178,4 +178,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters b/examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj.filters similarity index 93% rename from examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters rename to examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj.filters index 6bb03815..6c8f5a1e 100644 --- a/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters +++ b/examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer.vcxproj.filters @@ -28,7 +28,7 @@ imgui - + sources @@ -48,7 +48,7 @@ sources - + sources @@ -58,4 +58,4 @@ imgui - \ No newline at end of file + diff --git a/examples/example_sdl_sdlrenderer/main.cpp b/examples/example_sdl2_sdlrenderer/main.cpp similarity index 99% rename from examples/example_sdl_sdlrenderer/main.cpp rename to examples/example_sdl2_sdlrenderer/main.cpp index f4a2890b..0812b76d 100644 --- a/examples/example_sdl_sdlrenderer/main.cpp +++ b/examples/example_sdl2_sdlrenderer/main.cpp @@ -8,7 +8,7 @@ // For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_sdlrenderer.h" #include #include diff --git a/examples/example_sdl_vulkan/build_win32.bat b/examples/example_sdl2_vulkan/build_win32.bat similarity index 77% rename from examples/example_sdl_vulkan/build_win32.bat rename to examples/example_sdl2_vulkan/build_win32.bat index d4a71884..5bc51985 100644 --- a/examples/example_sdl_vulkan/build_win32.bat +++ b/examples/example_sdl2_vulkan/build_win32.bat @@ -1,8 +1,8 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. -@set OUT_EXE=example_sdl_vulkan +@set OUT_EXE=example_sdl2_vulkan @set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I %VULKAN_SDK%\include -@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp @set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 /libpath:%VULKAN_SDK%\lib32 SDL2.lib SDL2main.lib shell32.lib vulkan-1.lib @set OUT_DIR=Debug diff --git a/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj similarity index 98% rename from examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj rename to examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj index fc69ca70..35282cc0 100644 --- a/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj +++ b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj @@ -20,7 +20,7 @@ {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3} - example_sdl_vulkan + example_sdl2_vulkan 8.1 @@ -164,7 +164,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -182,4 +182,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj.filters similarity index 93% rename from examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters rename to examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj.filters index f1d404ce..d3b12984 100644 --- a/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters +++ b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj.filters @@ -19,7 +19,7 @@ imgui - + sources @@ -45,7 +45,7 @@ imgui - + sources @@ -58,4 +58,4 @@ imgui - \ No newline at end of file + diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp similarity index 99% rename from examples/example_sdl_vulkan/main.cpp rename to examples/example_sdl2_vulkan/main.cpp index 3fc3bf0e..c4130c15 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -10,7 +10,7 @@ // Read comments in imgui_impl_vulkan.h. #include "imgui.h" -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl2.h" #include "imgui_impl_vulkan.h" #include // printf, fprintf #include // abort diff --git a/examples/example_sdl_opengl2/README.md b/examples/example_sdl_opengl2/README.md deleted file mode 100644 index 2bf4d03a..00000000 --- a/examples/example_sdl_opengl2/README.md +++ /dev/null @@ -1,29 +0,0 @@ - -# How to Build - -- On Windows with Visual Studio's IDE - -Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) if necessary. - -- On Windows with Visual Studio's CLI - -``` -set SDL2_DIR=path_to_your_sdl2_folder -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console -# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries -# or for 64-bit: -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console -``` - -- On Linux and similar Unixes - -``` -c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -``` - -- On Mac OS X - -``` -brew install sdl2 -c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -``` diff --git a/examples/example_sdl_sdlrenderer/README.md b/examples/example_sdl_sdlrenderer/README.md deleted file mode 100644 index 209f15ac..00000000 --- a/examples/example_sdl_sdlrenderer/README.md +++ /dev/null @@ -1,25 +0,0 @@ - -# How to Build - -- On Windows with Visual Studio's CLI - -``` -set SDL2_DIR=path_to_your_sdl2_folder -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /subsystem:console -# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries -# or for 64-bit: -cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib /subsystem:console -``` - -- On Linux and similar Unixes - -``` -c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -``` - -- On Mac OS X - -``` -brew install sdl2 -c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -``` diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index aec5af3c..9b442b27 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -17,15 +17,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_opengl3", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_vulkan", "example_glfw_vulkan\example_glfw_vulkan.vcxproj", "{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_directx11", "example_sdl_directx11\example_sdl_directx11.vcxproj", "{9E1987E3-1F19-45CA-B9C9-D31E791836D8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_directx11", "example_sdl2_directx11\example_sdl2_directx11.vcxproj", "{9E1987E3-1F19-45CA-B9C9-D31E791836D8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_opengl2", "example_sdl_opengl2\example_sdl_opengl2.vcxproj", "{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_opengl2", "example_sdl2_opengl2\example_sdl2_opengl2.vcxproj", "{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_opengl3", "example_sdl_opengl3\example_sdl_opengl3.vcxproj", "{BBAEB705-1669-40F3-8567-04CF6A991F4C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_opengl3", "example_sdl2_opengl3\example_sdl2_opengl3.vcxproj", "{BBAEB705-1669-40F3-8567-04CF6A991F4C}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_sdlrenderer", "example_sdl_sdlrenderer\example_sdl_sdlrenderer.vcxproj", "{0C0B2BEA-311F-473C-9652-87923EF639E3}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_sdlrenderer", "example_sdl2_sdlrenderer\example_sdl2_sdlrenderer.vcxproj", "{0C0B2BEA-311F-473C-9652-87923EF639E3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_vulkan", "example_sdl_vulkan\example_sdl_vulkan.vcxproj", "{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_vulkan", "example_sdl2_vulkan\example_sdl2_vulkan.vcxproj", "{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/imgui.cpp b/imgui.cpp index e04d623f..d1e9807f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -386,6 +386,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2023/02/07 (1.89.3) - backends: renamed "imgui_impl_sdl.cpp" to "imgui_impl_sdl2.cpp" and "imgui_impl_sdl.h" to "imgui_impl_sdl2.h". (#6146) This is in prevision for the future release of SDL3. - 2022/10/26 (1.89) - commented out redirecting OpenPopupContextItem() which was briefly the name of OpenPopupOnItemClick() from 1.77 to 1.79. - 2022/10/12 (1.89) - removed runtime patching of invalid "%f"/"%0.f" format strings for DragInt()/SliderInt(). This was obsoleted in 1.61 (May 2018). See 1.61 changelog for details. - 2022/09/26 (1.89) - renamed and merged keyboard modifiers key enums and flags into a same set. Kept inline redirection enums (will obsolete). From e816bc67238bd1bac8d188c41c04c9f5714433dd Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Feb 2023 12:24:42 +0100 Subject: [PATCH 4/6] Merge misc changes from docking branch to reduce small drift. In particular: - imgui.cpp : move UpdateInputEvents() higher in NewFrame() to match docking + update RenderMouseCursor() to match. - imgui_draw.cpp: ImDrawList::_ResetForNewFrame() change from c807192ab - Backends: SDL2. Add MouseWindowID + change SDL_CaptureMouse() test to match docking branch. Not strictly necessary but aimed at reducing drift because we go on and fork this file. + moved responsability of checking valid names to TabBarGetTabName() to simplify both branches. --- backends/imgui_impl_allegro5.cpp | 2 +- backends/imgui_impl_dx10.cpp | 6 +-- backends/imgui_impl_dx10.h | 4 +- backends/imgui_impl_dx11.cpp | 4 +- backends/imgui_impl_dx11.h | 2 +- backends/imgui_impl_dx12.cpp | 58 +++++++++++---------- backends/imgui_impl_dx12.h | 2 +- backends/imgui_impl_dx9.cpp | 4 +- backends/imgui_impl_dx9.h | 2 +- backends/imgui_impl_glfw.cpp | 80 +++++++++++++++++------------ backends/imgui_impl_metal.h | 2 +- backends/imgui_impl_metal.mm | 16 +++--- backends/imgui_impl_opengl3.cpp | 2 +- backends/imgui_impl_opengl3.h | 2 +- backends/imgui_impl_osx.h | 2 +- backends/imgui_impl_osx.mm | 34 ++++++------ backends/imgui_impl_sdl2.cpp | 25 ++++++--- backends/imgui_impl_sdlrenderer.cpp | 3 +- backends/imgui_impl_sdlrenderer.h | 2 +- backends/imgui_impl_vulkan.cpp | 4 +- backends/imgui_impl_vulkan.h | 6 +-- backends/imgui_impl_wgpu.cpp | 4 +- backends/imgui_impl_wgpu.h | 2 +- backends/imgui_impl_win32.cpp | 8 ++- imgui.cpp | 53 ++++++++++--------- imgui_draw.cpp | 2 + imgui_internal.h | 4 +- imgui_widgets.cpp | 12 +++-- 28 files changed, 193 insertions(+), 154 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index bf7f141e..b7e77687 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -275,7 +275,7 @@ void ImGui_ImplAllegro5_InvalidateDeviceObjects() ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); if (bd->Texture) { - io.Fonts->SetTexID(nullptr); + io.Fonts->SetTexID(0); al_destroy_bitmap(bd->Texture); bd->Texture = nullptr; } diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 9118929e..e0743592 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -2,8 +2,8 @@ // This needs to be used along with a Platform Backend (e.g. Win32) // Implemented features: -// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -515,7 +515,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects() return; if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } - if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(nullptr); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. + if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } diff --git a/backends/imgui_impl_dx10.h b/backends/imgui_impl_dx10.h index 31e62aca..fde520c9 100644 --- a/backends/imgui_impl_dx10.h +++ b/backends/imgui_impl_dx10.h @@ -2,8 +2,8 @@ // This needs to be used along with a Platform Backend (e.g. Win32) // Implemented features: -// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 40394e0f..43fe8144 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -527,7 +527,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() return; if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } - if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(nullptr); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. + if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h index a83bce1b..f12d7186 100644 --- a/backends/imgui_impl_dx11.h +++ b/backends/imgui_impl_dx11.h @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 51b0d815..2e390d20 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. @@ -50,6 +50,33 @@ #endif // DirectX data +struct ImGui_ImplDX12_RenderBuffers; +struct ImGui_ImplDX12_Data +{ + ID3D12Device* pd3dDevice; + ID3D12RootSignature* pRootSignature; + ID3D12PipelineState* pPipelineState; + DXGI_FORMAT RTVFormat; + ID3D12Resource* pFontTextureResource; + D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; + D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; + ID3D12DescriptorHeap* pd3dSrvDescHeap; + UINT numFramesInFlight; + + ImGui_ImplDX12_RenderBuffers* pFrameResources; + UINT frameIndex; + + ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; } +}; + +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; +} + +// Buffers used during the rendering of a frame struct ImGui_ImplDX12_RenderBuffers { ID3D12Resource* IndexBuffer; @@ -58,35 +85,11 @@ struct ImGui_ImplDX12_RenderBuffers int VertexBufferSize; }; -struct ImGui_ImplDX12_Data -{ - ID3D12Device* pd3dDevice; - ID3D12RootSignature* pRootSignature; - ID3D12PipelineState* pPipelineState; - DXGI_FORMAT RTVFormat; - ID3D12Resource* pFontTextureResource; - D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; - D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; - - ImGui_ImplDX12_RenderBuffers* pFrameResources; - UINT numFramesInFlight; - UINT frameIndex; - - ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; } -}; - struct VERTEX_CONSTANT_BUFFER_DX12 { float mvp[4][4]; }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() -{ - return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; -} - // Functions static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr) { @@ -676,8 +679,8 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); if (!bd || !bd->pd3dDevice) return; - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO& io = ImGui::GetIO(); SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); SafeRelease(bd->pFontTextureResource); @@ -709,8 +712,8 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight]; bd->numFramesInFlight = num_frames_in_flight; + bd->pd3dSrvDescHeap = cbv_srv_heap; bd->frameIndex = UINT_MAX; - IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) // Create buffers with a default size (they will later be grown as needed) for (int i = 0; i < num_frames_in_flight; i++) @@ -731,6 +734,7 @@ void ImGui_ImplDX12_Shutdown() IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + // Clean up windows and device objects ImGui_ImplDX12_InvalidateDeviceObjects(); delete[] bd->pFrameResources; io.BackendRendererName = nullptr; diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index 6548f6f5..ea6d33b9 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. // See imgui_impl_dx12.cpp file for details. diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 89de0e62..61e9d6ed 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -366,7 +366,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects() return; if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } - if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(nullptr); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. + if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. } void ImGui_ImplDX9_NewFrame() diff --git a/backends/imgui_impl_dx9.h b/backends/imgui_impl_dx9.h index 6dc805b9..32e89ec9 100644 --- a/backends/imgui_impl_dx9.h +++ b/backends/imgui_impl_dx9.h @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index c39afa38..41d3a611 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -1,7 +1,7 @@ // dear imgui: Platform Backend for GLFW // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) -// (Requires: GLFW 3.1+) +// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.) // Implemented features: // [X] Platform: Clipboard support. @@ -70,10 +70,15 @@ // GLFW #include + #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 -#include // for glfwGetWin32Window +#include // for glfwGetWin32Window() +#endif +#ifdef __APPLE__ +#define GLFW_EXPOSE_NATIVE_COCOA +#include // for glfwGetCocoaWindow() #endif #ifdef __EMSCRIPTEN__ @@ -509,11 +514,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = bd->Window; - // Set platform dependent data in viewport -#if defined(_WIN32) - ImGui::GetMainViewport()->PlatformHandleRaw = (void*)glfwGetWin32Window(bd->Window); -#endif - // Create mouse cursors // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist, // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. @@ -543,7 +543,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); - // Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096) // We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves. // FIXME: May break chaining in case user registered their own Emscripten callback? @@ -551,6 +550,14 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, false, ImGui_ImplEmscripten_WheelCallback); #endif + // Set platform dependent data in viewport + ImGuiViewport* main_viewport = ImGui::GetMainViewport(); +#ifdef _WIN32 + main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window); +#elif defined(__APPLE__) + main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window); +#endif + bd->ClientApi = client_api; return true; } @@ -598,24 +605,29 @@ static void ImGui_ImplGlfw_UpdateMouseData() return; } + // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) + { + GLFWwindow* window = bd->Window; + #ifdef __EMSCRIPTEN__ - const bool is_app_focused = true; + const bool is_window_focused = true; #else - const bool is_app_focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0; + const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; #endif - if (is_app_focused) - { - // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) - if (io.WantSetMousePos) - glfwSetCursorPos(bd->Window, (double)io.MousePos.x, (double)io.MousePos.y); - - // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured) - if (is_app_focused && bd->MouseWindow == nullptr) + if (is_window_focused) { - double mouse_x, mouse_y; - glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y); - io.AddMousePosEvent((float)mouse_x, (float)mouse_y); - bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y); + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + glfwSetCursorPos(window, (double)io.MousePos.x, (double)io.MousePos.y); + + // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured) + if (bd->MouseWindow == nullptr) + { + double mouse_x, mouse_y; + glfwGetCursorPos(window, &mouse_x, &mouse_y); + bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y); + io.AddMousePosEvent((float)mouse_x, (float)mouse_y); + } } } } @@ -628,17 +640,21 @@ static void ImGui_ImplGlfw_UpdateMouseCursor() return; ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) - { - // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else + // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) { - // Show OS mouse cursor - // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. - glfwSetCursor(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + GLFWwindow* window = bd->Window; + if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + // Show OS mouse cursor + // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. + glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } } } diff --git a/backends/imgui_impl_metal.h b/backends/imgui_impl_metal.h index 49584443..da9e9ef9 100644 --- a/backends/imgui_impl_metal.h +++ b/backends/imgui_impl_metal.h @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 3f8c7760..5f058857 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -3,7 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -70,16 +70,16 @@ struct ImGui_ImplMetal_Data { - MetalContext* SharedMetalContext; + MetalContext* SharedMetalContext; - ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); } }; -static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); } -static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : NULL; } -static void ImGui_ImplMetal_DestroyBackendData() { IM_DELETE(ImGui_ImplMetal_GetBackendData()); } +static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); } +static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; } +static void ImGui_ImplMetal_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal_GetBackendData()); } -static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); } #ifdef IMGUI_IMPL_METAL_CPP @@ -297,7 +297,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c { dispatch_async(dispatch_get_main_queue(), ^{ ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); - if (bd != NULL) + if (bd != nullptr) { @synchronized(bd->SharedMetalContext.bufferCache) { diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 0b6fcfe4..e12294fe 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -5,7 +5,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. +// [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_opengl3.h b/backends/imgui_impl_opengl3.h index 5baf5abd..3a95f052 100644 --- a/backends/imgui_impl_opengl3.h +++ b/backends/imgui_impl_opengl3.h @@ -5,7 +5,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. +// [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index fd8755b6..da08c4cf 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -9,7 +9,7 @@ // [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: IME support. -// + // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 6b34b39a..edb376ce 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -66,22 +66,22 @@ // Data struct ImGui_ImplOSX_Data { - CFTimeInterval Time; - NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; - bool MouseCursorHidden; - ImGuiObserver* Observer; - KeyEventResponder* KeyEventResponder; - NSTextInputContext* InputContext; - id Monitor; - - ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } + CFTimeInterval Time; + NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; + bool MouseCursorHidden; + ImGuiObserver* Observer; + KeyEventResponder* KeyEventResponder; + NSTextInputContext* InputContext; + id Monitor; + + ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } }; -static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); } -static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; } -static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); } +static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); } +static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; } +static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); } -static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); } // Forward Declarations static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view); @@ -391,8 +391,6 @@ bool ImGui_ImplOSX_Init(NSView* view) // Setup backend capabilities flags io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) - //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy) io.BackendPlatformName = "imgui_impl_osx"; bd->Observer = [ImGuiObserver new]; @@ -476,11 +474,11 @@ bool ImGui_ImplOSX_Init(NSView* view) void ImGui_ImplOSX_Shutdown() { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); - bd->Observer = NULL; - if (bd->Monitor != NULL) + bd->Observer = nullptr; + if (bd->Monitor != nullptr) { [NSEvent removeMonitor:bd->Monitor]; - bd->Monitor = NULL; + bd->Monitor = nullptr; } ImGui_ImplOSX_DestroyBackendData(); } diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 9055b55d..cff755bc 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -91,6 +91,7 @@ struct ImGui_ImplSDL2_Data SDL_Window* Window; SDL_Renderer* Renderer; Uint64 Time; + Uint32 MouseWindowID; int MouseButtonsDown; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; SDL_Cursor* LastMouseCursor; @@ -261,7 +262,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { case SDL_MOUSEMOTION: { - io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y); + ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); + io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); return true; } case SDL_MOUSEWHEEL: @@ -318,7 +320,10 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. Uint8 window_event = event->window.event; if (window_event == SDL_WINDOWEVENT_ENTER) + { + bd->MouseWindowID = event->window.windowID; bd->PendingMouseLeaveFrame = 0; + } if (window_event == SDL_WINDOWEVENT_LEAVE) bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) @@ -374,14 +379,19 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer) bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); // Set platform dependent data in viewport -#if defined(SDL_VIDEO_DRIVER_WINDOWS) + // Our mouse update function expect PlatformHandle to be filled for the main viewport + ImGuiViewport* main_viewport = ImGui::GetMainViewport(); + main_viewport->PlatformHandleRaw = nullptr; SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info)) - ImGui::GetMainViewport()->PlatformHandleRaw = (void*)info.info.win.window; -#else - (void)window; + { +#if defined(SDL_VIDEO_DRIVER_WINDOWS) + main_viewport->PlatformHandleRaw = (void*)info.info.win.window; +#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA) + main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; #endif + } // From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event. // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered. @@ -457,7 +467,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse((bd->MouseButtonsDown != 0 && ImGui::GetDragDropPayload() == nullptr) ? SDL_TRUE : SDL_FALSE); + SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE); SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else @@ -580,8 +590,9 @@ void ImGui_ImplSDL2_NewFrame() if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) { - io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + bd->MouseWindowID = 0; bd->PendingMouseLeaveFrame = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } ImGui_ImplSDL2_UpdateMouseData(); diff --git a/backends/imgui_impl_sdlrenderer.cpp b/backends/imgui_impl_sdlrenderer.cpp index 87381f27..b786ebd2 100644 --- a/backends/imgui_impl_sdlrenderer.cpp +++ b/backends/imgui_impl_sdlrenderer.cpp @@ -10,8 +10,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// Missing features: +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. diff --git a/backends/imgui_impl_sdlrenderer.h b/backends/imgui_impl_sdlrenderer.h index 51a1c45f..de1eff65 100644 --- a/backends/imgui_impl_sdlrenderer.h +++ b/backends/imgui_impl_sdlrenderer.h @@ -10,7 +10,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. #pragma once #include "imgui.h" // IMGUI_IMPL_API diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index cd35fd9a..bfc488c2 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -2,8 +2,8 @@ // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. @@ -117,7 +117,7 @@ struct ImGui_ImplVulkan_Data VkDeviceMemory UploadBufferMemory; VkBuffer UploadBuffer; - // Render buffers + // Render buffers for main window ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; ImGui_ImplVulkan_Data() diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 99fd0082..64cc887c 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -2,8 +2,8 @@ // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'. // See imgui_impl_vulkan.cpp file for details. @@ -89,8 +89,8 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*l // You probably do NOT need to use or care about those functions. // Those functions only exist because: // 1) they facilitate the readability and maintenance of the multiple main.cpp examples files. -// 2) the upcoming multi-viewport feature will need them internally. -// Generally we avoid exposing any kind of superfluous high-level helpers in the backends, +// 2) the multi-viewport / platform window implementation needs them internally. +// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings, // but it is too much code to duplicate everywhere so we exceptionally expose them. // // Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.). diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 11c1a376..946b4476 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -4,7 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -685,7 +685,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects() SafeRelease(g_resources); ImGuiIO& io = ImGui::GetIO(); - io.Fonts->SetTexID(nullptr); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. + io.Fonts->SetTexID(0); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. for (unsigned int i = 0; i < g_numFramesInFlight; i++) SafeRelease(g_pFrameResources[i]); diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 8bc1a39a..09142078 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -4,7 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 4bb6673b..7ebb58c5 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -254,7 +254,8 @@ static void ImGui_ImplWin32_UpdateMouseData() ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(bd->hWnd != 0); - const bool is_app_focused = (::GetForegroundWindow() == bd->hWnd); + HWND focused_window = ::GetForegroundWindow(); + const bool is_app_focused = (focused_window == bd->hWnd); if (is_app_focused) { // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) @@ -514,6 +515,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA switch (msg) { case WM_MOUSEMOVE: + { // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events bd->MouseHwnd = hwnd; if (!bd->MouseTracked) @@ -522,8 +524,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA ::TrackMouseEvent(&tme); bd->MouseTracked = true; } - io.AddMousePosEvent((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam)); + POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) }; + io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y); break; + } case WM_MOUSELEAVE: if (bd->MouseHwnd == hwnd) bd->MouseHwnd = nullptr; diff --git a/imgui.cpp b/imgui.cpp index d1e9807f..a4fe84a1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1864,7 +1864,7 @@ static const ImU32 GCrc32LookupTable[256] = // Known size hash // It is ok to call ImHashData on a string with known length but the ### operator won't be supported. // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed) +ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed) { ImU32 crc = ~seed; const unsigned char* data = (const unsigned char*)data_p; @@ -1880,7 +1880,7 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed) // - If we reach ### in the string we discard the hash so far and reset to the seed. // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build) // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImGuiID ImHashStr(const char* data_p, size_t data_size, ImU32 seed) +ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed) { seed = ~seed; ImU32 crc = seed; @@ -3374,24 +3374,26 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso { ImGuiContext& g = *GImGui; IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); + ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas; for (int n = 0; n < g.Viewports.Size; n++) { + // We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor. + ImVec2 offset, size, uv[4]; + if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) + continue; ImGuiViewportP* viewport = g.Viewports[n]; + const ImVec2 pos = base_pos - offset; + const float scale = base_scale; + if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale))) + continue; ImDrawList* draw_list = GetForegroundDrawList(viewport); - ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas; - ImVec2 offset, size, uv[4]; - if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) - { - const ImVec2 pos = base_pos - offset; - const float scale = base_scale; - ImTextureID tex_id = font_atlas->TexID; - draw_list->PushTextureID(tex_id); - draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); - draw_list->PopTextureID(); - } + ImTextureID tex_id = font_atlas->TexID; + draw_list->PushTextureID(tex_id); + draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); + draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); + draw_list->PopTextureID(); } } @@ -3886,7 +3888,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) return false; // Special handling for calling after Begin() which represent the title bar or tab. - // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. + // When the window is skipped/collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. if (g.LastItemData.ID == window->MoveId && window->WriteAccessed) return false; } @@ -4353,6 +4355,11 @@ void ImGui::NewFrame() g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame)); g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)g.FramerateSecPerFrameCount)) : FLT_MAX; + // Process input queue (trickle as many events as possible), turn events into writes to IO structure + g.InputEventsTrail.resize(0); + UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue); + + // Update viewports (after processing input queue, so io.MouseHoveredViewport is set) UpdateViewportsNewFrame(); // Setup current font and draw list shared data @@ -4474,10 +4481,6 @@ void ImGui::NewFrame() //if (g.IO.AppFocusLost) // ClosePopupsExceptModals(); - // Process input queue (trickle as many events as possible) - g.InputEventsTrail.resize(0); - UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue); - // Update keyboard input state UpdateKeyboardInputs(); @@ -5777,7 +5780,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar if (window->Collapsed) { // Title bar only - float backup_border_size = style.FrameBorderSize; + const float backup_border_size = style.FrameBorderSize; g.Style.FrameBorderSize = window->WindowBorderSize; ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); @@ -9983,7 +9986,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) const int current_stack_size = g.BeginPopupStack.Size; if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup) - if (IsPopupOpen(0u, ImGuiPopupFlags_AnyPopupId)) + if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId)) return; ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. @@ -13977,7 +13980,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; p += ImFormatString(p, buf_end - p, "%s'%s'", - tab_n > 0 ? ", " : "", (tab->NameOffset != -1) ? TabBarGetTabName(tab_bar, tab) : "???"); + tab_n > 0 ? ", " : "", TabBarGetTabName(tab_bar, tab)); } p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } "); if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } @@ -13999,7 +14002,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); Text("%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f", - tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? TabBarGetTabName(tab_bar, tab) : "???", tab->Offset, tab->Width, tab->ContentWidth); + tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, TabBarGetTabName(tab_bar, tab), tab->Offset, tab->Width, tab->ContentWidth); PopID(); } TreePop(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 09db1c6b..f694ff23 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -389,6 +389,8 @@ void ImDrawList::_ResetForNewFrame() IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0); IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4)); IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID)); + if (_Splitter._Count > 1) + _Splitter.Merge(this); CmdBuffer.resize(0); IdxBuffer.resize(0); diff --git a/imgui_internal.h b/imgui_internal.h index 021a24ec..9c8d02df 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -318,8 +318,8 @@ namespace ImStb //----------------------------------------------------------------------------- // Helpers: Hashing -IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0); -IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0); +IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImGuiID seed = 0); +IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImGuiID seed = 0); // Helpers: Sorting #ifndef ImQsort diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5f34e782..f60845bf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7660,6 +7660,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) { ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n]; tab->Offset = tab_offset; + tab->NameOffset = -1; tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f); } tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f); @@ -7667,6 +7668,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) section_tab_index += section->TabCount; } + // Clear name buffers + tab_bar->TabsNames.Buf.resize(0); + // If we have lost the selected tab, select the next most recently active one if (found_selected_tab_id == false) tab_bar->SelectedTabId = 0; @@ -7698,10 +7702,6 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing; tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing; - // Clear name buffers - if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) - tab_bar->TabsNames.Buf.resize(0); - // Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame) ImGuiWindow* window = g.CurrentWindow; window->DC.CursorPos = tab_bar->BarRect.Min; @@ -7759,7 +7759,9 @@ ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar) const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { - IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < tab_bar->TabsNames.Buf.Size); + if (tab->NameOffset == -1) + return "N/A"; + IM_ASSERT(tab->NameOffset < tab_bar->TabsNames.Buf.Size); return tab_bar->TabsNames.Buf.Data + tab->NameOffset; } From d9bf80f655208d9dca5d79287bc6b23fb5e2dcb2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Feb 2023 13:26:24 +0100 Subject: [PATCH 5/6] Backends: SDL3: copied imgui_impl_sdl2 into imgui_impl_sdl3 and ONLY replaced strings (1/2). (#6146) NO OTHER CHANGES. This WILL NOT compile with SDL3. This intermediate commit designed to make it easier to visualize the meaningful channges commit in the next commit. --- backends/imgui_impl_sdl3.cpp | 555 +++++++++++++++++++++++++++++++++++ backends/imgui_impl_sdl3.h | 36 +++ 2 files changed, 591 insertions(+) create mode 100644 backends/imgui_impl_sdl3.cpp create mode 100644 backends/imgui_impl_sdl3.h diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp new file mode 100644 index 00000000..78f0cf0b --- /dev/null +++ b/backends/imgui_impl_sdl3.cpp @@ -0,0 +1,555 @@ +// dear imgui: Platform Backend for SDL3 +// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) +// (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) +// (Prefer SDL 2.0.5+ for full feature support.) + +// Implemented features: +// [X] Platform: Clipboard support. +// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] +// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// Missing features: +// [ ] Platform: SDL3 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. + +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2023-02-07: Forked "imgui_impl_sdl2" into "imgui_impl_sdl3". Removed version checks for old feature. Refer to imgui_impl_sdl2.cpp for older changelog. + +#include "imgui.h" +#include "imgui_impl_sdl3.h" + +// SDL +#include +#include +#if defined(__APPLE__) +#include +#endif + +#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) +#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1 +#else +#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 +#endif +#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) + +// SDL Data +struct ImGui_ImplSDL3_Data +{ + SDL_Window* Window; + SDL_Renderer* Renderer; + Uint64 Time; + Uint32 MouseWindowID; + int MouseButtonsDown; + SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; + SDL_Cursor* LastMouseCursor; + int PendingMouseLeaveFrame; + char* ClipboardTextData; + bool MouseCanUseGlobalState; + + ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); } +}; + +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. +static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; +} + +// Functions +static const char* ImGui_ImplSDL3_GetClipboardText(void*) +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + if (bd->ClipboardTextData) + SDL_free(bd->ClipboardTextData); + bd->ClipboardTextData = SDL_GetClipboardText(); + return bd->ClipboardTextData; +} + +static void ImGui_ImplSDL3_SetClipboardText(void*, const char* text) +{ + SDL_SetClipboardText(text); +} + +static ImGuiKey ImGui_ImplSDL3_KeycodeToImGuiKey(int keycode) +{ + switch (keycode) + { + case SDLK_TAB: return ImGuiKey_Tab; + case SDLK_LEFT: return ImGuiKey_LeftArrow; + case SDLK_RIGHT: return ImGuiKey_RightArrow; + case SDLK_UP: return ImGuiKey_UpArrow; + case SDLK_DOWN: return ImGuiKey_DownArrow; + case SDLK_PAGEUP: return ImGuiKey_PageUp; + case SDLK_PAGEDOWN: return ImGuiKey_PageDown; + case SDLK_HOME: return ImGuiKey_Home; + case SDLK_END: return ImGuiKey_End; + case SDLK_INSERT: return ImGuiKey_Insert; + case SDLK_DELETE: return ImGuiKey_Delete; + case SDLK_BACKSPACE: return ImGuiKey_Backspace; + case SDLK_SPACE: return ImGuiKey_Space; + case SDLK_RETURN: return ImGuiKey_Enter; + case SDLK_ESCAPE: return ImGuiKey_Escape; + case SDLK_QUOTE: return ImGuiKey_Apostrophe; + case SDLK_COMMA: return ImGuiKey_Comma; + case SDLK_MINUS: return ImGuiKey_Minus; + case SDLK_PERIOD: return ImGuiKey_Period; + case SDLK_SLASH: return ImGuiKey_Slash; + case SDLK_SEMICOLON: return ImGuiKey_Semicolon; + case SDLK_EQUALS: return ImGuiKey_Equal; + case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; + case SDLK_BACKSLASH: return ImGuiKey_Backslash; + case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; + case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent; + case SDLK_CAPSLOCK: return ImGuiKey_CapsLock; + case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock; + case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock; + case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen; + case SDLK_PAUSE: return ImGuiKey_Pause; + case SDLK_KP_0: return ImGuiKey_Keypad0; + case SDLK_KP_1: return ImGuiKey_Keypad1; + case SDLK_KP_2: return ImGuiKey_Keypad2; + case SDLK_KP_3: return ImGuiKey_Keypad3; + case SDLK_KP_4: return ImGuiKey_Keypad4; + case SDLK_KP_5: return ImGuiKey_Keypad5; + case SDLK_KP_6: return ImGuiKey_Keypad6; + case SDLK_KP_7: return ImGuiKey_Keypad7; + case SDLK_KP_8: return ImGuiKey_Keypad8; + case SDLK_KP_9: return ImGuiKey_Keypad9; + case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal; + case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide; + case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; + case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract; + case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd; + case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter; + case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual; + case SDLK_LCTRL: return ImGuiKey_LeftCtrl; + case SDLK_LSHIFT: return ImGuiKey_LeftShift; + case SDLK_LALT: return ImGuiKey_LeftAlt; + case SDLK_LGUI: return ImGuiKey_LeftSuper; + case SDLK_RCTRL: return ImGuiKey_RightCtrl; + case SDLK_RSHIFT: return ImGuiKey_RightShift; + case SDLK_RALT: return ImGuiKey_RightAlt; + case SDLK_RGUI: return ImGuiKey_RightSuper; + case SDLK_APPLICATION: return ImGuiKey_Menu; + case SDLK_0: return ImGuiKey_0; + case SDLK_1: return ImGuiKey_1; + case SDLK_2: return ImGuiKey_2; + case SDLK_3: return ImGuiKey_3; + case SDLK_4: return ImGuiKey_4; + case SDLK_5: return ImGuiKey_5; + case SDLK_6: return ImGuiKey_6; + case SDLK_7: return ImGuiKey_7; + case SDLK_8: return ImGuiKey_8; + case SDLK_9: return ImGuiKey_9; + case SDLK_a: return ImGuiKey_A; + case SDLK_b: return ImGuiKey_B; + case SDLK_c: return ImGuiKey_C; + case SDLK_d: return ImGuiKey_D; + case SDLK_e: return ImGuiKey_E; + case SDLK_f: return ImGuiKey_F; + case SDLK_g: return ImGuiKey_G; + case SDLK_h: return ImGuiKey_H; + case SDLK_i: return ImGuiKey_I; + case SDLK_j: return ImGuiKey_J; + case SDLK_k: return ImGuiKey_K; + case SDLK_l: return ImGuiKey_L; + case SDLK_m: return ImGuiKey_M; + case SDLK_n: return ImGuiKey_N; + case SDLK_o: return ImGuiKey_O; + case SDLK_p: return ImGuiKey_P; + case SDLK_q: return ImGuiKey_Q; + case SDLK_r: return ImGuiKey_R; + case SDLK_s: return ImGuiKey_S; + case SDLK_t: return ImGuiKey_T; + case SDLK_u: return ImGuiKey_U; + case SDLK_v: return ImGuiKey_V; + case SDLK_w: return ImGuiKey_W; + case SDLK_x: return ImGuiKey_X; + case SDLK_y: return ImGuiKey_Y; + case SDLK_z: return ImGuiKey_Z; + case SDLK_F1: return ImGuiKey_F1; + case SDLK_F2: return ImGuiKey_F2; + case SDLK_F3: return ImGuiKey_F3; + case SDLK_F4: return ImGuiKey_F4; + case SDLK_F5: return ImGuiKey_F5; + case SDLK_F6: return ImGuiKey_F6; + case SDLK_F7: return ImGuiKey_F7; + case SDLK_F8: return ImGuiKey_F8; + case SDLK_F9: return ImGuiKey_F9; + case SDLK_F10: return ImGuiKey_F10; + case SDLK_F11: return ImGuiKey_F11; + case SDLK_F12: return ImGuiKey_F12; + } + return ImGuiKey_None; +} + +static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) +{ + ImGuiIO& io = ImGui::GetIO(); + io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0); + io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0); + io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0); + io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0); +} + +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field. +bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) +{ + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + + switch (event->type) + { + case SDL_MOUSEMOTION: + { + ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); + io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); + return true; + } + case SDL_MOUSEWHEEL: + { + //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); +#if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten! + float wheel_x = -event->wheel.preciseX; + float wheel_y = event->wheel.preciseY; +#else + float wheel_x = -(float)event->wheel.x; + float wheel_y = (float)event->wheel.y; +#endif +#ifdef __EMSCRIPTEN__ + wheel_x /= 100.0f; +#endif + io.AddMouseWheelEvent(wheel_x, wheel_y); + return true; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + int mouse_button = -1; + if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } + if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } + if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; } + if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; } + if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } + if (mouse_button == -1) + break; + io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); + bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); + return true; + } + case SDL_TEXTINPUT: + { + io.AddInputCharactersUTF8(event->text.text); + return true; + } + case SDL_KEYDOWN: + case SDL_KEYUP: + { + ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); + ImGuiKey key = ImGui_ImplSDL3_KeycodeToImGuiKey(event->key.keysym.sym); + io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); + io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. + return true; + } + case SDL_WINDOWEVENT: + { + // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. + // - However we won't get a correct LEAVE event for a captured window. + // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why + // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. + Uint8 window_event = event->window.event; + if (window_event == SDL_WINDOWEVENT_ENTER) + { + bd->MouseWindowID = event->window.windowID; + bd->PendingMouseLeaveFrame = 0; + } + if (window_event == SDL_WINDOWEVENT_LEAVE) + bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) + io.AddFocusEvent(true); + else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) + io.AddFocusEvent(false); + return true; + } + } + return false; +} + +static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer) +{ + ImGuiIO& io = ImGui::GetIO(); + IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); + + // Check and store if we are on a SDL backend that supports global mouse position + // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) + bool mouse_can_use_global_state = false; +#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE + const char* sdl_backend = SDL_GetCurrentVideoDriver(); + const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; + for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++) + if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0) + mouse_can_use_global_state = true; +#endif + + // Setup backend capabilities flags + ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)(); + io.BackendPlatformUserData = (void*)bd; + io.BackendPlatformName = "imgui_impl_sdl3"; + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + bd->Window = window; + bd->Renderer = renderer; + bd->MouseCanUseGlobalState = mouse_can_use_global_state; + + io.SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; + io.ClipboardUserData = nullptr; + + // Load mouse cursors + bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); + + // Set platform dependent data in viewport + // Our mouse update function expect PlatformHandle to be filled for the main viewport + ImGuiViewport* main_viewport = ImGui::GetMainViewport(); + main_viewport->PlatformHandleRaw = nullptr; + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(window, &info)) + { +#if defined(SDL_VIDEO_DRIVER_WINDOWS) + main_viewport->PlatformHandleRaw = (void*)info.info.win.window; +#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA) + main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; +#endif + } + + // From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event. + // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered. + // (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application. + // It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click: + // you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED) +#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); +#endif + + // From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710) +#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE + SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0"); +#endif + + return true; +} + +bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) +{ + IM_UNUSED(sdl_gl_context); // Viewport branch will need this. + return ImGui_ImplSDL3_Init(window, nullptr); +} + +bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window) +{ +#if !SDL_HAS_VULKAN + IM_ASSERT(0 && "Unsupported"); +#endif + return ImGui_ImplSDL3_Init(window, nullptr); +} + +bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window) +{ +#if !defined(_WIN32) + IM_ASSERT(0 && "Unsupported"); +#endif + return ImGui_ImplSDL3_Init(window, nullptr); +} + +bool ImGui_ImplSDL3_InitForMetal(SDL_Window* window) +{ + return ImGui_ImplSDL3_Init(window, nullptr); +} + +bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer) +{ + return ImGui_ImplSDL3_Init(window, renderer); +} + +void ImGui_ImplSDL3_Shutdown() +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + + if (bd->ClipboardTextData) + SDL_free(bd->ClipboardTextData); + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) + SDL_FreeCursor(bd->MouseCursors[cursor_n]); + bd->LastMouseCursor = NULL; + + io.BackendPlatformName = nullptr; + io.BackendPlatformUserData = nullptr; + IM_DELETE(bd); +} + +static void ImGui_ImplSDL3_UpdateMouseData() +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + ImGuiIO& io = ImGui::GetIO(); + + // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) +#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE + // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside + SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); + const bool is_app_focused = (bd->Window == focused_window); +#else + const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only +#endif + if (is_app_focused) + { + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); + + // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + { + int window_x, window_y, mouse_x_global, mouse_y_global; + SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); + SDL_GetWindowPosition(bd->Window, &window_x, &window_y); + io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); + } + } +} + +static void ImGui_ImplSDL3_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) + return; + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + SDL_ShowCursor(SDL_FALSE); + } + else + { + // Show OS mouse cursor + SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; + if (bd->LastMouseCursor != expected_cursor) + { + SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113) + bd->LastMouseCursor = expected_cursor; + } + SDL_ShowCursor(SDL_TRUE); + } +} + +static void ImGui_ImplSDL3_UpdateGamepads() +{ + ImGuiIO& io = ImGui::GetIO(); + if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. + return; + + // Get gamepad + io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; + SDL_GameController* game_controller = SDL_GameControllerOpen(0); + if (!game_controller) + return; + io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + + // Update gamepad inputs + #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) + #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); } + #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } + const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. + MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); + MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); + MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square + MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle + MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle + MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross + MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); + MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); + MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); + MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767); + MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767); + MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK); + MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK); + MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767); + #undef MAP_BUTTON + #undef MAP_ANALOG +} + +void ImGui_ImplSDL3_NewFrame() +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDL3_Init()?"); + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + SDL_GetWindowSize(bd->Window, &w, &h); + if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) + w = h = 0; + if (bd->Renderer != nullptr) + SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h); + else + SDL_GL_GetDrawableSize(bd->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 (we don't use SDL_GetTicks() because it is using millisecond resolution) + static Uint64 frequency = SDL_GetPerformanceFrequency(); + Uint64 current_time = SDL_GetPerformanceCounter(); + io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); + bd->Time = current_time; + + if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) + { + bd->MouseWindowID = 0; + bd->PendingMouseLeaveFrame = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + } + + ImGui_ImplSDL3_UpdateMouseData(); + ImGui_ImplSDL3_UpdateMouseCursor(); + + // Update game controllers (if enabled and available) + ImGui_ImplSDL3_UpdateGamepads(); +} diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h new file mode 100644 index 00000000..6dd54e6a --- /dev/null +++ b/backends/imgui_impl_sdl3.h @@ -0,0 +1,36 @@ +// dear imgui: Platform Backend for SDL3 +// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) +// (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) + +// Implemented features: +// [X] Platform: Clipboard support. +// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] +// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// Missing features: +// [ ] Platform: SDL3 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. + +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API + +struct SDL_Window; +struct SDL_Renderer; +typedef union SDL_Event SDL_Event; + +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window); +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window); +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForMetal(SDL_Window* window); +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer); +IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame(); +IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event); + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +static inline void ImGui_ImplSDL3_NewFrame(SDL_Window*) { ImGui_ImplSDL3_NewFrame(); } // 1.84: removed unnecessary parameter +#endif From 13fbd994915fbb93e3a3b467416532516bad0947 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Feb 2023 13:49:37 +0100 Subject: [PATCH 6/6] Backends: SDL3: update to run with SDL3. Examples: Add SDL3+Gl example. Remove some version checks. (#6146) More update upcoming in docking branch. --- backends/imgui_impl_sdl3.cpp | 177 ++++++++-------- backends/imgui_impl_sdl3.h | 9 +- docs/BACKENDS.md | 1 + docs/CHANGELOG.txt | 5 + examples/example_sdl3_opengl3/Makefile | 84 ++++++++ .../example_sdl3_opengl3/Makefile.emscripten | 92 +++++++++ examples/example_sdl3_opengl3/README.md | 57 ++++++ examples/example_sdl3_opengl3/build_win32.bat | 8 + .../example_sdl3_opengl3.vcxproj | 182 +++++++++++++++++ .../example_sdl3_opengl3.vcxproj.filters | 64 ++++++ examples/example_sdl3_opengl3/main.cpp | 193 ++++++++++++++++++ examples/imgui_examples.sln | 10 + 12 files changed, 780 insertions(+), 102 deletions(-) create mode 100644 examples/example_sdl3_opengl3/Makefile create mode 100644 examples/example_sdl3_opengl3/Makefile.emscripten create mode 100644 examples/example_sdl3_opengl3/README.md create mode 100644 examples/example_sdl3_opengl3/build_win32.bat create mode 100644 examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj create mode 100644 examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj.filters create mode 100644 examples/example_sdl3_opengl3/main.cpp diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 78f0cf0b..6e8abee8 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -1,15 +1,13 @@ -// dear imgui: Platform Backend for SDL3 +// dear imgui: Platform Backend for SDL3 (*EXPERIMENTAL*) // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) -// (Prefer SDL 2.0.5+ for full feature support.) +// (IMPORTANT: SDL 3.0.0 is NOT YET RELEASED. IT IS POSSIBLE THAT ITS SPECS/API WILL CHANGE BEFORE RELEASE) // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. -// Missing features: -// [ ] Platform: SDL3 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -24,18 +22,17 @@ #include "imgui_impl_sdl3.h" // SDL -#include -#include +#include +#include #if defined(__APPLE__) #include #endif -#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1 #else #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 #endif -#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) // SDL Data struct ImGui_ImplSDL3_Data @@ -194,10 +191,10 @@ static ImGuiKey ImGui_ImplSDL3_KeycodeToImGuiKey(int keycode) static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) { ImGuiIO& io = ImGui::GetIO(); - io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0); - io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0); - io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0); - io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0); + io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & SDL_KMOD_CTRL) != 0); + io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & SDL_KMOD_SHIFT) != 0); + io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & SDL_KMOD_ALT) != 0); + io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0); } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. @@ -212,30 +209,25 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) switch (event->type) { - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: { ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); return true; } - case SDL_MOUSEWHEEL: + case SDL_EVENT_MOUSE_WHEEL: { //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); -#if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten! - float wheel_x = -event->wheel.preciseX; - float wheel_y = event->wheel.preciseY; -#else - float wheel_x = -(float)event->wheel.x; - float wheel_y = (float)event->wheel.y; -#endif -#ifdef __EMSCRIPTEN__ + float wheel_x = -event->wheel.x; + float wheel_y = event->wheel.y; + #ifdef __EMSCRIPTEN__ wheel_x /= 100.0f; -#endif + #endif io.AddMouseWheelEvent(wheel_x, wheel_y); return true; } - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: { int mouse_button = -1; if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } @@ -245,45 +237,45 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } if (mouse_button == -1) break; - io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); - bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); + io.AddMouseButtonEvent(mouse_button, (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)); + bd->MouseButtonsDown = (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); return true; } - case SDL_TEXTINPUT: + case SDL_EVENT_TEXT_INPUT: { io.AddInputCharactersUTF8(event->text.text); return true; } - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: { ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); ImGuiKey key = ImGui_ImplSDL3_KeycodeToImGuiKey(event->key.keysym.sym); - io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); + io.AddKeyEvent(key, (event->type == SDL_EVENT_KEY_DOWN)); io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. return true; } - case SDL_WINDOWEVENT: + case SDL_EVENT_WINDOW_MOUSE_ENTER: + { + bd->MouseWindowID = event->window.windowID; + bd->PendingMouseLeaveFrame = 0; + return true; + } + // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why + // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. + // FIXME: Unconfirmed whether this is still needed with SDL3. + case SDL_EVENT_WINDOW_MOUSE_LEAVE: { - // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. - // - However we won't get a correct LEAVE event for a captured window. - // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, - // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why - // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. - Uint8 window_event = event->window.event; - if (window_event == SDL_WINDOWEVENT_ENTER) - { - bd->MouseWindowID = event->window.windowID; - bd->PendingMouseLeaveFrame = 0; - } - if (window_event == SDL_WINDOWEVENT_LEAVE) - bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; - if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) - io.AddFocusEvent(true); - else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) - io.AddFocusEvent(false); + bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; return true; } + case SDL_EVENT_WINDOW_FOCUS_GAINED: + io.AddFocusEvent(true); + return true; + case SDL_EVENT_WINDOW_FOCUS_LOST: + io.AddFocusEvent(false); + return true; } return false; } @@ -308,8 +300,8 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer) ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_sdl3"; - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) - io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) bd->Window = window; bd->Renderer = renderer; @@ -335,8 +327,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); main_viewport->PlatformHandleRaw = nullptr; SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (SDL_GetWindowWMInfo(window, &info)) + if (SDL_GetWindowWMInfo(window, &info, SDL_SYSWM_CURRENT_VERSION)) { #if defined(SDL_VIDEO_DRIVER_WINDOWS) main_viewport->PlatformHandleRaw = (void*)info.info.win.window; @@ -370,9 +361,6 @@ bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window) { -#if !SDL_HAS_VULKAN - IM_ASSERT(0 && "Unsupported"); -#endif return ImGui_ImplSDL3_Init(window, nullptr); } @@ -403,7 +391,7 @@ void ImGui_ImplSDL3_Shutdown() if (bd->ClipboardTextData) SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) - SDL_FreeCursor(bd->MouseCursors[cursor_n]); + SDL_DestroyCursor(bd->MouseCursors[cursor_n]); bd->LastMouseCursor = NULL; io.BackendPlatformName = nullptr; @@ -429,15 +417,17 @@ static void ImGui_ImplSDL3_UpdateMouseData() { // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) if (io.WantSetMousePos) - SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); + SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) { - int window_x, window_y, mouse_x_global, mouse_y_global; + // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) + float mouse_x_global, mouse_y_global; + int window_x, window_y; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); - SDL_GetWindowPosition(bd->Window, &window_x, &window_y); - io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); + SDL_GetWindowPosition(focused_window, &window_x, &window_y); + io.AddMousePosEvent(mouse_x_global - window_x, mouse_y_global - window_y); } } } @@ -453,7 +443,7 @@ static void ImGui_ImplSDL3_UpdateMouseCursor() if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) { // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - SDL_ShowCursor(SDL_FALSE); + SDL_HideCursor(); } else { @@ -464,7 +454,7 @@ static void ImGui_ImplSDL3_UpdateMouseCursor() SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113) bd->LastMouseCursor = expected_cursor; } - SDL_ShowCursor(SDL_TRUE); + SDL_ShowCursor(); } } @@ -476,40 +466,40 @@ static void ImGui_ImplSDL3_UpdateGamepads() // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - SDL_GameController* game_controller = SDL_GameControllerOpen(0); - if (!game_controller) + SDL_Gamepad* gamepad = SDL_OpenGamepad(0); + if (!gamepad) return; io.BackendFlags |= ImGuiBackendFlags_HasGamepad; // Update gamepad inputs #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) - #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); } - #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } + #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GetGamepadButton(gamepad, BUTTON_NO) != 0); } + #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GetGamepadAxis(gamepad, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. - MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); - MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); - MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square - MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle - MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle - MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross - MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); - MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); - MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); - MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); - MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767); - MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767); - MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK); - MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK); - MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767); + MAP_BUTTON(ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START); + MAP_BUTTON(ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK); + MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_X); // Xbox X, PS Square + MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_B); // Xbox B, PS Circle + MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_Y); // Xbox Y, PS Triangle + MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_A); // Xbox A, PS Cross + MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT); + MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT); + MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP); + MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN); + MAP_BUTTON(ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); + MAP_BUTTON(ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); + MAP_ANALOG(ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767); + MAP_ANALOG(ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767); + MAP_BUTTON(ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK); + MAP_BUTTON(ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK); + MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767); + MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768); + MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767); #undef MAP_BUTTON #undef MAP_ANALOG } @@ -526,10 +516,7 @@ void ImGui_ImplSDL3_NewFrame() SDL_GetWindowSize(bd->Window, &w, &h); if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) w = h = 0; - if (bd->Renderer != nullptr) - SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h); - else - SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); + SDL_GetWindowSizeInPixels(bd->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); diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 6dd54e6a..f76ca948 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -1,14 +1,13 @@ -// dear imgui: Platform Backend for SDL3 +// dear imgui: Platform Backend for SDL3 (*EXPERIMENTAL*) // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) +// (IMPORTANT: SDL 3.0.0 is NOT YET RELEASED. IT IS POSSIBLE THAT ITS SPECS/API WILL CHANGE BEFORE RELEASE) // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. -// Missing features: -// [ ] Platform: SDL3 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -30,7 +29,3 @@ IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SD IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event); - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -static inline void ImGui_ImplSDL3_NewFrame(SDL_Window*) { ImGui_ImplSDL3_NewFrame(); } // 1.84: removed unnecessary parameter -#endif diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index c6edde0a..ef31bb02 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -63,6 +63,7 @@ List of Platforms Backends: imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org + imgui_impl_sdl3.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org (*EXPERIMENTAL*) imgui_impl_win32.cpp ; Win32 native API (Windows) imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 066e952a..66324647 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -98,6 +98,10 @@ All changes: for smooth scrolling as reported by SDL. (#4019, #6096) - Backends: SDL2: Avoid calling SDL_SetCursor() when cursor has not changed, as the function is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version). (#6113) +- Backends: SDL3: Added experimental imgui_impl_sdl3.cpp backend. (#6146) [@dovker, @ocornut] + SDL 3.0.0 has not yet been released, so it is possible that its specs/api will change before + release. This backend is provided as a convenience for early adopters etc. We don't recommend + switching to SDL3 before it is released. - Backends: GLFW: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096) [@ocornut, @wolfpld, @tolopolarity] - Backends: GLFW: Added ImGui_ImplGlfw_SetCallbacksChainForAllWindows() to instruct backend @@ -108,6 +112,7 @@ All changes: - Examples: refactored SDL2+GL and GLFW+GL examples to compile with Emscripten. (#2492, #2494, #3699, #3705) [@ocornut, @nicolasnoble] The dedicated example_emscripten_opengl3/ has been removed. +- Examples: Added SDL3+GL experimental example. (#6146) - Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx] diff --git a/examples/example_sdl3_opengl3/Makefile b/examples/example_sdl3_opengl3/Makefile new file mode 100644 index 00000000..3a00a31e --- /dev/null +++ b/examples/example_sdl3_opengl3/Makefile @@ -0,0 +1,84 @@ +# +# Cross Platform Makefile +# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X +# +# You will need SDL3 (http://www.libsdl.org) which is still unreleased/unpackaged. + +#CXX = g++ +#CXX = clang++ + +EXE = example_sdl3_opengl3 +IMGUI_DIR = ../.. +SOURCES = main.cpp +SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) +UNAME_S := $(shell uname -s) +LINUX_GL_LIBS = -lGL + +CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends +CXXFLAGS += -g -Wall -Wformat +LIBS = + +##--------------------------------------------------------------------- +## OPENGL ES +##--------------------------------------------------------------------- + +## This assumes a GL ES library available in the system, e.g. libGLESv2.so +# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2 +# LINUX_GL_LIBS = -lGLESv2 +## If you're on a Raspberry Pi and want to use the legacy drivers, +## use the following instead: +# LINUX_GL_LIBS = -L/opt/vc/lib -lbrcmGLESv2 + +##--------------------------------------------------------------------- +## BUILD FLAGS PER PLATFORM +##--------------------------------------------------------------------- + +ifeq ($(UNAME_S), Linux) #LINUX + ECHO_MESSAGE = "Linux" + LIBS += $(LINUX_GL_LIBS) -ldl `sdl3-config --libs` + + CXXFLAGS += `sdl3-config --cflags` + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(UNAME_S), Darwin) #APPLE + ECHO_MESSAGE = "Mac OS X" + LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs` + LIBS += -L/usr/local/lib -L/opt/local/lib + + CXXFLAGS += `sdl3-config --cflags` + CXXFLAGS += -I/usr/local/include -I/opt/local/include + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(OS), Windows_NT) + ECHO_MESSAGE = "MinGW" + LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` + + CXXFLAGS += `pkg-config --cflags sdl3` + CFLAGS = $(CXXFLAGS) +endif + +##--------------------------------------------------------------------- +## BUILD RULES +##--------------------------------------------------------------------- + +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/backends/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +all: $(EXE) + @echo Build complete for $(ECHO_MESSAGE) + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + +clean: + rm -f $(EXE) $(OBJS) diff --git a/examples/example_sdl3_opengl3/Makefile.emscripten b/examples/example_sdl3_opengl3/Makefile.emscripten new file mode 100644 index 00000000..b8c3570f --- /dev/null +++ b/examples/example_sdl3_opengl3/Makefile.emscripten @@ -0,0 +1,92 @@ +# +# Makefile to use with SDL+emscripten +# See https://emscripten.org/docs/getting_started/downloads.html +# for installation instructions. +# +# This Makefile assumes you have loaded emscripten's environment. +# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead) +# +# Running `make -f Makefile.emscripten` will produce three files: +# - web/index.html +# - web/index.js +# - web/index.wasm +# +# All three are needed to run the demo. + +CC = emcc +CXX = em++ +WEB_DIR = web +EXE = $(WEB_DIR)/index.html +IMGUI_DIR = ../.. +SOURCES = main.cpp +SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) +UNAME_S := $(shell uname -s) +CPPFLAGS = +LDFLAGS = +EMS = + +##--------------------------------------------------------------------- +## EMSCRIPTEN OPTIONS +##--------------------------------------------------------------------- + +# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only) +EMS += -s USE_SDL=2 +EMS += -s DISABLE_EXCEPTION_CATCHING=1 +LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1 + +# Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877) +#EMS += -s BINARYEN_TRAP_MODE=clamp +#EMS += -s SAFE_HEAP=1 ## Adds overhead + +# Emscripten allows preloading a file or folder to be accessible at runtime. +# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts" +# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html +# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.) +USE_FILE_SYSTEM ?= 0 +ifeq ($(USE_FILE_SYSTEM), 0) +LDFLAGS += -s NO_FILESYSTEM=1 +CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS +endif +ifeq ($(USE_FILE_SYSTEM), 1) +LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts +endif + +##--------------------------------------------------------------------- +## FINAL BUILD FLAGS +##--------------------------------------------------------------------- + +CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends +#CPPFLAGS += -g +CPPFLAGS += -Wall -Wformat -Os $(EMS) +LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html +LDFLAGS += $(EMS) + +##--------------------------------------------------------------------- +## BUILD RULES +##--------------------------------------------------------------------- + +%.o:%.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/%.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/backends/%.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +all: $(EXE) + @echo Build complete for $(EXE) + +$(WEB_DIR): + mkdir $@ + +serve: all + python3 -m http.server -d $(WEB_DIR) + +$(EXE): $(OBJS) $(WEB_DIR) + $(CXX) -o $@ $(OBJS) $(LDFLAGS) + +clean: + rm -rf $(OBJS) $(WEB_DIR) diff --git a/examples/example_sdl3_opengl3/README.md b/examples/example_sdl3_opengl3/README.md new file mode 100644 index 00000000..8b137b16 --- /dev/null +++ b/examples/example_sdl3_opengl3/README.md @@ -0,0 +1,57 @@ + +# How to Build + +## Windows with Visual Studio's IDE + +Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) if necessary. + +## Windows with Visual Studio's CLI + +Use build_win32.bat or directly: +``` +set SDL2_DIR=path_to_your_sdl3_folder +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL3.lib opengl32.lib /subsystem:console +# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries +# or for 64-bit: +cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL3.lib SDL2mainopengl32.lib /subsystem:console +``` + +## Linux and similar Unixes + +Use our Makefile or directly: +``` +c++ `sdl3-config --cflags` -I .. -I ../.. -I ../../backends + main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp + `sdl3-config --libs` -lGL -ldl +``` + +## macOS + +Use our Makefile or directly: +``` +brew install sdl3 +c++ `sdl3-config --cflags` -I .. -I ../.. -I ../../backends + main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp + `sdl3-config --libs` -framework OpenGl -framework CoreFoundation +``` + +## Emscripten + +**Building** + +You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions + +- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools. +- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup. +- Then build using `make -f Makefile.emscripten` while in the current directory. + +**Running an Emscripten project** + +To run on a local machine: +- `make -f Makefile.emscripten serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build. +- Otherwise, generally you will need a local webserver. Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):
+_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_ +- Emscripten SDK has a handy `emrun` command: `emrun web/index.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details. +- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses). +- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`. +- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only). diff --git a/examples/example_sdl3_opengl3/build_win32.bat b/examples/example_sdl3_opengl3/build_win32.bat new file mode 100644 index 00000000..ba7d25bc --- /dev/null +++ b/examples/example_sdl3_opengl3/build_win32.bat @@ -0,0 +1,8 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +@set OUT_DIR=Debug +@set OUT_EXE=example_sdl3_opengl3 +@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp +@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib opengl32.lib shell32.lib +mkdir %OUT_DIR% +cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj new file mode 100644 index 00000000..60c99645 --- /dev/null +++ b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj @@ -0,0 +1,182 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {84AAA301-84FE-428B-9E3E-817BC8123C0C} + example_sdl3_opengl3 + 8.1 + + + + Application + true + MultiByte + v140 + + + Application + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + + + true + %SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + + + true + %SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL3.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL3.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj.filters b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj.filters new file mode 100644 index 00000000..f590e326 --- /dev/null +++ b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj.filters @@ -0,0 +1,64 @@ + + + + + {20b90ce4-7fcb-4731-b9a0-075f875de82d} + + + {f18ab499-84e1-499f-8eff-9754361e0e52} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + sources + + + imgui + + + imgui + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + sources + + + + + + imgui + + + diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp new file mode 100644 index 00000000..613228b0 --- /dev/null +++ b/examples/example_sdl3_opengl3/main.cpp @@ -0,0 +1,193 @@ +// Dear ImGui: standalone example application for SDL3 + OpenGL +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#include "imgui.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_opengl3.h" +#include +#include +#if defined(IMGUI_IMPL_OPENGL_ES2) +#include +#else +#include +#endif + +// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + +// Main code +int main(int, char**) +{ + // Setup SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) + { + printf("Error: %s\n", SDL_GetError()); + return -1; + } + + // Decide GL+GLSL versions +#if defined(IMGUI_IMPL_OPENGL_ES2) + // GL ES 2.0 + GLSL 100 + const char* glsl_version = "#version 100"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#elif defined(__APPLE__) + // GL 3.2 Core + GLSL 150 + const char* glsl_version = "#version 150"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); +#else + // GL 3.0 + GLSL 130 + const char* glsl_version = "#version 130"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#endif + + // Create window with graphics context + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + SDL_GL_MakeCurrent(window, gl_context); + SDL_GL_SetSwapInterval(1); // Enable vsync + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL3_InitForOpenGL(window, gl_context); + ImGui_ImplOpenGL3_Init(glsl_version); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; +#ifdef __EMSCRIPTEN__ + // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. + // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. + io.IniFilename = NULL; + EMSCRIPTEN_MAINLOOP_BEGIN +#else + while (!done) +#endif + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + if (event.type == SDL_EVENT_QUIT) + done = true; + if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) + done = true; + } + + // Start the Dear ImGui frame + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + SDL_GL_SwapWindow(window); + } +#ifdef __EMSCRIPTEN__ + EMSCRIPTEN_MAINLOOP_END; +#endif + + // Cleanup + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL3_Shutdown(); + ImGui::DestroyContext(); + + SDL_GL_DeleteContext(gl_context); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index 9b442b27..fdaf0692 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -27,6 +27,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_sdlrenderer", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_vulkan", "example_sdl2_vulkan\example_sdl2_vulkan.vcxproj", "{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_opengl3", "example_sdl3_opengl3\example_sdl3_opengl3.vcxproj", "{84AAA301-84FE-428B-9E3E-817BC8123C0C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -131,6 +133,14 @@ Global {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|Win32.Build.0 = Release|Win32 {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|x64.ActiveCfg = Release|x64 {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|x64.Build.0 = Release|x64 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.ActiveCfg = Debug|Win32 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.Build.0 = Debug|Win32 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|x64.ActiveCfg = Debug|x64 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|x64.Build.0 = Debug|x64 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Release|Win32.ActiveCfg = Release|Win32 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Release|Win32.Build.0 = Release|Win32 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Release|x64.ActiveCfg = Release|x64 + {84AAA301-84FE-428B-9E3E-817BC8123C0C}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE