diff --git a/ui.c b/ui.c index c3cb86e..1dbdd76 100644 --- a/ui.c +++ b/ui.c @@ -89,9 +89,10 @@ int uiLoadGame(UIContext *ui, const char *path) { return 0; } -static const char *MENU_ITEMS[3] = { +static const char *MENU_ITEMS[4] = { "File", "Emulation", + "Video", NULL }; @@ -169,6 +170,25 @@ int uiRun(UIContext *ui, bool running) { nk_menu_end(ctx); } + if (nk_menu_begin_label(ctx, "Video", NK_TEXT_ALIGN_CENTERED, nk_vec2(windowScaleX(&ui->win, 100), windowGetScreenHeight(&ui->win)))) { + float multiplier = windowGetScreenSizeMultiplier(&ui->win); + + nk_layout_row_dynamic(ctx, windowGetMenuHeight(&ui->win), 1); + if (nk_menu_item_label(ctx, multiplier == 1.0f ? "x1 *" : "x1", NK_TEXT_ALIGN_LEFT)) { + windowSetScreenSizeMultiplier(&ui->win, 1.0f); + } + if (nk_menu_item_label(ctx, multiplier == 2.0f ? "x2 *" : "x2", NK_TEXT_ALIGN_LEFT)) { + windowSetScreenSizeMultiplier(&ui->win, 2.0f); + } + if (nk_menu_item_label(ctx, multiplier == 3.0f ? "x3 *" : "x3", NK_TEXT_ALIGN_LEFT)) { + windowSetScreenSizeMultiplier(&ui->win, 3.0f); + } + if (nk_menu_item_label(ctx, multiplier == 4.0f ? "x4 *" : "x4", NK_TEXT_ALIGN_LEFT)) { + windowSetScreenSizeMultiplier(&ui->win, 4.0f); + } + nk_menu_end(ctx); + } + windowMenubarEnd(&ui->win); } windowGuiEnd(&ui->win); diff --git a/window.c b/window.c index 30684b2..19658bc 100644 --- a/window.c +++ b/window.c @@ -56,7 +56,37 @@ static void applyStyles(struct nk_context *ctx, float scaleX, float scaleY) { ctx->style.contextual_button.padding = nk_vec2(20 * scaleX, 4 * scaleY); } +/* scale the window for High-DPI displays */ +static void scaleWindow(WindowContext *win) { + int renderW, renderH; + int oldWindowX, oldWindowY; + int newWindowX, newWindowY; + int oldWindowW, oldWindowH; + int newWindowW, newWindowH; + float scaleX, scaleY; + float hdpi, vdpi; + SDL_GetRendererOutputSize(win->renderer, &renderW, &renderH); + SDL_GetWindowPosition(win->window, &oldWindowX, &oldWindowY); + SDL_GetWindowSize(win->window, &oldWindowW, &oldWindowH); + SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(win->window), NULL, &hdpi, &vdpi); + scaleX = (float)(renderW) / (float)(oldWindowW); + scaleY = (float)(renderH) / (float)(oldWindowH); + win->screenScaleX = (hdpi / 96) * scaleX; + win->screenScaleY = (vdpi / 96) * scaleY; + + newWindowW = SCREEN_WIDTH * win->screenSizeMultiplier * (hdpi / 96) / scaleX; + newWindowH = (SCREEN_HEIGHT * win->screenSizeMultiplier + MENU_HEIGHT) * (vdpi / 96) / scaleY; + newWindowX = oldWindowX - (newWindowW - oldWindowW) / 2; + newWindowY = oldWindowY - (newWindowH - oldWindowH) / 2; + if (newWindowX < 0) newWindowX = 0; + if (newWindowY < 0) newWindowY = 0; + SDL_SetWindowSize(win->window, newWindowW, newWindowH); + SDL_SetWindowPosition(win->window, newWindowX, newWindowY); +} + int windowInit(WindowContext *win, const char *title) { + win->screenSizeMultiplier = 1.0f; + win->window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT + MENU_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); @@ -86,25 +116,7 @@ int windowInit(WindowContext *win, const char *title) { SDL_SetTextureColorMod(win->rightEye, 0, 0xc6, 0xf0); SDL_SetTextureBlendMode(win->rightEye, SDL_BLENDMODE_ADD); - /* scale the window and renderer for High-DPI displays */ - { - int renderW, renderH; - int windowW, windowH; - float scaleX, scaleY; - float hdpi, vdpi; - SDL_GetRendererOutputSize(win->renderer, &renderW, &renderH); - SDL_GetWindowSize(win->window, &windowW, &windowH); - SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(win->window), NULL, &hdpi, &vdpi); - scaleX = (float)(renderW) / (float)(windowW); - scaleY = (float)(renderH) / (float)(windowH); - - win->winWidth = SCREEN_WIDTH * (hdpi / 96) / scaleX; - win->winHeight = (SCREEN_HEIGHT + MENU_HEIGHT) * (vdpi / 96) / scaleY; - win->screenScaleX = (hdpi / 96) * scaleX; - win->screenScaleY = (vdpi / 96) * scaleY; - - SDL_SetWindowSize(win->window, win->winWidth, win->winHeight); - } + scaleWindow(win); win->nk = nk_sdl_init(win->window, win->renderer); applyStyles(win->nk, win->screenScaleX, win->screenScaleY); @@ -143,6 +155,16 @@ void windowDestroy(WindowContext *win) { SDL_DestroyWindow(win->window); } +float windowGetScreenSizeMultiplier(WindowContext *win) { + return win->screenSizeMultiplier; +} + +void windowSetScreenSizeMultiplier(WindowContext *win, float multiplier) { + win->screenSizeMultiplier = multiplier; + scaleWindow(win); + applyStyles(win->nk, win->screenScaleX, win->screenScaleY); +} + static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { int x, y, i; uint8_t color; @@ -186,15 +208,15 @@ int windowGetMenuHeight(WindowContext *win) { } int windowGetScreenHeight(WindowContext *win) { - return SCREEN_HEIGHT * win->screenScaleY; + return SCREEN_HEIGHT * win->screenSizeMultiplier * win->screenScaleY; } void windowDisplayBegin(WindowContext *win) { SDL_Rect dst; dst.x = 0; dst.y = MENU_HEIGHT * win->screenScaleY; - dst.w = SCREEN_WIDTH * win->screenScaleX; - dst.h = SCREEN_HEIGHT * win->screenScaleY; + dst.w = SCREEN_WIDTH * win->screenSizeMultiplier * win->screenScaleX; + dst.h = SCREEN_HEIGHT * win->screenSizeMultiplier * win->screenScaleY; SDL_RenderClear(win->renderer); SDL_RenderCopy(win->renderer, win->leftEye, NULL, &dst); @@ -207,7 +229,9 @@ void windowDisplayEnd(WindowContext *win) { } bool windowGuiBegin(WindowContext *win, const char *title) { - return nk_begin(win->nk, title, nk_rect(0, 0, SCREEN_WIDTH * win->screenScaleX, MENU_HEIGHT * win->screenScaleY), NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND); + return nk_begin(win->nk, title, + nk_rect(0, 0, SCREEN_WIDTH * win->screenSizeMultiplier * win->screenScaleX, MENU_HEIGHT * win->screenScaleY), + NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND); } void windowGuiEnd(WindowContext *win) { diff --git a/window.h b/window.h index 394c816..4775638 100644 --- a/window.h +++ b/window.h @@ -6,7 +6,7 @@ typedef struct WindowContext { SDL_Window *window; - int winWidth, winHeight; + float screenSizeMultiplier; float screenScaleX, screenScaleY; SDL_Renderer *renderer; SDL_Texture *leftEye; @@ -18,6 +18,8 @@ typedef struct WindowContext { int windowInit(WindowContext *win, const char *title); void windowDestroy(WindowContext *win); +float windowGetScreenSizeMultiplier(WindowContext *win); +void windowSetScreenSizeMultiplier(WindowContext *win, float multiplier); void windowUpdate(WindowContext *win, const uint8_t *left, const uint8_t *right); int windowScaleX(WindowContext *win, int x);