Set up nuklear

This commit is contained in:
Simon Gellis 2024-10-26 01:20:25 -04:00
parent 38b9369511
commit acde199b4a
10 changed files with 31427 additions and 13 deletions

View File

@ -12,4 +12,8 @@ Install the following dependencies:
Run Run
```sh ```sh
make build make build
``` ```
## Dependencies
This program uses a vendored version of [nuklear](https://github.com/Immediate-Mode-UI/Nuklear/tree/6566d9075d5fed48af014c93f87c4aed8c4bd21c) for GUIs.

30906
external/nuklear.h vendored Normal file

File diff suppressed because it is too large Load Diff

393
external/nuklear_sdl_renderer.h vendored Normal file
View File

@ -0,0 +1,393 @@
/*
* Nuklear - 4.9.4 - public domain
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_SDL_RENDERER_H_
#define NK_SDL_RENDERER_H_
#ifndef NK_SDL_RENDERER_SDL_H
#define NK_SDL_RENDERER_SDL_H <SDL.h>
#endif
#include NK_SDL_RENDERER_SDL_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_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 22)
/* Metal API does not support cliprects with negative coordinates or large
* dimensions. The issue is fixed in SDL2 with version 2.0.22 but until
* that version is released, the NK_SDL_CLAMP_CLIP_RECT flag can be used to
* ensure the cliprect is itself clipped to the viewport.
* See discussion at https://discourse.libsdl.org/t/rendergeometryraw-producing-different-results-in-metal-vs-opengl/34953
*/
#define NK_SDL_CLAMP_CLIP_RECT
#endif
#endif /* NK_SDL_RENDERER_H_ */
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_SDL_RENDERER_IMPLEMENTATION
#include <string.h>
#include <stdlib.h>
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture tex_null;
SDL_Texture *font_tex;
};
struct nk_sdl_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
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;
} sdl;
NK_INTERN void
nk_sdl_device_upload_atlas(const void *image, int width, int height)
{
struct nk_sdl_device *dev = &sdl.ogl;
SDL_Texture *g_SDLFontTexture = SDL_CreateTexture(sdl.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height);
if (g_SDLFontTexture == NULL) {
SDL_Log("error creating texture");
return;
}
SDL_UpdateTexture(g_SDLFontTexture, NULL, image, 4 * width);
SDL_SetTextureBlendMode(g_SDLFontTexture, SDL_BLENDMODE_BLEND);
dev->font_tex = g_SDLFontTexture;
}
NK_API void
nk_sdl_render(enum nk_anti_aliasing AA)
{
/* setup global state */
struct nk_sdl_device *dev = &sdl.ogl;
{
SDL_Rect saved_clip;
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_Rect viewport;
#endif
SDL_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);
size_t vc = offsetof(struct nk_sdl_vertex, col);
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
struct nk_buffer vbuf, ebuf;
/* 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_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);
config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config);
/* 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);
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_RenderGetViewport(sdl.renderer, &viewport);
#endif
nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
{
SDL_Rect r;
r.x = cmd->clip_rect.x;
r.y = cmd->clip_rect.y;
r.w = cmd->clip_rect.w;
r.h = cmd->clip_rect.h;
#ifdef NK_SDL_CLAMP_CLIP_RECT
if (r.x < 0) {
r.w += r.x;
r.x = 0;
}
if (r.y < 0) {
r.h += r.y;
r.y = 0;
}
if (r.h > viewport.h) {
r.h = viewport.h;
}
if (r.w > viewport.w) {
r.w = viewport.w;
}
#endif
SDL_RenderSetClipRect(sdl.renderer, &r);
}
{
const void *vertices = nk_buffer_memory_const(&vbuf);
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 float*)((const nk_byte*)vertices + vt), vs,
(vbuf.needed / vs),
(void *) offset, cmd->elem_count, 2);
offset += cmd->elem_count;
}
}
SDL_RenderSetClipRect(sdl.renderer, &saved_clip);
if (!clipping_enabled) {
SDL_RenderSetClipRect(sdl.renderer, NULL);
}
nk_clear(&sdl.ctx);
nk_buffer_clear(&dev->cmds);
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
}
static void
nk_sdl_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = SDL_GetClipboardText();
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
static void
nk_sdl_clipboard_copy(nk_handle usr, const char *text, int len)
{
char *str = 0;
(void)usr;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
memcpy(str, text, (size_t)len);
str[len] = '\0';
SDL_SetClipboardText(str);
free(str);
}
NK_API struct nk_context*
nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer)
{
#ifndef NK_SDL_CLAMP_CLIP_RECT
SDL_RendererInfo info;
SDL_version runtimeVer;
/* warn for cases where NK_SDL_CLAMP_CLIP_RECT should have been set but isn't */
SDL_GetRendererInfo(renderer, &info);
SDL_GetVersion(&runtimeVer);
if (strncmp("metal", info.name, 5) == 0 &&
SDL_VERSIONNUM(runtimeVer.major, runtimeVer.minor, runtimeVer.patch) < SDL_VERSIONNUM(2, 0, 22))
{
SDL_LogWarn(
SDL_LOG_CATEGORY_APPLICATION,
"renderer is using Metal API but runtime SDL version %d.%d.%d is older than compiled version %d.%d.%d, "
"which may cause issues with rendering",
runtimeVer.major, runtimeVer.minor, runtimeVer.patch,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL
);
}
#endif
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;
sdl.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&sdl.ogl.cmds);
return &sdl.ctx;
}
NK_API void
nk_sdl_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&sdl.atlas);
nk_font_atlas_begin(&sdl.atlas);
*atlas = &sdl.atlas;
}
NK_API void
nk_sdl_font_stash_end(void)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sdl_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sdl.atlas, nk_handle_ptr(sdl.ogl.font_tex), &sdl.ogl.tex_null);
if (sdl.atlas.default_font)
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)
{
struct nk_context *ctx = &sdl.ctx;
switch(evt->type)
{
case SDL_KEYUP: /* KEYUP & KEYDOWN share same routine */
case SDL_KEYDOWN:
{
int down = evt->type == SDL_KEYDOWN;
const Uint8* state = SDL_GetKeyboardState(0);
switch(evt->key.keysym.sym)
{
case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
case SDLK_z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_r: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_c: nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_v: nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_x: nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_b: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
case SDLK_LEFT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
else nk_input_key(ctx, NK_KEY_LEFT, down);
break;
case SDLK_RIGHT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else nk_input_key(ctx, NK_KEY_RIGHT, down);
break;
}
}
return 1;
case SDL_MOUSEBUTTONUP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
case SDL_MOUSEBUTTONDOWN:
{
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
switch(evt->button.button)
{
case SDL_BUTTON_LEFT:
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
}
}
return 1;
case SDL_MOUSEMOTION:
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
}
else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
case SDL_TEXTINPUT:
{
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
}
return 1;
case SDL_MOUSEWHEEL:
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}
return 0;
}
NK_API
void nk_sdl_shutdown(void)
{
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);
memset(&sdl, 0, sizeof(sdl));
}
#endif /* NK_SDL_RENDERER_IMPLEMENTATION */

3
game.c
View File

@ -55,6 +55,7 @@ int runGame(VB *sim, GraphicsContext *gfx) {
clocks = MAX_STEP_CLOCKS; clocks = MAX_STEP_CLOCKS;
vbEmulate(sim, &clocks); vbEmulate(sim, &clocks);
gfxMenuInputBegin(gfx);
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) { if (event.type == SDL_QUIT) {
return 0; return 0;
@ -65,7 +66,9 @@ int runGame(VB *sim, GraphicsContext *gfx) {
if (event.type == SDL_KEYUP) { if (event.type == SDL_KEYUP) {
ctrlKeyUp(&ctrl, event.key.keysym.sym); ctrlKeyUp(&ctrl, event.key.keysym.sym);
} }
gfxMenuHandleEvent(gfx, &event);
} }
gfxMenuInputEnd(gfx);
vbSetKeys(sim, ctrlKeys(&ctrl)); vbSetKeys(sim, ctrlKeys(&ctrl));
} }
} }

View File

@ -1,5 +1,8 @@
#include <graphics.h> #include <graphics.h>
#define WINDOW_WIDTH 1536
#define WINDOW_HEIGHT 896
static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) {
int x, y, i; int x, y, i;
uint8_t color; uint8_t color;
@ -15,9 +18,11 @@ static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) {
} }
int gfxInit(GraphicsContext *gfx) { int gfxInit(GraphicsContext *gfx) {
float fontScale = 1;
gfx->window = SDL_CreateWindow("Shrooms VB", gfx->window = SDL_CreateWindow("Shrooms VB",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
1536, 896, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (!gfx->window) { if (!gfx->window) {
fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); fprintf(stderr, "Error creating window: %s\n", SDL_GetError());
return 1; return 1;
@ -29,12 +34,38 @@ int gfxInit(GraphicsContext *gfx) {
goto cleanup_window; goto cleanup_window;
} }
gfx->winSurface = SDL_GetWindowSurface(gfx->window); /* scale the renderer output for High-DPI displays */
if (!gfx->winSurface) { {
fprintf(stderr, "Error getting surface: %s\n", SDL_GetError()); int renderW, renderH;
goto cleanup_window; int windowW, windowH;
float scaleX, scaleY;
SDL_GetRendererOutputSize(gfx->renderer, &renderW, &renderH);
SDL_GetWindowSize(gfx->window, &windowW, &windowH);
scaleX = (float)(renderW) / (float)(windowW);
scaleY = (float)(renderH) / (float)(windowH);
SDL_RenderSetScale(gfx->renderer, scaleX, scaleY);
} }
gfx->nk = nk_sdl_init(gfx->window, gfx->renderer);
{
struct nk_font_atlas *atlas;
struct nk_font *font;
struct nk_font_config config = nk_font_config(0);
nk_sdl_font_stash_begin(&atlas);
font = nk_font_atlas_add_default(atlas, 13 * fontScale, &config);
nk_sdl_font_stash_end();
font->handle.height /= fontScale;
nk_style_set_font(gfx->nk, &font->handle);
}
gfx->bg.r = 0.10f;
gfx->bg.g = 0.18f;
gfx->bg.b = 0.24f;
gfx->bg.a = 1.0f;
gfx->leftEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224); gfx->leftEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224);
if (!gfx->leftEye) { if (!gfx->leftEye) {
fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError()); fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError());
@ -83,10 +114,60 @@ void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes) {
gfxUpdateEye(gfx->rightEye, bytes); gfxUpdateEye(gfx->rightEye, bytes);
} }
void gfxMenuInputBegin(GraphicsContext *gfx) {
nk_input_begin(gfx->nk);
}
void gfxMenuHandleEvent(GraphicsContext *gfx, SDL_Event *event) {
(void) gfx;
nk_sdl_handle_event(event);
}
void gfxMenuInputEnd(GraphicsContext *gfx) {
nk_sdl_handle_grab();
nk_input_end(gfx->nk);
}
void gfxRender(GraphicsContext *gfx) { void gfxRender(GraphicsContext *gfx) {
/* GUI */
if (nk_begin(gfx->nk, "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(gfx->nk, 30, 80, 1);
if (nk_button_label(gfx->nk, "button"))
fprintf(stdout, "button pressed\n");
nk_layout_row_dynamic(gfx->nk, 30, 2);
if (nk_option_label(gfx->nk, "easy", op == EASY)) op = EASY;
if (nk_option_label(gfx->nk, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(gfx->nk, 25, 1);
nk_property_int(gfx->nk, "Compression:", 0, &property, 100, 10, 1);
nk_layout_row_dynamic(gfx->nk, 20, 1);
nk_label(gfx->nk, "background:", NK_TEXT_LEFT);
nk_layout_row_dynamic(gfx->nk, 25, 1);
if (nk_combo_begin_color(gfx->nk, nk_rgb_cf(gfx->bg), nk_vec2(nk_widget_width(gfx->nk),400))) {
nk_layout_row_dynamic(gfx->nk, 120, 1);
gfx->bg = nk_color_picker(gfx->nk, gfx->bg, NK_RGBA);
nk_layout_row_dynamic(gfx->nk, 25, 1);
gfx->bg.r = nk_propertyf(gfx->nk, "#R:", 0, gfx->bg.r, 1.0f, 0.01f,0.005f);
gfx->bg.g = nk_propertyf(gfx->nk, "#G:", 0, gfx->bg.g, 1.0f, 0.01f,0.005f);
gfx->bg.b = nk_propertyf(gfx->nk, "#B:", 0, gfx->bg.b, 1.0f, 0.01f,0.005f);
gfx->bg.a = nk_propertyf(gfx->nk, "#A:", 0, gfx->bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(gfx->nk);
}
}
nk_end(gfx->nk);
SDL_SetRenderDrawColor(gfx->renderer, gfx->bg.r * 255, gfx->bg.g * 255, gfx->bg.b * 255, gfx->bg.a * 255);
SDL_RenderClear(gfx->renderer); SDL_RenderClear(gfx->renderer);
SDL_RenderCopy(gfx->renderer, gfx->leftEye, NULL, NULL);
SDL_RenderCopy(gfx->renderer, gfx->rightEye, NULL, NULL); nk_sdl_render(NK_ANTI_ALIASING_ON);
SDL_RenderPresent(gfx->renderer); SDL_RenderPresent(gfx->renderer);
} }

View File

@ -2,13 +2,15 @@
#define SHROOMS_VB_NATIVE_GRAPHICS_ #define SHROOMS_VB_NATIVE_GRAPHICS_
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <nuklear.h>
typedef struct { typedef struct {
SDL_Window *window; SDL_Window *window;
SDL_Surface *winSurface;
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *leftEye; SDL_Texture *leftEye;
SDL_Texture *rightEye; SDL_Texture *rightEye;
struct nk_context *nk;
struct nk_colorf bg;
} GraphicsContext; } GraphicsContext;
int gfxInit(GraphicsContext *gfx); int gfxInit(GraphicsContext *gfx);
@ -17,6 +19,10 @@ void gfxDestroy(GraphicsContext *gfx);
void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes); void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes);
void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes); void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes);
void gfxMenuInputBegin(GraphicsContext *gfx);
void gfxMenuHandleEvent(GraphicsContext *gfx, SDL_Event *event);
void gfxMenuInputEnd(GraphicsContext *gfx);
void gfxRender(GraphicsContext *gfx); void gfxRender(GraphicsContext *gfx);
#endif #endif

1
main.c
View File

@ -69,6 +69,7 @@ int main(int argc, char **argv) {
vbInit(sim); vbInit(sim);
vbSetCartROM(sim, rom, romSize); vbSetCartROM(sim, rom, romSize);
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
if (SDL_Init(SDL_INIT_EVERYTHING)) { if (SDL_Init(SDL_INIT_EVERYTHING)) {
fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError());
return 1; return 1;

View File

@ -28,14 +28,14 @@ output/%.o: %.c
@mkdir -p output @mkdir -p output
@$(CC) -c -o $@ $< -I . \ @$(CC) -c -o $@ $< -I . \
-I shrooms-vb-core/core $(SDL2FLAGS) \ -I shrooms-vb-core/core $(SDL2FLAGS) \
-O3 -flto -fno-strict-aliasing \ -O3 -flto=auto -fno-strict-aliasing \
-Werror -std=c90 -Wall -Wextra -Wpedantic -Werror -std=c90 -Wall -Wextra -Wpedantic
output/vb.o: shrooms-vb-core/core/vb.c output/vb.o: shrooms-vb-core/core/vb.c
@mkdir -p output @mkdir -p output
@$(CC) -c -o $@ $< -I . \ @$(CC) -c -o $@ $< -I . \
-I shrooms-vb-core/core $(SDL2FLAGS) \ -I shrooms-vb-core/core \
-O3 -flto -fno-strict-aliasing \ -O3 -flto=auto -fno-strict-aliasing \
-Werror -std=c90 -Wall -Wextra -Wpedantic -Werror -std=c90 -Wall -Wextra -Wpedantic
output/%.o: assets/%.bin output/%.o: assets/%.bin
@ -43,6 +43,6 @@ output/%.o: assets/%.bin
@$(LD) -r -b binary $(BINLINKFLAGS) -o $@ $< @$(LD) -r -b binary $(BINLINKFLAGS) -o $@ $<
shrooms-vb: $(OFILES) shrooms-vb: $(OFILES)
@$(CC) -o $@ $(OFILES) $(SDL2FLAGS) -flto @$(CC) -o $@ $(OFILES) $(SDL2FLAGS) -lm -flto=auto
build: shrooms-vb build: shrooms-vb

3
nuklear.c Normal file
View File

@ -0,0 +1,3 @@
#define NK_IMPLEMENTATION
#define NK_SDL_RENDERER_IMPLEMENTATION
#include "nuklear.h"

17
nuklear.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef SHROOMS_VB_NATIVE_NUKLEAR_
#define SHROOMS_VB_NATIVE_NUKLEAR_
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_BOOL
#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
#include "external/nuklear.h"
#define NK_SDL_RENDERER_SDL_H <SDL2/SDL.h>
#include "external/nuklear_sdl_renderer.h"
#endif