Nuklear icon indicating copy to clipboard operation
Nuklear copied to clipboard

SDL3 support

Open trexxet opened this issue 1 year ago • 4 comments

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

trexxet avatar Jan 04 '25 17:01 trexxet

Would love for either SDL_GPU or SDL_renderer implementation so it would work across different graphics platforms.

Two attempts that I know of...

  1. lessthan3 started up a port of the sdl3_gl2 demos: https://github.com/Immediate-Mode-UI/Nuklear/pull/719
  2. I've opened up a sdl3 branch with some initial attempts too

RobLoach avatar Jan 05 '25 19:01 RobLoach

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.

trexxet avatar Jan 06 '25 18:01 trexxet

Still worth to keep the issue open. Good to have a tracking thread, thanks :+1:

RobLoach avatar Jan 07 '25 16:01 RobLoach

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
}

nuklear-opengl-sdl3-c.zip

Image

8Observer8 avatar Jun 07 '25 15:06 8Observer8

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!

sleeptightAnsiC avatar Nov 04 '25 17:11 sleeptightAnsiC

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.

sleeptightAnsiC avatar Nov 16 '25 22:11 sleeptightAnsiC

🔥

RobLoach avatar Nov 16 '25 22:11 RobLoach