From 62b17f928ee43cf681e5e1dcbe27a463c1ebef4d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 21 Sep 2021 17:12:30 +0200 Subject: [PATCH] Backends: SDL_Renderer: Added renderer backend for SDL 2.0.17+ (#3926) (Squashed 20 commits) --- backends/imgui_impl_sdl.cpp | 5 + backends/imgui_impl_sdl.h | 1 + backends/imgui_impl_sdlrenderer.cpp | 223 ++++++++++++++++++ backends/imgui_impl_sdlrenderer.h | 19 ++ docs/BACKENDS.md | 1 + docs/EXAMPLES.md | 5 + docs/README.md | 2 +- examples/example_sdl_sdlrenderer/Makefile | 79 +++++++ examples/example_sdl_sdlrenderer/README.md | 25 ++ .../example_sdl_sdlrenderer/build_win32.bat | 8 + .../example_sdl_sdlrenderer.vcxproj | 181 ++++++++++++++ .../example_sdl_sdlrenderer.vcxproj.filters | 61 +++++ examples/example_sdl_sdlrenderer/main.cpp | 168 +++++++++++++ 13 files changed, 777 insertions(+), 1 deletion(-) create mode 100644 backends/imgui_impl_sdlrenderer.cpp create mode 100644 backends/imgui_impl_sdlrenderer.h create mode 100644 examples/example_sdl_sdlrenderer/Makefile create mode 100644 examples/example_sdl_sdlrenderer/README.md create mode 100644 examples/example_sdl_sdlrenderer/build_win32.bat create mode 100644 examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj create mode 100644 examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters create mode 100644 examples/example_sdl_sdlrenderer/main.cpp diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index e5f99bcb..651fda51 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -251,6 +251,11 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) return true; } +bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window) +{ + return ImGui_ImplSDL2_Init(window); +} + bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) { IM_UNUSED(sdl_gl_context); // Viewport branch will need this. diff --git a/backends/imgui_impl_sdl.h b/backends/imgui_impl_sdl.h index 9b40a676..f85233af 100644 --- a/backends/imgui_impl_sdl.h +++ b/backends/imgui_impl_sdl.h @@ -21,6 +21,7 @@ struct SDL_Window; typedef union SDL_Event SDL_Event; +IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); diff --git a/backends/imgui_impl_sdlrenderer.cpp b/backends/imgui_impl_sdlrenderer.cpp new file mode 100644 index 00000000..a268deec --- /dev/null +++ b/backends/imgui_impl_sdlrenderer.cpp @@ -0,0 +1,223 @@ +// dear imgui: Renderer Backend for SDL_Renderer, with Platform Backend SDL +// (Requires: SDL 2.0.17+) + +// Implemented features: + +// 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. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + + +// CHANGELOG +// 2021-16-03: Creation + +#include "imgui.h" +#include "imgui_impl_sdlrenderer.h" +#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier +#include // intptr_t +#else +#include // intptr_t +#endif + +#include "SDL.h" + +#if SDL_MAJOR_VERSION < 2 || SDL_MINOR_VERSION < 0 || SDL_PATCHLEVEL < 17 +# error Requires: SDL 2.0.17+ because of SDL_RenderGeometry function +#endif + +struct ImGui_ImplSDLRenderer_Data +{ + SDL_Renderer *SDLRenderer; + SDL_Texture *FontTexture; + ImGui_ImplSDLRenderer_Data() { memset(this, 0, sizeof(*this)); } +}; + +// 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_ImplSDLRenderer_Data* ImGui_ImplSDLRenderer_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + +// Functions +bool ImGui_ImplSDLRenderer_Init(SDL_Renderer *renderer) +{ + ImGuiIO& io = ImGui::GetIO(); + IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); + IM_ASSERT(renderer != NULL && "SDL_Renderer not initialized!"); + + // Setup backend capabilities flags + ImGui_ImplSDLRenderer_Data* bd = IM_NEW(ImGui_ImplSDLRenderer_Data)(); + io.BackendRendererUserData = (void*)bd; + io.BackendRendererName = "imgui_impl_SDLRenderer"; + + bd->SDLRenderer = renderer; + return true; +} + +void ImGui_ImplSDLRenderer_Shutdown() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData(); + + ImGui_ImplSDLRenderer_DestroyDeviceObjects(); + + io.BackendRendererName = NULL; + io.BackendRendererUserData = NULL; + IM_DELETE(bd); +} + +static void ImGui_ImplSDLRenderer_SetupRenderState() +{ + ImGui_ImplSDLRenderer_Data *bd = ImGui_ImplSDLRenderer_GetBackendData(); + + // Clear out any viewports and cliprects set by the user + SDL_RenderSetViewport(bd->SDLRenderer, NULL); + SDL_RenderSetClipRect(bd->SDLRenderer, NULL); +} + +void ImGui_ImplSDLRenderer_NewFrame() +{ + ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDLRenderer_Init()?"); + + if (!bd->FontTexture) { + ImGui_ImplSDLRenderer_CreateDeviceObjects(); + } +} + +void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data) +{ + ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData(); + + // If there's a scale factor set by the user, use that instead + float rsX = 1.0f; + float rsY = 1.0f; + SDL_RenderGetScale(bd->SDLRenderer, &rsX, &rsY); + + ImVec2 renderScale; + // If the user has specified a scale factor to SDL_Renderer already (via SDL_RenderSetScale()), SDL will scale whatever we pass + // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here. + renderScale.x = (rsX == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; + renderScale.y = (rsY == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; + + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * renderScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * renderScale.y); + if (fb_width == 0 || fb_height == 0) + return; + + + // Will project scissor/clipping rectangles into framebuffer space + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = renderScale; + + ImGui_ImplSDLRenderer_SetupRenderState(); + + for (int n = 0; n < draw_data->CmdListsCount; n++) { + + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; + const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; + + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) { + ImGui_ImplSDLRenderer_SetupRenderState(); + } else { + pcmd->UserCallback(cmd_list, pcmd); + } + } + else + { + // Project scissor/clipping rectangles into framebuffer space + ImVec4 clip_rect; + clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; + clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; + clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; + clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; + + if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) + { + SDL_Rect r; + r.x = clip_rect.x; + r.y = clip_rect.y; + r.w = clip_rect.z - clip_rect.x; + r.h = clip_rect.w - clip_rect.y; + + SDL_RenderSetClipRect(bd->SDLRenderer, &r); + + + int xy_stride = sizeof(ImDrawVert); + float *xy = (float *)((char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)); + + int uv_stride = sizeof(ImDrawVert); + float *uv = (float*)((char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)); + + int col_stride = sizeof(ImDrawVert); + int *color = (int*)((char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)); + + SDL_Texture *tex = (SDL_Texture*)pcmd->TextureId; + + SDL_RenderGeometryRaw(bd->SDLRenderer, tex, + xy, xy_stride, color, + col_stride, + uv, uv_stride, + cmd_list->VtxBuffer.Size, + idx_buffer, pcmd->ElemCount, sizeof (ImDrawIdx)); + + } + } + idx_buffer += pcmd->ElemCount; + } + } +} + +// Called by Init/NewFrame/Shutdown +bool ImGui_ImplSDLRenderer_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. + bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); + if (bd->FontTexture == NULL) { + SDL_Log("error creating texture"); + return false; + } + SDL_UpdateTexture(bd->FontTexture, NULL, pixels, 4 * width); + SDL_SetTextureBlendMode(bd->FontTexture, SDL_BLENDMODE_BLEND); + // Store our identifier + io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); + + return true; +} + +void ImGui_ImplSDLRenderer_DestroyFontsTexture() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData(); + if (bd->FontTexture) { + io.Fonts->SetTexID(0); + SDL_DestroyTexture(bd->FontTexture); + bd->FontTexture = NULL; + } +} + +bool ImGui_ImplSDLRenderer_CreateDeviceObjects() +{ + return ImGui_ImplSDLRenderer_CreateFontsTexture(); +} + +void ImGui_ImplSDLRenderer_DestroyDeviceObjects() +{ + ImGui_ImplSDLRenderer_DestroyFontsTexture(); +} + diff --git a/backends/imgui_impl_sdlrenderer.h b/backends/imgui_impl_sdlrenderer.h new file mode 100644 index 00000000..7b439618 --- /dev/null +++ b/backends/imgui_impl_sdlrenderer.h @@ -0,0 +1,19 @@ +// dear imgui: Renderer Backend for SDL using SDL_Renderer +// (Requires: SDL 2.0.17+) + + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API + +struct SDL_Renderer; + +IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_Init(SDL_Renderer *renderer); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data); + +// Called by Init/NewFrame/Shutdown +IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyDeviceObjects(); diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 2ad719a9..bbd66854 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -75,6 +75,7 @@ List of Renderer Backends: imgui_impl_metal.mm ; Metal (with ObjC) imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context) imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline) + imgui_impl_sdlrenderer.cpp; use SDL2 and SDL_Renderer, any SDL backend (opengl, gles, gles2, d3d9, d3d11, metal or software) can be used underneath imgui_impl_vulkan.cpp ; Vulkan imgui_impl_wgpu.cpp ; WebGPU diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 0fd7c250..69ecfa87 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -130,6 +130,11 @@ This uses more modern OpenGL calls and custom shaders.
This may actually also work with OpenGL 2.x contexts!
Prefer using that if you are using modern OpenGL in your application (anything with shaders). +[example_sdl_sdlrenderer/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_sdlrenderer/)
+Use SDL2 and SDL_Renderer, any SDL backend (opengl, gles, gles2, d3d9, d3d11, metal or software) can be used underneath
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_sdlrenderer.cpp
+It requires SDL 2.0.17+ + [example_glfw_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/)
GLFW (Win32, Mac, Linux) + Vulkan example.
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp
diff --git a/docs/README.md b/docs/README.md index 25850973..9d6dc93f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -116,7 +116,7 @@ On most platforms and when using C++, **you should be able to use a combination Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!** Officially maintained backends/bindings (in repository): -- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, Vulkan, WebGPU. +- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU. - Platforms: GLFW, SDL2, Win32, Glut, OSX, Android. - Frameworks: Emscripten, Allegro5, Marmalade. diff --git a/examples/example_sdl_sdlrenderer/Makefile b/examples/example_sdl_sdlrenderer/Makefile new file mode 100644 index 00000000..5667789a --- /dev/null +++ b/examples/example_sdl_sdlrenderer/Makefile @@ -0,0 +1,79 @@ +# +# Cross Platform Makefile +# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X +# +# You will need SDL2 (http://www.libsdl.org): +# Linux: +# apt-get install libsdl2-dev +# Mac OS X: +# brew install sdl2 +# MSYS2: +# pacman -S mingw-w64-i686-SDL2 +# + +#CXX = g++ +#CXX = clang++ + +EXE = example_sdl_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 +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) +UNAME_S := $(shell uname -s) + +CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends +CXXFLAGS += -g -Wall -Wformat +LIBS = + +##--------------------------------------------------------------------- +## BUILD FLAGS PER PLATFORM +##--------------------------------------------------------------------- + +ifeq ($(UNAME_S), Linux) #LINUX + ECHO_MESSAGE = "Linux" + LIBS += -lGL -ldl `sdl2-config --libs` + + CXXFLAGS += `sdl2-config --cflags` + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(UNAME_S), Darwin) #APPLE + ECHO_MESSAGE = "Mac OS X" + LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs` + LIBS += -L/usr/local/lib -L/opt/local/lib + + CXXFLAGS += `sdl2-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 sdl2` + + CXXFLAGS += `pkg-config --cflags sdl2` + 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_sdl_sdlrenderer/README.md b/examples/example_sdl_sdlrenderer/README.md new file mode 100644 index 00000000..5f431240 --- /dev/null +++ b/examples/example_sdl_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_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/example_sdl_sdlrenderer/build_win32.bat b/examples/example_sdl_sdlrenderer/build_win32.bat new file mode 100644 index 00000000..6c1b5fde --- /dev/null +++ b/examples/example_sdl_sdlrenderer/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_sdl_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 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_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj new file mode 100644 index 00000000..376a2275 --- /dev/null +++ b/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj @@ -0,0 +1,181 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} + example_sdl_sdlrenderer + 8.1 + + + + Application + true + MultiByte + v110 + + + Application + true + MultiByte + v110 + + + Application + false + true + MultiByte + v110 + + + Application + false + true + MultiByte + v110 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + + + true + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + + + true + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters b/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters new file mode 100644 index 00000000..01e98fcb --- /dev/null +++ b/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters @@ -0,0 +1,61 @@ + + + + + {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 + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + + sources + + + diff --git a/examples/example_sdl_sdlrenderer/main.cpp b/examples/example_sdl_sdlrenderer/main.cpp new file mode 100644 index 00000000..4fd04028 --- /dev/null +++ b/examples/example_sdl_sdlrenderer/main.cpp @@ -0,0 +1,168 @@ +// Dear ImGui: standalone example application for SDL2 + SDL_Renderer +// (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 + +// See imgui_impl_sdl.cpp for details. +// (Requires: SDL 2.0.17+) + +#include "imgui.h" +#include "imgui_impl_sdl.h" +#include "imgui_impl_sdlrenderer.h" +#include +#include + +#if SDL_MAJOR_VERSION < 2 || SDL_MINOR_VERSION < 0 || SDL_PATCHLEVEL < 17 +# error Requires: SDL 2.0.17+ because of SDL_RenderGeometry function +#endif + +// Main code +int main(int, char**) +{ + // Setup SDL + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) + { + printf("Error: %s\n", SDL_GetError()); + return -1; + } + + // SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2"); + // SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); + // SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); + + // Setup window + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + + // 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::StyleColorsClassic(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL2_InitForSDLRenderer(window); + + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (renderer == NULL) { + SDL_Log("Error creating SDL renderer"); + return false; + } else { + SDL_RendererInfo info; + SDL_GetRendererInfo(renderer, &info); + SDL_Log("Current SDL Renderer: %s", info.name); + } + + ImGui_ImplSDLRenderer_Init(renderer); + + // 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. + // - 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 \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.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; + while (!done) + { + // 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. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // 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_ImplSDL2_ProcessEvent(&event); + if (event.type == SDL_QUIT) + done = true; + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) + done = true; + } + + // Start the Dear ImGui frame + ImGui_ImplSDLRenderer_NewFrame(); + ImGui_ImplSDL2_NewFrame(window); + 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 created 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(); + ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData()); + + SDL_RenderPresent(renderer); + } + + // Cleanup + ImGui_ImplSDLRenderer_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +}