Skip to content

Commit

Permalink
Add new options to stretch or resize the window according to the game…
Browse files Browse the repository at this point in the history
…'s aspect ratio.
  • Loading branch information
Arignir committed Jan 7, 2023
1 parent c6dac95 commit e9e4aa0
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 55 deletions.
59 changes: 49 additions & 10 deletions include/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,26 @@
# define MAX_QUICKSAVES 5
# define POWER_SAVE_FRAME_DELAY 30

struct ImGuiIO;

enum texture_filter_kind {
TEXTURE_FILTER_MIN = 0,

TEXTURE_FILTER_NEAREST = 0,
TEXTURE_FILTER_LINEAR,
TEXTURE_FILTER_LINEAR = 1,

TEXTURE_FILTER_MAX = 1,
};

struct ImGuiIO;
enum aspect_ratio {
ASPECT_RATIO_MIN = 0,

ASPECT_RATIO_RESIZE = 0,
ASPECT_RATIO_BORDERS = 1,
ASPECT_RATIO_STRETCH = 2,

ASPECT_RATIO_MAX = 2,
};

enum bind_actions {
BIND_UNASSIGNED = 0,
Expand Down Expand Up @@ -125,9 +139,10 @@ struct app {
} file;

struct {
uint32_t display_size;
enum aspect_ratio aspect_ratio;
bool vsync;
bool color_correction;
uint32_t display_size;

struct {
enum texture_filter_kind kind;
Expand Down Expand Up @@ -155,23 +170,47 @@ struct app {
/* How many frames before going back to power save mode? */
uint32_t power_save_fcounter;

/* Size of the menu bar, used to re-scale the window */
ImVec2 menubar_size;
/* Temporary value used to measure the FPS. */
uint32_t ticks_last_frame;

/*
** The size of the `game` window.
** Usually the size of the window minus the menubar's height (if it is visible).
*/
struct {
int width;
int height;
} game;

/* Size of the FPS counter within the menubar. */
float menubar_fps_width;

// Temporary value used to measure the FPS.
uint32_t ticks_last_frame;
/* Size of the menu bar */
ImVec2 menubar_size;

struct {
int width;
int height;

/* Used when resizing, to know if the new window is bigger or smaller than the previous one. */
uint32_t old_area;

/* Indicates if the window needs to be resized */
bool resize;

/*
** Indicates if the user wants to resize the windows to the given ratio.
** Otherwise, `video->display_size` is taken
**/
bool resize_with_ratio;
float resize_ratio;
} win;

/* The error message to print, if any. */
struct {
char *msg;
bool active;
} error;

/* Indicates if the user wants to resize the windows to `video->display_size`. */
bool refresh_windows_size;
} ui;

struct {
Expand Down
8 changes: 8 additions & 0 deletions source/gui/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ gui_config_load(
app->video.display_size = max(1, min(app->video.display_size, 5));
}

if (mjson_get_number(data, data_len, "$.video.aspect_ratio", &d)) {
app->video.aspect_ratio = (int)d;
app->video.aspect_ratio = max(ASPECT_RATIO_MIN, min(app->video.aspect_ratio, ASPECT_RATIO_MAX));
}

if (mjson_get_bool(data, data_len, "$.video.vsync", &b)) {
app->video.vsync = b;
}
Expand All @@ -112,6 +117,7 @@ gui_config_load(

if (mjson_get_number(data, data_len, "$.video.texture_filter", &d)) {
app->video.texture_filter.kind = (int)d;
app->video.texture_filter.kind = max(TEXTURE_FILTER_MIN, min(app->video.texture_filter.kind, TEXTURE_FILTER_MAX));
app->video.texture_filter.refresh = true;
}
}
Expand Down Expand Up @@ -227,6 +233,7 @@ gui_config_save(
// Video
"video": {
"display_size": %d,
"aspect_ratio": %d,
"vsync": %B,
"color_correction": %B,
"texture_filter": %d
Expand Down Expand Up @@ -267,6 +274,7 @@ gui_config_save(
(int)app->emulation.rtc_autodetect,
(int)app->emulation.rtc_force_enabled,
(int)app->video.display_size,
(int)app->video.aspect_ratio,
(int)app->video.vsync,
(int)app->video.color_correction,
(int)app->video.texture_filter.kind,
Expand Down
36 changes: 32 additions & 4 deletions source/gui/sdl/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,38 @@ gui_sdl_handle_inputs(
break;
};
case SDL_WINDOWEVENT: {
if (event.window.event == SDL_WINDOWEVENT_CLOSE
&& event.window.windowID == SDL_GetWindowID(app->sdl.window)
) {
app->run = false;
/* Keep only events related to our current window. */
if (event.window.windowID != SDL_GetWindowID(app->sdl.window)) {
break;
}

switch (event.window.event) {
case SDL_WINDOWEVENT_CLOSE: {
app->run = false;
break;
};
case SDL_WINDOWEVENT_SIZE_CHANGED: {
app->ui.win.old_area = app->ui.win.width * app->ui.win.height;
app->ui.win.width = event.window.data1;
app->ui.win.height = event.window.data2;

app->ui.game.width = app->ui.win.width;
app->ui.game.height = app->ui.win.height - app->ui.menubar_size.y;
break;
};
case SDL_WINDOWEVENT_RESIZED: {
if (app->video.aspect_ratio == ASPECT_RATIO_RESIZE) {
app->ui.win.resize = true;
app->ui.win.resize_with_ratio = true;

if (app->ui.win.width * app->ui.win.height >= app->ui.win.old_area) { // The window was made bigger
app->ui.win.resize_ratio = max(app->ui.game.width / (float)GBA_SCREEN_WIDTH, app->ui.game.height / (float)GBA_SCREEN_HEIGHT);
} else {
app->ui.win.resize_ratio = min(app->ui.game.width / (float)GBA_SCREEN_WIDTH, app->ui.game.height / (float)GBA_SCREEN_HEIGHT);
}
}
break;
};
}
break;
};
Expand Down
61 changes: 30 additions & 31 deletions source/gui/windows/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,39 @@ void
gui_win_game(
struct app *app
) {
float game_scale;
float rel_x;
float rel_y;
int width;
int height;

/* Resize the window to keep the correct aspect ratio */
SDL_GetWindowSize(app->sdl.window, &width, &height);
height = max(0, height - app->ui.menubar_size.y);
game_scale = min(width / (float)GBA_SCREEN_WIDTH, height / (float)GBA_SCREEN_HEIGHT);
rel_x = (width - (GBA_SCREEN_WIDTH * game_scale)) * 0.5f;
rel_y = (height - (GBA_SCREEN_HEIGHT * game_scale)) * 0.5f;
GLint last_texture;
float game_pos_x;
float game_pos_y;
float game_size_x;
float game_size_y;

/* Resize the game to keep the correct aspect ratio */
switch (app->video.aspect_ratio) {
case ASPECT_RATIO_RESIZE:
case ASPECT_RATIO_BORDERS: {
float game_scale;

game_scale = min(app->ui.game.width / (float)GBA_SCREEN_WIDTH, app->ui.game.height / (float)GBA_SCREEN_HEIGHT);
game_pos_x = (app->ui.game.width - (GBA_SCREEN_WIDTH * game_scale)) * 0.5f;
game_pos_y = (app->ui.game.height - (GBA_SCREEN_HEIGHT * game_scale)) * 0.5f;
game_size_x = GBA_SCREEN_WIDTH * game_scale;
game_size_y = GBA_SCREEN_HEIGHT * game_scale;
break;
};
case ASPECT_RATIO_STRETCH: {
game_pos_x = 0;
game_pos_y = 0;
game_size_x = app->ui.game.width;
game_size_y = app->ui.game.height;
break;
};
}

igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, (ImVec2){.x = 0, .y = 0});
igPushStyleVarFloat(ImGuiStyleVar_WindowBorderSize, 0);

igSetNextWindowPos(
(ImVec2){
.x = rel_x,
.y = (float)app->ui.menubar_size.y + rel_y,
},
ImGuiCond_Always,
(ImVec2){.x = 0, .y = 0}
);

igSetNextWindowSize(
(ImVec2){
.x = GBA_SCREEN_WIDTH * game_scale,
.y = GBA_SCREEN_HEIGHT * game_scale
},
ImGuiCond_Always
);
igSetNextWindowPos((ImVec2){.x = game_pos_x, .y = (float)app->ui.menubar_size.y + game_pos_y}, ImGuiCond_Always, (ImVec2){.x = 0, .y = 0});
igSetNextWindowSize((ImVec2){.x = game_size_x, .y = game_size_y}, ImGuiCond_Always);

igBegin(
"Game",
Expand All @@ -60,9 +61,7 @@ gui_win_game(
ImGuiWindowFlags_NoBackground
);

GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);

glBindTexture(GL_TEXTURE_2D, app->sdl.game_texture);

if (app->video.texture_filter.refresh) {
Expand Down Expand Up @@ -91,7 +90,7 @@ gui_win_game(

igImage(
(void *)(uintptr_t)app->sdl.game_texture,
(ImVec2){.x = GBA_SCREEN_WIDTH * game_scale, .y = GBA_SCREEN_HEIGHT * game_scale},
(ImVec2){.x = game_size_x, .y = game_size_y},
(ImVec2){.x = 0, .y = 0},
(ImVec2){.x = 1, .y = 1},
(ImVec4){.x = 1, .y = 1, .z = 1, .w = 1},
Expand Down
40 changes: 38 additions & 2 deletions source/gui/windows/menubar.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ gui_win_menubar_video(
int width;
int height;

char const *display_sizes[] = {
static char const * const display_sizes[] = {
"x1",
"x2",
"x3",
Expand All @@ -288,13 +288,49 @@ gui_win_menubar_video(
true
)) {
app->video.display_size = x;
app->ui.refresh_windows_size = true;
app->ui.win.resize = true;
app->ui.win.resize_with_ratio = false;
}
}

igEndMenu();
}

/* Aspect Ratio */
if (igBeginMenu("Aspect Ratio", true)) {
if (igMenuItemBool(
"Auto resize",
NULL,
app->video.aspect_ratio == ASPECT_RATIO_RESIZE,
true
)) {
app->video.aspect_ratio = ASPECT_RATIO_RESIZE;
app->ui.win.resize = true;
app->ui.win.resize_with_ratio = true;
app->ui.win.resize_ratio = min(app->ui.game.width / (float)GBA_SCREEN_WIDTH, app->ui.game.height / (float)GBA_SCREEN_HEIGHT);
}

if (igMenuItemBool(
"Black borders",
NULL,
app->video.aspect_ratio == ASPECT_RATIO_BORDERS,
true
)) {
app->video.aspect_ratio = ASPECT_RATIO_BORDERS;
}

if (igMenuItemBool(
"Stretch",
NULL,
app->video.aspect_ratio == ASPECT_RATIO_STRETCH,
true
)) {
app->video.aspect_ratio = ASPECT_RATIO_STRETCH;
}

igEndMenu();
}

igSeparator();

/* Texture Filter */
Expand Down
31 changes: 23 additions & 8 deletions source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,13 @@ main(
app.video.color_correction = true;
app.video.vsync = false;
app.video.display_size = 3;
app.video.aspect_ratio = ASPECT_RATIO_RESIZE;
app.audio.mute = false;
app.audio.level = 1.0f;
app.video.texture_filter.kind = TEXTURE_FILTER_NEAREST;
app.video.texture_filter.refresh = true;
app.ui.refresh_windows_size = true;
app.ui.win.resize = true;
app.ui.win.resize_ratio = 3;
gui_sdl_setup_default_binds(&app);

gui_config_load(&app);
Expand Down Expand Up @@ -350,13 +352,26 @@ main(
}
}

if (app.ui.refresh_windows_size) {
SDL_SetWindowSize(
app.sdl.window,
GBA_SCREEN_WIDTH * app.video.display_size * app.ui.scale,
app.ui.menubar_size.y + GBA_SCREEN_HEIGHT * app.video.display_size * app.ui.scale
);
app.ui.refresh_windows_size = false;
/* The window needs to be resized */
if (app.ui.win.resize) {
uint32_t new_width;
uint32_t new_height;

/*
** Do we wanna resize it to the aspect ratio given in `app.ui.win.resize_ratio`?
** Otherwise, use `app.video.display_size`.
*/
if (app.ui.win.resize_with_ratio) {
new_width = GBA_SCREEN_WIDTH * app.ui.win.resize_ratio * app.ui.scale;
new_height = app.ui.menubar_size.y + GBA_SCREEN_HEIGHT * app.ui.win.resize_ratio * app.ui.scale;
} else {
new_width = GBA_SCREEN_WIDTH * app.video.display_size * app.ui.scale;
new_height = app.ui.menubar_size.y + GBA_SCREEN_HEIGHT * app.video.display_size * app.ui.scale;
}

SDL_SetWindowSize(app.sdl.window, new_width, new_height);
app.ui.win.resize = false;
app.ui.win.resize_with_ratio = false;
}

sdl_counters[1] = SDL_GetPerformanceCounter();
Expand Down

0 comments on commit e9e4aa0

Please sign in to comment.