浏览代码

feat: sdl3_renderer backend

ryan zmuda 11 月之前
父节点
当前提交
aecd78a204

+ 2 - 1
demo/sdl3_renderer/CMakeLists.txt

@@ -24,7 +24,8 @@ target_sources(${EXECUTABLE_NAME} PRIVATE main.c)
 
 find_package(SDL3 REQUIRED)
 
-target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3)
+# TODO: remove libm and fallback on Nuklear floor()
+target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3 m)
 
 # Nuklear Include Directory
 target_include_directories(${EXECUTABLE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../..)

+ 3 - 3
demo/sdl3_renderer/cmake/FindSDL3.cmake

@@ -1,8 +1,8 @@
 include(FetchContent)
 FetchContent_Declare(
     SDL3
-    GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
-    GIT_TAG eb3fc06
-    #GIT_SHALLOW 1
+    GIT_REPOSITORY  https://github.com/libsdl-org/SDL.git
+    GIT_TAG         release-3.2.2
+    GIT_SHALLOW     TRUE
 )
 FetchContent_MakeAvailable(SDL3)

+ 176 - 2
demo/sdl3_renderer/main.c

@@ -1,15 +1,88 @@
+/* nuklear - public domain */
+#include <stdio.h>
+#include <stddef.h> /* offsetof TODO: sdl2_renderer didn't need this header? */
+
 #define SDL_MAIN_USE_CALLBACKS
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
 
-#define NK_SDL_RENDERER_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_SDL3_RENDERER_IMPLEMENTATION
+#define NK_INCLUDE_STANDARD_BOOL
+#include "nuklear.h"
 #include "nuklear_sdl3_renderer.h"
 
+#define WINDOW_WIDTH 1200
+#define WINDOW_HEIGHT 800
+
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the defines */
+/*#define INCLUDE_ALL */
+/*#define INCLUDE_STYLE */
+/*#define INCLUDE_CALCULATOR */
+/*#define INCLUDE_CANVAS */
+#define INCLUDE_OVERVIEW
+/*#define INCLUDE_CONFIGURATOR */
+/*#define INCLUDE_NODE_EDITOR */
+
+#define INCLUDE_ALL
+
+#ifdef INCLUDE_ALL
+    #define INCLUDE_STYLE
+    #define INCLUDE_CALCULATOR
+    #define INCLUDE_CANVAS
+    #define INCLUDE_OVERVIEW
+    /* #define INCLUDE_CONFIGURATOR */
+    #define INCLUDE_NODE_EDITOR
+#endif
+
+#ifdef INCLUDE_STYLE
+    #include "../../demo/common/style.c"
+#endif
+#ifdef INCLUDE_CALCULATOR
+    #include "../../demo/common/calculator.c"
+#endif
+#ifdef INCLUDE_CANVAS
+    #include "../../demo/common/canvas.c"
+#endif
+#ifdef INCLUDE_OVERVIEW
+    #include "../../demo/common/overview.c"
+#endif
+/*
+#ifdef INCLUDE_CONFIGURATOR
+    #include "../../demo/common/style_configurator.c"
+#endif
+*/
+#ifdef INCLUDE_NODE_EDITOR
+    #include "../../demo/common/node_editor.c"
+#endif
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
+
 typedef struct AppContext {
     SDL_Window* window;
     SDL_Renderer* renderer;
 } AppContext;
 
+struct nk_context * ctx;
+struct nk_colorf bg;
+
 SDL_AppResult SDL_Fail(){
     SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
     return SDL_APP_FAILURE;
@@ -25,13 +98,57 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
         return SDL_Fail();
     }
 
-    if (!SDL_CreateWindowAndRenderer("Nuklear: SDL3 Renderer", 1200, 800, SDL_WINDOW_RESIZABLE, &appContext->window, &appContext->renderer)) {
+    if (!SDL_CreateWindowAndRenderer("Nuklear: SDL3 Renderer", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &appContext->window, &appContext->renderer)) {
         SDL_free(appContext);
         return SDL_Fail();
     }
 
+    SDL_StartTextInput(appContext->window);
+
+    bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
+
     *appstate = appContext;
 
+    float font_scale = 1;
+
+    {
+        int render_w, render_h;
+        int window_w, window_h;
+        float scale_x, scale_y;
+        SDL_GetCurrentRenderOutputSize(appContext->renderer, &render_w, &render_h);
+        SDL_GetWindowSize(appContext->window, &window_w, &window_h);
+        scale_x = (float)(render_w) / (float)(window_w);
+        scale_y = (float)(render_h) / (float)(window_h);
+        SDL_SetRenderScale(appContext->renderer, scale_x, scale_y);
+        font_scale = scale_y;
+    }
+
+    ctx = nk_sdl_init(appContext->window, appContext->renderer);
+
+    {
+        struct nk_font_atlas *atlas;
+        struct nk_font_config config = nk_font_config(0);
+        struct nk_font *font;
+
+        /* set up the font atlas and add desired font; note that font sizes are
+         * multiplied by font_scale to produce better results at higher DPIs */
+        nk_sdl_font_stash_begin(&atlas);
+        font = nk_font_atlas_add_default(atlas, 13 * font_scale, &config);
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14 * font_scale, &config);*/
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 16 * font_scale, &config);*/
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13 * font_scale, &config);*/
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12 * font_scale, &config);*/
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10 * font_scale, &config);*/
+        /*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13 * font_scale, &config);*/
+        nk_sdl_font_stash_end();
+
+        /* this hack makes the font appear to be scaled down to the desired
+         * size and is only necessary when font_scale > 1 */
+        font->handle.height /= font_scale;
+        /*nk_style_load_all_cursors(ctx, atlas->cursors);*/
+        nk_style_set_font(ctx, &font->handle);
+    }
+
     return SDL_APP_CONTINUE;
 }
 
@@ -49,12 +166,69 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event* event) {
 }
 
 SDL_AppResult SDL_AppIterate(void *appstate) {
+    nk_input_end(ctx);
     AppContext* app = (AppContext*)appstate;
 
+    /* GUI */
+    if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
+        NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
+        NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
+    {
+        enum {EASY, HARD};
+        static int op = EASY;
+        static int property = 20;
+
+        nk_layout_row_static(ctx, 30, 80, 1);
+        if (nk_button_label(ctx, "button"))
+            printf("button pressed\n");
+        nk_layout_row_dynamic(ctx, 30, 2);
+        if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
+        if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
+        nk_layout_row_dynamic(ctx, 25, 1);
+        nk_property_int(ctx, "Compression:", 0, &property, 1000, 1, 1);
+
+        nk_layout_row_dynamic(ctx, 20, 1);
+        nk_label(ctx, "background:", NK_TEXT_LEFT);
+        nk_layout_row_dynamic(ctx, 25, 1);
+        if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
+            nk_layout_row_dynamic(ctx, 120, 1);
+            bg = nk_color_picker(ctx, bg, NK_RGBA);
+            nk_layout_row_dynamic(ctx, 25, 1);
+            bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
+            bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
+            bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
+            bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
+            nk_combo_end(ctx);
+        }
+    }
+    nk_end(ctx);
+
+    /* -------------- EXAMPLES ---------------- */
+    #ifdef INCLUDE_CALCULATOR
+        calculator(ctx);
+    #endif
+    #ifdef INCLUDE_CANVAS
+    canvas(ctx);
+    #endif
+    #ifdef INCLUDE_OVERVIEW
+        overview(ctx);
+    #endif
+    #ifdef INCLUDE_CONFIGURATOR
+        style_configurator(ctx, color_table);
+    #endif
+    #ifdef INCLUDE_NODE_EDITOR
+        node_editor(ctx);
+    #endif
+    /* ----------------------------------------- */
+
     SDL_SetRenderDrawColor(app->renderer, 255, 0, 255, SDL_ALPHA_OPAQUE);
     SDL_RenderClear(app->renderer);
+
+    nk_sdl_render(NK_ANTI_ALIASING_ON);
+
     SDL_RenderPresent(app->renderer);
 
+    nk_input_begin(ctx);
     return SDL_APP_CONTINUE;
 }
 

+ 38 - 77
demo/sdl3_renderer/nuklear_sdl3_renderer.h

@@ -1,3 +1,6 @@
+/*
+ * Nuklear - 4.9.4 - public domain
+ */
 /*
  * ==============================================================
  *
@@ -8,25 +11,16 @@
 #ifndef NK_SDL3_RENDERER_H_
 #define NK_SDL3_RENDERER_H_
 
-#ifndef NK_SDL3_RENDERER_SDL_H
-#define NK_SDL3_RENDERER_SDL_H <SDL3/SDL.h>
-#endif
-#include NK_SDL3_RENDERER_SDL_H
-
-#define NK_SIZE_TYPE size_t
-
-#ifndef NUKLEAR_H
-#define NUKLEAR_H "nuklear.h"
-#endif
-#include NUKLEAR_H
-
 NK_API struct nk_context*   nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer);
 NK_API void                 nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
 NK_API void                 nk_sdl_font_stash_end(void);
 NK_API int                  nk_sdl_handle_event(SDL_Event *evt);
 NK_API void                 nk_sdl_render(enum nk_anti_aliasing);
 NK_API void                 nk_sdl_shutdown(void);
-NK_API void                 nk_sdl_handle_grab(void);
+
+#if SDL_MAJOR_VERSION < 3
+#error "nuklear_sdl3_renderer requires at least SDL 3.0.0"
+#endif
 
 #endif /* NK_SDL_RENDERER_H_ */
 
@@ -37,17 +31,7 @@ NK_API void                 nk_sdl_handle_grab(void);
  *
  * ===============================================================
  */
-#ifdef NK_SDL_RENDERER_IMPLEMENTATION
-
-/* Nuklear SDL3 Renderer defines some macros for Nuklear SDL use */
-#define NK_MEMCPY SDL_memcpy
-#define NK_IMPLEMENTATION
-
-#include <stddef.h>
-
-#if SDL_MAJOR_VERSION < 3
-#error "nuklear_sdl3_renderer requires at least SDL 3.0.0"
-#endif
+#ifdef NK_SDL3_RENDERER_IMPLEMENTATION
 
 struct nk_sdl_device {
     struct nk_buffer cmds;
@@ -58,17 +42,16 @@ struct nk_sdl_device {
 struct nk_sdl_vertex {
     float position[2];
     float uv[2];
-    nk_byte col[4];
+    float col[4];
 };
 
-struct nk_sdl {
+static struct nk_sdl {
     SDL_Window *win;
     SDL_Renderer *renderer;
     struct nk_sdl_device ogl;
     struct nk_context ctx;
     struct nk_font_atlas atlas;
-    Uint64 time_of_last_frame;
-} nk_sdl;
+} sdl;
 
 NK_INTERN void
 nk_sdl_device_upload_atlas(const void *image, int width, int height)
@@ -93,7 +76,7 @@ nk_sdl_render(enum nk_anti_aliasing AA)
 
     {
         SDL_Rect saved_clip;
-        SDL_bool clipping_enabled;
+        bool clipping_enabled;
         int vs = sizeof(struct nk_sdl_vertex);
         size_t vp = offsetof(struct nk_sdl_vertex, position);
         size_t vt = offsetof(struct nk_sdl_vertex, uv);
@@ -107,16 +90,11 @@ nk_sdl_render(enum nk_anti_aliasing AA)
         /* fill converting configuration */
         struct nk_convert_config config;
         static const struct nk_draw_vertex_layout_element vertex_layout[] = {
-            {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, position)},
-            {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, uv)},
-            {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sdl_vertex, col)},
+            {NK_VERTEX_POSITION,    NK_FORMAT_FLOAT,                NK_OFFSETOF(struct nk_sdl_vertex, position)},
+            {NK_VERTEX_TEXCOORD,    NK_FORMAT_FLOAT,                NK_OFFSETOF(struct nk_sdl_vertex, uv)},
+            {NK_VERTEX_COLOR,       NK_FORMAT_R32G32B32A32_FLOAT,   NK_OFFSETOF(struct nk_sdl_vertex, col)},
             {NK_VERTEX_LAYOUT_END}
         };
-
-        Uint64 now = SDL_GetTicks64();
-        sdl.ctx.delta_time_seconds = (float)(now - sdl.time_of_last_frame) / 1000;
-        sdl.time_of_last_frame = now;
-
         NK_MEMSET(&config, 0, sizeof(config));
         config.vertex_layout = vertex_layout;
         config.vertex_size = sizeof(struct nk_sdl_vertex);
@@ -137,8 +115,8 @@ nk_sdl_render(enum nk_anti_aliasing AA)
         /* iterate over and execute each draw command */
         offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
 
-        clipping_enabled = SDL_RenderIsClipEnabled(sdl.renderer);
-        SDL_RenderGetClipRect(sdl.renderer, &saved_clip);
+        clipping_enabled = SDL_RenderClipEnabled(sdl.renderer);
+        SDL_GetRenderClipRect(sdl.renderer, &saved_clip);
 
         nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds)
         {
@@ -150,7 +128,7 @@ nk_sdl_render(enum nk_anti_aliasing AA)
                 r.y = cmd->clip_rect.y;
                 r.w = cmd->clip_rect.w;
                 r.h = cmd->clip_rect.h;
-                SDL_RenderSetClipRect(sdl.renderer, &r);
+                SDL_SetRenderClipRect(sdl.renderer, &r);
             }
 
             {
@@ -159,7 +137,7 @@ nk_sdl_render(enum nk_anti_aliasing AA)
                 SDL_RenderGeometryRaw(sdl.renderer,
                         (SDL_Texture *)cmd->texture.ptr,
                         (const float*)((const nk_byte*)vertices + vp), vs,
-                        (const SDL_Color*)((const nk_byte*)vertices + vc), vs,
+                        (const SDL_FColor*)((const nk_byte*)vertices + vc), vs,
                         (const float*)((const nk_byte*)vertices + vt), vs,
                         (vbuf.needed / vs),
                         (void *) offset, cmd->elem_count, 2);
@@ -168,9 +146,9 @@ nk_sdl_render(enum nk_anti_aliasing AA)
             }
         }
 
-        SDL_RenderSetClipRect(sdl.renderer, &saved_clip);
+        SDL_SetRenderClipRect(sdl.renderer, &saved_clip);
         if (!clipping_enabled) {
-            SDL_RenderSetClipRect(sdl.renderer, NULL);
+            SDL_SetRenderClipRect(sdl.renderer, NULL);
         }
 
         nk_clear(&sdl.ctx);
@@ -194,12 +172,12 @@ nk_sdl_clipboard_copy(nk_handle usr, const char *text, int len)
     char *str = 0;
     (void)usr;
     if (!len) return;
-    str = (char*)SDL_malloc((size_t)len+1);
+    str = (char*)malloc((size_t)len+1);
     if (!str) return;
-    SDL_memcpy(str, text, (size_t)len);
+    memcpy(str, text, (size_t)len);
     str[len] = '\0';
     SDL_SetClipboardText(str);
-    SDL_free(str);
+    free(str);
 }
 
 NK_API struct nk_context*
@@ -207,7 +185,6 @@ nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer)
 {
     sdl.win = win;
     sdl.renderer = renderer;
-    sdl.time_of_last_frame = SDL_GetTicks64();
     nk_init_default(&sdl.ctx, 0);
     sdl.ctx.clip.copy = nk_sdl_clipboard_copy;
     sdl.ctx.clip.paste = nk_sdl_clipboard_paste;
@@ -235,22 +212,6 @@ nk_sdl_font_stash_end(void)
         nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
 }
 
-NK_API void
-nk_sdl_handle_grab(void)
-{
-    struct nk_context *ctx = &sdl.ctx;
-    if (ctx->input.mouse.grab) {
-        SDL_SetRelativeMouseMode(SDL_TRUE);
-    } else if (ctx->input.mouse.ungrab) {
-        /* better support for older SDL by setting mode first; causes an extra mouse motion event */
-        SDL_SetRelativeMouseMode(SDL_FALSE);
-        SDL_WarpMouseInWindow(sdl.win, (int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y);
-    } else if (ctx->input.mouse.grabbed) {
-        ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
-        ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
-    }
-}
-
 NK_API int
 nk_sdl_handle_event(SDL_Event *evt)
 {
@@ -258,12 +219,12 @@ nk_sdl_handle_event(SDL_Event *evt)
 
     switch(evt->type)
     {
-        case SDL_EVENT_KEY_UP:
+        case SDL_EVENT_KEY_UP: /* KEYUP & KEYDOWN share same routine */
         case SDL_EVENT_KEY_DOWN:
             {
-                int down = evt->type == SDL_KEYDOWN;
-                const Uint8* state = SDL_GetKeyboardState(0);
-                switch(evt->key.keysym.sym)
+                int down = evt->type == SDL_EVENT_KEY_DOWN;
+                const bool* state = SDL_GetKeyboardState(0);
+                switch(evt->key.key)
                 {
                     case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
                     case SDLK_LSHIFT:    nk_input_key(ctx, NK_KEY_SHIFT, down); break;
@@ -297,13 +258,13 @@ nk_sdl_handle_event(SDL_Event *evt)
                         else nk_input_key(ctx, NK_KEY_RIGHT, down);
                         break;
                 }
+                return 1;
             }
-            return 1;
 
-        case SDL_EVENT_MOUSE_BUTTON_UP:
+        case SDL_EVENT_MOUSE_BUTTON_UP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
         case SDL_EVENT_MOUSE_BUTTON_DOWN:
             {
-                int down = evt->type == SDL_MOUSEBUTTONDOWN;
+                int down = evt->button.down;
                 const int x = evt->button.x, y = evt->button.y;
                 switch(evt->button.button)
                 {
@@ -328,7 +289,7 @@ nk_sdl_handle_event(SDL_Event *evt)
         case SDL_EVENT_TEXT_INPUT:
             {
                 nk_glyph glyph;
-                SDL_memcpy(glyph, evt->text.text, NK_UTF_SIZE);
+                memcpy(glyph, evt->text.text, NK_UTF_SIZE);
                 nk_input_glyph(ctx, glyph);
             }
             return 1;
@@ -341,15 +302,15 @@ nk_sdl_handle_event(SDL_Event *evt)
 }
 
 NK_API
-void nk_sdl_shutdown(struct nk_sdl* sdl)
+void nk_sdl_shutdown(void)
 {
-    struct nk_sdl_device *dev = &sdl->ogl;
-    nk_font_atlas_clear(&sdl->atlas);
-    SDL_free(&sdl->ctx);
+    struct nk_sdl_device *dev = &sdl.ogl;
+    nk_font_atlas_clear(&sdl.atlas);
+    nk_free(&sdl.ctx);
     SDL_DestroyTexture(dev->font_tex);
     /* glDeleteTextures(1, &dev->font_tex); */
     nk_buffer_free(&dev->cmds);
-    NK_MEMSET(sdl, 0, sizeof(sdl));
+    memset(&sdl, 0, sizeof(sdl));
 }
 
-#endif /* NK_SDL_RENDERER_IMPLEMENTATION */
+#endif /* NK_SDL3_RENDERER_IMPLEMENTATION */