SDL3 support
Shouldn't be hard, just a few patches to nuklear_sdl_gl3.h
Here's my working solution using CMake:
file(READ ${NUKLEAR_PREFIX_INCLUDE}/nuklear_sdl_gl3.h SDL_FILE_CONTENTS)
string(REPLACE "SDL2" "SDL3" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_GetTicks64" "SDL_GetTicks" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_GL_GetDrawableSize" "SDL_GetWindowSizeInPixels" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_TRUE" "true" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_FALSE" "false" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_KEYUP" "SDL_EVENT_KEY_UP" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_KEYDOWN" "SDL_EVENT_KEY_DOWN" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_MOUSEBUTTONUP" "SDL_EVENT_MOUSE_BUTTON_UP" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_MOUSEBUTTONDOWN" "SDL_EVENT_MOUSE_BUTTON_DOWN" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_MOUSEMOTION" "SDL_EVENT_MOUSE_MOTION" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_MOUSEWHEEL" "SDL_EVENT_MOUSE_WHEEL" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_TEXTINPUT" "SDL_EVENT_TEXT_INPUT" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_b" "SDLK_B" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_c" "SDLK_C" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_e" "SDLK_E" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_r" "SDLK_R" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_v" "SDLK_V" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_x" "SDLK_X" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDLK_z" "SDLK_Z" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "const Uint8* state = SDL_GetKeyboardState(0);" "const _Bool* state = SDL_GetKeyboardState(0);" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "SDL_SetRelativeMouseMode(" "SDL_SetWindowRelativeMouseMode(sdl.win, " SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "switch(evt->key.keysym.sym)" "switch(evt->key.key)" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
file(WRITE ${NUKLEAR_PREFIX_INCLUDE}/nuklear_sdl_gl3.h "${SDL_FILE_CONTENTS}")
Also, please, add the extern "C" wrap to nuklear_sdl_gl3.h
Would love for either SDL_GPU or SDL_renderer implementation so it would work across different graphics platforms.
Two attempts that I know of...
- lessthan3 started up a port of the sdl3_gl2 demos: https://github.com/Immediate-Mode-UI/Nuklear/pull/719
- I've opened up a
sdl3branch with some initial attempts too
Oh, should have searched for PRs - I have checked issues only. Anyway, this patch may be useful for anyone trying to use SDL3 before official support.
Still worth to keep the issue open. Good to have a tracking thread, thanks :+1:
I added the following changes to the nuklear_sdl_gles2.h
string(REPLACE "SDLK_a" "SDLK_A" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "evt->wheel.preciseX, evt->wheel.preciseY" "evt->wheel.x, evt->wheel.y" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "KMOD_LCTRL" "SDL_KMOD_LCTRL" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
string(REPLACE "KMOD_RCTRL" "SDL_KMOD_RCTRL" SDL_FILE_CONTENTS "${SDL_FILE_CONTENTS}")
The problem is that it is impossible to type in the "Edit Box" on Windows 10 and WebAssembly: https://nuklear-opengl-sdl3-c.netlify.app/
main.c
#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#ifdef __EMSCRIPTEN__
#include <SDL3/SDL_opengles2.h>
#else
#include <glad/glad.h>
#endif // __EMSCRIPTEN__
// #define NK_INCLUDE_FIXED_TYPES
// #define NK_INCLUDE_DEFAULT_ALLOCATOR
// #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
// #define NK_INCLUDE_FONT_BAKING
// #define NK_INCLUDE_DEFAULT_FONT
// #define NK_UINT_DRAW_INDEX // ✅ This is the fix
// #define NK_IMPLEMENTATION
// #define NK_SDL_GL3_IMPLEMENTATION
// #include "nuklear.h"
// #define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_SDL_GLES2_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_sdl3_gles2.h"
static SDL_Window *window = NULL;
SDL_GLContext glContext;
struct nk_context *ctx;
char buffer[256];
int text_len = 0;
// This function runs once at startup
SDL_AppResult SDL_AppInit(void **appState, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO))
{
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // Enable MULTISAMPLE
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); // can be 2, 4, 8 or 16
const char *title = "Example in C, SDL3, and OpenGL";
size_t canvasWidth = 350;
size_t canvasHeight = 350;
window = SDL_CreateWindow(title, canvasWidth, canvasHeight, SDL_WINDOW_OPENGL);
if (!window)
{
SDL_Log("Couldn't create the window: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
glContext = SDL_GL_CreateContext(window);
if (!glContext)
{
SDL_Log("Couldn't create the glContext: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_GL_SetSwapInterval(1); // Turn on vertical sync
SDL_StartTextInput(NULL);
#ifdef __WIN32__
if (!gladLoadGL())
{
SDL_Log("Failed to initialize OpenGL function pointers");
return SDL_APP_FAILURE;
}
#endif // __WIN32__
glClearColor(50.f / 255.f, 50.f / 255.f, 50.f / 255.f, 1.f);
glViewport(0, 0, canvasWidth, canvasHeight);
// Init Nuklear
ctx = nk_sdl_init(window);
// Fonts (optional)
struct nk_font_atlas *atlas;
nk_sdl_font_stash_begin(&atlas);
nk_sdl_font_stash_end();
return SDL_APP_CONTINUE;
}
// This function runs when a new event (mouse input, keypresses, etc) occurs
SDL_AppResult SDL_AppEvent(void *appState, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT)
return SDL_APP_SUCCESS;
nk_input_begin(ctx);
nk_sdl_handle_event(event);
nk_input_end(ctx);
return SDL_APP_CONTINUE;
}
// This function runs once per frame, and is the heart of the program
SDL_AppResult SDL_AppIterate(void *appState)
{
// GUI
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 220, 150),
NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE |
NK_WINDOW_MINIMIZABLE | NK_WINDOW_TITLE))
{
// nk_layout_row_static(ctx, 30, 200, 1);
// nk_label(ctx, "Hello, Nuklear!", NK_TEXT_LEFT);
// if (nk_button_label(ctx, "Press Me"))
// {
// SDL_Log("Button was pressed!");
// }
nk_layout_row_dynamic(ctx, 30, 1);
nk_label(ctx, "Enter your name:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_FIELD | NK_EDIT_CLIPBOARD,
buffer, &text_len, sizeof(buffer),
nk_filter_default);
nk_label(ctx, "Hello, Nuklear!", NK_TEXT_LEFT);
if (nk_button_label(ctx, "Press Me"))
{
SDL_Log("Button was pressed!");
}
}
nk_end(ctx);
glClear(GL_COLOR_BUFFER_BIT);
nk_sdl_render(NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024);
// Update the screen
SDL_GL_SwapWindow(window);
return SDL_APP_CONTINUE;
}
// This function runs once at shutdown
void SDL_AppQuit(void *appState, SDL_AppResult result)
{
// Cleanup
nk_sdl_shutdown();
SDL_GL_DestroyContext(glContext);
// SDL will clean up the window for us
}
I've mentioned some concerns related to SDL_gpu, here https://github.com/Immediate-Mode-UI/Nuklear/issues/726#issuecomment-3487246016
~~I'm currently working on updated SDL_renderer demo as mentioned at the very bottom of https://github.com/Immediate-Mode-UI/Nuklear/pull/779~~
~~EDIT: aready submitted PR with new nk_sdl3_renderer demo: https://github.com/Immediate-Mode-UI/Nuklear/pull/852~~
EDIT: demo/sdl3_renderer has been already merged. Enjoy!
I think this one can be closed, since the other issue already tracks a request for SDL_gpu demo: https://github.com/Immediate-Mode-UI/Nuklear/issues/726
Swapping rendering backend should be trivial now.
🔥