diff --git a/game.c b/game.c index b1aa3b9..d0d95c9 100644 --- a/game.c +++ b/game.c @@ -22,8 +22,7 @@ int onFrame(VB *sim) { state = vbGetUserData(sim); vbGetPixels(sim, leftEye, 1, 384, rightEye, 1, 384); - gfxUpdateLeftEye(state->gfx, leftEye); - gfxUpdateRightEye(state->gfx, rightEye); + gfxUpdateEyes(state->gfx, leftEye, rightEye); samples = vbGetSamples(sim, NULL, &samplePairs); audioUpdate(&state->aud, samples, samplePairs * 4); @@ -48,8 +47,7 @@ int runGame(VB *sim, GraphicsContext *gfx) { ctrlInit(&ctrl); - gfxUpdateLeftEye(gfx, LEFT_EYE_DEFAULT); - gfxUpdateRightEye(gfx, RIGHT_EYE_DEFAULT); + gfxUpdateEyes(gfx, LEFT_EYE_DEFAULT, RIGHT_EYE_DEFAULT); while (1) { clocks = MAX_STEP_CLOCKS; diff --git a/graphics.c b/graphics.c index 490c8a4..616eede 100644 --- a/graphics.c +++ b/graphics.c @@ -1,8 +1,61 @@ #include #include -#define WINDOW_WIDTH 1536 -#define WINDOW_HEIGHT 896 +#define SCREEN_WIDTH 384 +#define SCREEN_HEIGHT 224 +#define MENU_HEIGHT 20 + +#define WINDOW_WIDTH SCREEN_WIDTH +#define WINDOW_HEIGHT (SCREEN_HEIGHT + MENU_HEIGHT) + +static void setColorTable(struct nk_color *table) { + table[NK_COLOR_TEXT] = nk_rgb(80, 80, 80); + table[NK_COLOR_WINDOW] = nk_rgb(255, 255, 255); + table[NK_COLOR_HEADER] = nk_rgb(40, 40, 40); + table[NK_COLOR_BORDER] = nk_rgb(175, 175, 175); + table[NK_COLOR_BUTTON] = nk_rgb(255, 255, 255); + table[NK_COLOR_BUTTON_HOVER] = nk_rgb(215, 215, 215); + table[NK_COLOR_BUTTON_ACTIVE] = nk_rgb(175, 175, 175); + table[NK_COLOR_TOGGLE] = nk_rgb(100, 100, 100); + table[NK_COLOR_TOGGLE_HOVER] = nk_rgb(120, 120, 120); + table[NK_COLOR_TOGGLE_CURSOR] = nk_rgb(45, 45, 45); + table[NK_COLOR_SELECT] = nk_rgb(45, 45, 45); + table[NK_COLOR_SELECT_ACTIVE] = nk_rgb(35, 35, 35); + table[NK_COLOR_SLIDER] = nk_rgb(38, 38, 38); + table[NK_COLOR_SLIDER_CURSOR] = nk_rgb(100, 100, 100); + table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgb(120, 120, 120); + table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgb(150, 150, 150); + table[NK_COLOR_PROPERTY] = nk_rgb(38, 38, 38); + table[NK_COLOR_EDIT] = nk_rgb(38, 38, 38); + table[NK_COLOR_EDIT_CURSOR] = nk_rgb(175, 175, 175); + table[NK_COLOR_COMBO] = nk_rgb(45, 45, 45); + table[NK_COLOR_CHART] = nk_rgb(120, 120, 120); + table[NK_COLOR_CHART_COLOR] = nk_rgb(45, 45, 45); + table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgb(255, 0, 0); + table[NK_COLOR_SCROLLBAR] = nk_rgb(40, 40, 40); + table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgb(100, 100, 100); + table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgb(120, 120, 120); + table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgb(150, 150, 150); + table[NK_COLOR_TAB_HEADER] = nk_rgb(40, 40, 40); + table[NK_COLOR_KNOB] = nk_rgb(38, 38, 38); + table[NK_COLOR_KNOB_CURSOR] = nk_rgb(100, 100, 100); + table[NK_COLOR_KNOB_CURSOR_HOVER] = nk_rgb(120, 120, 120); + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = nk_rgb(150, 150, 150); +} + +static void applyStyles(struct nk_context *ctx) { + struct nk_color table[NK_COLOR_COUNT]; + setColorTable(table); + nk_style_from_table(ctx, table); + ctx->style.window.padding = nk_vec2(0, 0); + ctx->style.window.spacing = nk_vec2(0, 0); + ctx->style.window.menu_padding = nk_vec2(0, 0); + ctx->style.window.menu_border = 0; + + ctx->style.menu_button.hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); + ctx->style.menu_button.active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); + ctx->style.contextual_button.padding = nk_vec2(20, 4); +} static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { int x, y, i; @@ -48,25 +101,22 @@ int gfxInit(GraphicsContext *gfx) { } gfx->nk = nk_sdl_init(gfx->window, gfx->renderer); + applyStyles(gfx->nk); + /* tell nuklear the mouse moved somewhere so it doesn't think we're hovering in the top left */ + nk_input_motion(gfx->nk, 1024, 1024); { 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); + gfx->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->font->handle.height /= fontScale; + nk_style_set_font(gfx->nk, &gfx->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()); @@ -108,11 +158,9 @@ static void gfxUpdateEye(SDL_Texture *eye, const uint8_t *bytes) { SDL_UnlockTexture(eye); } -void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes) { - gfxUpdateEye(gfx->leftEye, bytes); -} -void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes) { - gfxUpdateEye(gfx->rightEye, bytes); +void gfxUpdateEyes(GraphicsContext *gfx, const uint8_t *left, const uint8_t *right) { + gfxUpdateEye(gfx->leftEye, left); + gfxUpdateEye(gfx->rightEye, right); } void gfxMenuInputBegin(GraphicsContext *gfx) { @@ -129,44 +177,61 @@ void gfxMenuInputEnd(GraphicsContext *gfx) { nk_input_end(gfx->nk); } +static void pushMenubarSpace(GraphicsContext *gfx, const char *text) { + struct nk_user_font *handle; + int len; + float width; + handle = &gfx->font->handle; + len = nk_strlen(text); + width = handle->width(handle->userdata, handle->height, text, len) + 16; + nk_layout_row_template_push_static(gfx->nk, width); +} + void gfxRender(GraphicsContext *gfx) { + SDL_Rect dst; + dst.x = 0; + dst.y = MENU_HEIGHT; + dst.w = SCREEN_WIDTH; + dst.h = SCREEN_HEIGHT; + + SDL_RenderClear(gfx->renderer); + SDL_RenderCopy(gfx->renderer, gfx->leftEye, NULL, &dst); + SDL_RenderCopy(gfx->renderer, gfx->rightEye, NULL, &dst); + /* 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); + if (nk_begin(gfx->nk, "Game", nk_rect(0, 0, SCREEN_WIDTH, MENU_HEIGHT), NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND)) { + nk_menubar_begin(gfx->nk); + nk_layout_row_template_begin(gfx->nk, 20); + pushMenubarSpace(gfx, "File"); + pushMenubarSpace(gfx, "Emulation"); + nk_layout_row_template_end(gfx->nk); + if (nk_menu_begin_label(gfx->nk, "File", NK_TEXT_ALIGN_CENTERED, nk_vec2(120, WINDOW_HEIGHT))) { + nk_layout_row_dynamic(gfx->nk, 22, 1); + if (nk_menu_item_label(gfx->nk, "Open ROM", NK_TEXT_ALIGN_LEFT)) { + printf("Open ROM\n"); + } + if (nk_menu_item_label(gfx->nk, "Quit", NK_TEXT_ALIGN_LEFT)) { + SDL_Event QuitEvent; + QuitEvent.type = SDL_QUIT; + QuitEvent.quit.timestamp = SDL_GetTicks(); + SDL_PushEvent(&QuitEvent); + } + nk_menu_end(gfx->nk); } + if (nk_menu_begin_label(gfx->nk, "Emulation", NK_TEXT_ALIGN_CENTERED, nk_vec2(120, WINDOW_HEIGHT))) { + nk_layout_row_dynamic(gfx->nk, 22, 1); + if (nk_menu_item_label(gfx->nk, "Pause", NK_TEXT_ALIGN_LEFT)) { + printf("Pause\n"); + } + if (nk_menu_item_label(gfx->nk, "Reset", NK_TEXT_ALIGN_LEFT)) { + printf("Reset\n"); + } + nk_menu_end(gfx->nk); + } + nk_menubar_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); - nk_sdl_render(NK_ANTI_ALIASING_ON); SDL_RenderPresent(gfx->renderer); diff --git a/graphics.h b/graphics.h index e4803d9..cae568b 100644 --- a/graphics.h +++ b/graphics.h @@ -10,14 +10,13 @@ typedef struct { SDL_Texture *leftEye; SDL_Texture *rightEye; struct nk_context *nk; - struct nk_colorf bg; + struct nk_font *font; } GraphicsContext; int gfxInit(GraphicsContext *gfx); void gfxDestroy(GraphicsContext *gfx); -void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes); -void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes); +void gfxUpdateEyes(GraphicsContext *gfx, const uint8_t *left, const uint8_t *right); void gfxMenuInputBegin(GraphicsContext *gfx); void gfxMenuHandleEvent(GraphicsContext *gfx, SDL_Event *event);