Scale the screen based on DPI

This commit is contained in:
Simon Gellis 2024-10-31 21:11:13 -04:00
parent c45cd14236
commit 3cb5606382
3 changed files with 45 additions and 28 deletions

8
ui.c
View File

@ -134,8 +134,8 @@ int uiRun(UIContext *ui) {
if (windowGuiBegin(&ui->win, "Shrooms VB")) { if (windowGuiBegin(&ui->win, "Shrooms VB")) {
windowMenubarBegin(&ui->win, MENU_ITEMS); windowMenubarBegin(&ui->win, MENU_ITEMS);
if (nk_menu_begin_label(ctx, "File", NK_TEXT_ALIGN_CENTERED, nk_vec2(120, windowGetScreenHeight(&ui->win)))) { if (nk_menu_begin_label(ctx, "File", NK_TEXT_ALIGN_CENTERED, nk_vec2(windowScaleX(&ui->win, 100), windowGetScreenHeight(&ui->win)))) {
nk_layout_row_dynamic(ctx, MENU_HEIGHT + 2, 1); nk_layout_row_dynamic(ctx, windowGetMenuHeight(&ui->win), 1);
if (nk_menu_item_label(ctx, "Open ROM", NK_TEXT_ALIGN_LEFT)) { if (nk_menu_item_label(ctx, "Open ROM", NK_TEXT_ALIGN_LEFT)) {
char *file = tinyfd_openFileDialog("Pick a ROM", NULL, 1, ROM_EXTENSIONS, "Virtual Boy ROM files", false); char *file = tinyfd_openFileDialog("Pick a ROM", NULL, 1, ROM_EXTENSIONS, "Virtual Boy ROM files", false);
if (file) { if (file) {
@ -152,9 +152,9 @@ int uiRun(UIContext *ui) {
nk_menu_end(ctx); nk_menu_end(ctx);
} }
if (nk_menu_begin_label(ctx, "Emulation", NK_TEXT_ALIGN_CENTERED, nk_vec2(120, windowGetScreenHeight(&ui->win)))) { if (nk_menu_begin_label(ctx, "Emulation", NK_TEXT_ALIGN_CENTERED, nk_vec2(windowScaleX(&ui->win, 100), windowGetScreenHeight(&ui->win)))) {
const char *label = status == status_paused ? "Resume" : "Pause"; const char *label = status == status_paused ? "Resume" : "Pause";
nk_layout_row_dynamic(ctx, MENU_HEIGHT + 2, 1); nk_layout_row_dynamic(ctx, windowGetMenuHeight(&ui->win), 1);
if (nk_menu_item_label(ctx, label, NK_TEXT_ALIGN_LEFT)) { if (nk_menu_item_label(ctx, label, NK_TEXT_ALIGN_LEFT)) {
if (status == status_paused) if (status == status_paused)
status = status_running; status = status_running;

View File

@ -1,12 +1,10 @@
#include "nuklear.h" #include "nuklear.h"
#include "window.h" #include "window.h"
#define MENU_HEIGHT 20
#define SCREEN_WIDTH 384 #define SCREEN_WIDTH 384
#define SCREEN_HEIGHT 224 #define SCREEN_HEIGHT 224
#define WINDOW_WIDTH SCREEN_WIDTH
#define WINDOW_HEIGHT (SCREEN_HEIGHT + MENU_HEIGHT)
static void setColorTable(struct nk_color *table) { static void setColorTable(struct nk_color *table) {
table[NK_COLOR_TEXT] = nk_rgb(80, 80, 80); table[NK_COLOR_TEXT] = nk_rgb(80, 80, 80);
table[NK_COLOR_WINDOW] = nk_rgb(255, 255, 255); table[NK_COLOR_WINDOW] = nk_rgb(255, 255, 255);
@ -42,7 +40,7 @@ static void setColorTable(struct nk_color *table) {
table[NK_COLOR_KNOB_CURSOR_ACTIVE] = nk_rgb(150, 150, 150); table[NK_COLOR_KNOB_CURSOR_ACTIVE] = nk_rgb(150, 150, 150);
} }
static void applyStyles(struct nk_context *ctx) { static void applyStyles(struct nk_context *ctx, float scaleX, float scaleY) {
struct nk_color table[NK_COLOR_COUNT]; struct nk_color table[NK_COLOR_COUNT];
setColorTable(table); setColorTable(table);
nk_style_from_table(ctx, table); nk_style_from_table(ctx, table);
@ -53,15 +51,14 @@ static void applyStyles(struct nk_context *ctx) {
ctx->style.menu_button.hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 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.menu_button.active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
ctx->style.contextual_button.padding = nk_vec2(20, 4); ctx->style.menu_button.padding = nk_vec2(2 * scaleX, 4 * scaleY);
ctx->style.contextual_button.padding = nk_vec2(20 * scaleX, 4 * scaleY);
} }
int windowInit(WindowContext *win, const char *title) { int windowInit(WindowContext *win, const char *title) {
float fontScale;
win->window = SDL_CreateWindow(title, win->window = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); SCREEN_WIDTH, SCREEN_HEIGHT + MENU_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (!win->window) { if (!win->window) {
fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); fprintf(stderr, "Error creating window: %s\n", SDL_GetError());
return -1; return -1;
@ -88,21 +85,28 @@ int windowInit(WindowContext *win, const char *title) {
SDL_SetTextureColorMod(win->rightEye, 0, 0xc6, 0xf0); SDL_SetTextureColorMod(win->rightEye, 0, 0xc6, 0xf0);
SDL_SetTextureBlendMode(win->rightEye, SDL_BLENDMODE_ADD); SDL_SetTextureBlendMode(win->rightEye, SDL_BLENDMODE_ADD);
/* scale the renderer output for High-DPI displays */ /* scale the window and renderer for High-DPI displays */
{ {
int renderW, renderH; int renderW, renderH;
int windowW, windowH; int windowW, windowH;
float scaleX, scaleY; float scaleX, scaleY;
float hdpi, vdpi;
SDL_GetRendererOutputSize(win->renderer, &renderW, &renderH); SDL_GetRendererOutputSize(win->renderer, &renderW, &renderH);
SDL_GetWindowSize(win->window, &windowW, &windowH); SDL_GetWindowSize(win->window, &windowW, &windowH);
SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(win->window), NULL, &hdpi, &vdpi);
scaleX = (float)(renderW) / (float)(windowW); scaleX = (float)(renderW) / (float)(windowW);
scaleY = (float)(renderH) / (float)(windowH); scaleY = (float)(renderH) / (float)(windowH);
SDL_RenderSetScale(win->renderer, scaleX, scaleY);
fontScale = scaleY; 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);
} }
win->nk = nk_sdl_init(win->window, win->renderer); win->nk = nk_sdl_init(win->window, win->renderer);
applyStyles(win->nk); applyStyles(win->nk, win->screenScaleX, win->screenScaleY);
/* tell nuklear the mouse moved somewhere so it doesn't think we're hovering in the top left */ /* tell nuklear the mouse moved somewhere so it doesn't think we're hovering in the top left */
nk_input_motion(win->nk, 1024, 1024); nk_input_motion(win->nk, 1024, 1024);
@ -111,10 +115,9 @@ int windowInit(WindowContext *win, const char *title) {
struct nk_font_config config = nk_font_config(0); struct nk_font_config config = nk_font_config(0);
nk_sdl_font_stash_begin(&atlas); nk_sdl_font_stash_begin(&atlas);
win->font = nk_font_atlas_add_default(atlas, 13 * fontScale, &config); win->font = nk_font_atlas_add_default(atlas, 11 * win->screenScaleY, &config);
nk_sdl_font_stash_end(); nk_sdl_font_stash_end();
win->font->handle.height /= fontScale;
nk_style_set_font(win->nk, &win->font->handle); nk_style_set_font(win->nk, &win->font->handle);
} }
@ -166,17 +169,28 @@ void windowUpdate(WindowContext *win, const uint8_t *left, const uint8_t *right)
updateEye(win->rightEye, right); updateEye(win->rightEye, right);
} }
int windowScaleX(WindowContext *win, int x) {
return x * win->screenScaleX;
}
int windowScaleY(WindowContext *win, int y) {
return y * win->screenScaleY;
}
int windowGetMenuHeight(WindowContext *win) {
return (MENU_HEIGHT + 2) * win->screenScaleY;
}
int windowGetScreenHeight(WindowContext *win) { int windowGetScreenHeight(WindowContext *win) {
(void) win; return SCREEN_HEIGHT * win->screenScaleY;
return SCREEN_HEIGHT;
} }
void windowDisplayBegin(WindowContext *win) { void windowDisplayBegin(WindowContext *win) {
SDL_Rect dst; SDL_Rect dst;
dst.x = 0; dst.x = 0;
dst.y = MENU_HEIGHT; dst.y = MENU_HEIGHT * win->screenScaleY;
dst.w = SCREEN_WIDTH; dst.w = SCREEN_WIDTH * win->screenScaleX;
dst.h = SCREEN_HEIGHT; dst.h = SCREEN_HEIGHT * win->screenScaleY;
SDL_RenderClear(win->renderer); SDL_RenderClear(win->renderer);
SDL_RenderCopy(win->renderer, win->leftEye, NULL, &dst); SDL_RenderCopy(win->renderer, win->leftEye, NULL, &dst);
@ -189,7 +203,7 @@ void windowDisplayEnd(WindowContext *win) {
} }
bool windowGuiBegin(WindowContext *win, const char *title) { bool windowGuiBegin(WindowContext *win, const char *title) {
return nk_begin(win->nk, title, nk_rect(0, 0, SCREEN_WIDTH, MENU_HEIGHT), NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND); 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);
} }
void windowGuiEnd(WindowContext *win) { void windowGuiEnd(WindowContext *win) {
@ -199,14 +213,14 @@ void windowGuiEnd(WindowContext *win) {
void windowMenubarBegin(WindowContext *win, const char **items) { void windowMenubarBegin(WindowContext *win, const char **items) {
const char **item; const char **item;
nk_menubar_begin(win->nk); nk_menubar_begin(win->nk);
nk_layout_row_template_begin(win->nk, MENU_HEIGHT); nk_layout_row_template_begin(win->nk, MENU_HEIGHT * win->screenScaleY);
for (item = items; *item != NULL; item++) { for (item = items; *item != NULL; item++) {
struct nk_user_font *handle; struct nk_user_font *handle;
int len; int len;
float width; float width;
handle = &win->font->handle; handle = &win->font->handle;
len = nk_strlen(*item); len = nk_strlen(*item);
width = handle->width(handle->userdata, handle->height, *item, len) + 16; width = handle->width(handle->userdata, handle->height, *item, len) + (16 * win->screenScaleX);
nk_layout_row_template_push_static(win->nk, width); nk_layout_row_template_push_static(win->nk, width);
} }
nk_layout_row_template_end(win->nk); nk_layout_row_template_end(win->nk);

View File

@ -4,10 +4,10 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "nuklear.h" #include "nuklear.h"
#define MENU_HEIGHT 20
typedef struct WindowContext { typedef struct WindowContext {
SDL_Window *window; SDL_Window *window;
int winWidth, winHeight;
float screenScaleX, screenScaleY;
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *leftEye; SDL_Texture *leftEye;
SDL_Texture *rightEye; SDL_Texture *rightEye;
@ -20,6 +20,9 @@ void windowDestroy(WindowContext *win);
void windowUpdate(WindowContext *win, const uint8_t *left, const uint8_t *right); void windowUpdate(WindowContext *win, const uint8_t *left, const uint8_t *right);
int windowScaleX(WindowContext *win, int x);
int windowScaleY(WindowContext *win, int y);
int windowGetMenuHeight(WindowContext *win);
int windowGetScreenHeight(WindowContext *win); int windowGetScreenHeight(WindowContext *win);
void windowDisplayBegin(WindowContext *win); void windowDisplayBegin(WindowContext *win);