Set up nuklear
This commit is contained in:
		
							parent
							
								
									38b9369511
								
							
						
					
					
						commit
						8ce1f9bc57
					
				|  | @ -13,3 +13,7 @@ Run | |||
| ```sh | ||||
| make build | ||||
| ``` | ||||
| 
 | ||||
| ## Dependencies | ||||
| 
 | ||||
| This program uses a vendored version of [nuklear](https://github.com/Immediate-Mode-UI/Nuklear/tree/6566d9075d5fed48af014c93f87c4aed8c4bd21c) for GUIs. | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -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
								
								
								
								
							
							
						
						
									
										3
									
								
								game.c
								
								
								
								
							|  | @ -55,6 +55,7 @@ int runGame(VB *sim, GraphicsContext *gfx) { | |||
|         clocks = MAX_STEP_CLOCKS; | ||||
|         vbEmulate(sim, &clocks); | ||||
| 
 | ||||
|         gfxMenuInputBegin(gfx); | ||||
|         while (SDL_PollEvent(&event)) { | ||||
|             if (event.type == SDL_QUIT) { | ||||
|                 return 0; | ||||
|  | @ -65,7 +66,9 @@ int runGame(VB *sim, GraphicsContext *gfx) { | |||
|             if (event.type == SDL_KEYUP) { | ||||
|                 ctrlKeyUp(&ctrl, event.key.keysym.sym); | ||||
|             } | ||||
|             gfxMenuHandleEvent(gfx, &event); | ||||
|         } | ||||
|         gfxMenuInputEnd(gfx); | ||||
|         vbSetKeys(sim, ctrlKeys(&ctrl)); | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										95
									
								
								graphics.c
								
								
								
								
							
							
						
						
									
										95
									
								
								graphics.c
								
								
								
								
							|  | @ -1,5 +1,8 @@ | |||
| #include <graphics.h> | ||||
| 
 | ||||
| #define WINDOW_WIDTH 1536 | ||||
| #define WINDOW_HEIGHT 896 | ||||
| 
 | ||||
| static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { | ||||
|     int x, y, i; | ||||
|     uint8_t color; | ||||
|  | @ -15,9 +18,11 @@ static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { | |||
| } | ||||
| 
 | ||||
| int gfxInit(GraphicsContext *gfx) { | ||||
|     float fontScale = 1; | ||||
| 
 | ||||
|     gfx->window = SDL_CreateWindow("Shrooms VB", | ||||
|         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) { | ||||
|         fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); | ||||
|         return 1; | ||||
|  | @ -29,12 +34,38 @@ int gfxInit(GraphicsContext *gfx) { | |||
|         goto cleanup_window; | ||||
|     } | ||||
| 
 | ||||
|     gfx->winSurface = SDL_GetWindowSurface(gfx->window); | ||||
|     if (!gfx->winSurface) { | ||||
|         fprintf(stderr, "Error getting surface: %s\n", SDL_GetError()); | ||||
|         goto cleanup_window; | ||||
|     /* scale the renderer output for High-DPI displays */ | ||||
|     { | ||||
|         int renderW, renderH; | ||||
|         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); | ||||
|     if (!gfx->leftEye) { | ||||
|         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); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     /* 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_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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,13 +2,15 @@ | |||
| #define SHROOMS_VB_NATIVE_GRAPHICS_ | ||||
| 
 | ||||
| #include <SDL2/SDL.h> | ||||
| #include <nuklear.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     SDL_Window *window; | ||||
|     SDL_Surface *winSurface; | ||||
|     SDL_Renderer *renderer; | ||||
|     SDL_Texture *leftEye; | ||||
|     SDL_Texture *rightEye; | ||||
|     struct nk_context *nk; | ||||
|     struct nk_colorf bg; | ||||
| } GraphicsContext; | ||||
| 
 | ||||
| int gfxInit(GraphicsContext *gfx); | ||||
|  | @ -17,6 +19,10 @@ void gfxDestroy(GraphicsContext *gfx); | |||
| void gfxUpdateLeftEye(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); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										3
									
								
								main.c
								
								
								
								
							
							
						
						
									
										3
									
								
								main.c
								
								
								
								
							|  | @ -1,7 +1,9 @@ | |||
| #include <cli.h> | ||||
| #include <game.h> | ||||
| #include <graphics.h> | ||||
| #include <GL/glew.h> | ||||
| #include <SDL2/SDL.h> | ||||
| #include <SDL2/SDL_opengl.h> | ||||
| #include "shrooms-vb-core/core/vb.h" | ||||
| #include <stdio.h> | ||||
| 
 | ||||
|  | @ -69,6 +71,7 @@ int main(int argc, char **argv) { | |||
|     vbInit(sim); | ||||
|     vbSetCartROM(sim, rom, romSize); | ||||
| 
 | ||||
|     SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); | ||||
|     if (SDL_Init(SDL_INIT_EVERYTHING)) { | ||||
|         fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); | ||||
|         return 1; | ||||
|  |  | |||
							
								
								
									
										8
									
								
								makefile
								
								
								
								
							
							
						
						
									
										8
									
								
								makefile
								
								
								
								
							|  | @ -28,14 +28,14 @@ output/%.o: %.c | |||
| 	@mkdir -p output | ||||
| 	@$(CC) -c -o $@ $< -I . \
 | ||||
| 		-I shrooms-vb-core/core $(SDL2FLAGS) \
 | ||||
| 		-O3 -flto -fno-strict-aliasing \
 | ||||
| 		-O3 -flto=auto -fno-strict-aliasing \
 | ||||
| 		-Werror -std=c90 -Wall -Wextra -Wpedantic | ||||
| 
 | ||||
| output/vb.o: shrooms-vb-core/core/vb.c | ||||
| 	@mkdir -p output | ||||
| 	@$(CC) -c -o $@ $< -I . \
 | ||||
| 		-I shrooms-vb-core/core $(SDL2FLAGS) \
 | ||||
| 		-O3 -flto -fno-strict-aliasing \
 | ||||
| 		-I shrooms-vb-core/core \
 | ||||
| 		-O3 -flto=auto -fno-strict-aliasing \
 | ||||
| 		-Werror -std=c90 -Wall -Wextra -Wpedantic | ||||
| 
 | ||||
| output/%.o: assets/%.bin | ||||
|  | @ -43,6 +43,6 @@ output/%.o: assets/%.bin | |||
| 	@$(LD) -r -b binary $(BINLINKFLAGS) -o $@ $< | ||||
| 
 | ||||
| shrooms-vb: $(OFILES) | ||||
| 	@$(CC) -o $@ $(OFILES) $(SDL2FLAGS) -flto | ||||
| 	@$(CC) -o $@ $(OFILES) $(SDL2FLAGS) -lm -flto=auto | ||||
| 
 | ||||
| build: shrooms-vb | ||||
|  | @ -0,0 +1,3 @@ | |||
| #define NK_IMPLEMENTATION | ||||
| #define NK_SDL_RENDERER_IMPLEMENTATION | ||||
| #include "nuklear.h" | ||||
|  | @ -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 | ||||
		Loading…
	
		Reference in New Issue