Add support for fullscreen + never grab mouse + resize window (#140)
* Implement full-screen via ALT+ENTER * Never grab mouse * Allow resizable window + fix mouse when resizing/switching to full screen * Keep aspect ratio of gl viewport when resizing window * Fix mouse when resizing the window * Fix off by one error
This commit is contained in:
parent
b3bdbb2650
commit
8a2167920e
|
|
@ -129,6 +129,7 @@ struct {
|
|||
float x;
|
||||
float y;
|
||||
} sdl_window_scale;
|
||||
int is_full_screen = 0;
|
||||
|
||||
tRenderer gl_renderer = {
|
||||
GLRenderer_Init,
|
||||
|
|
@ -141,7 +142,11 @@ tRenderer gl_renderer = {
|
|||
GLRenderer_BufferTexture,
|
||||
GLRenderer_BufferMaterial,
|
||||
GLRenderer_BufferModel,
|
||||
GLRenderer_FlushBuffers
|
||||
GLRenderer_FlushBuffers,
|
||||
GLRenderer_GetRenderSize,
|
||||
GLRenderer_GetWindowSize,
|
||||
GLRenderer_SetWindowSize,
|
||||
GLRenderer_GetViewport
|
||||
};
|
||||
|
||||
tRenderer* Window_Create(char* title, int width, int height, int pRender_width, int pRender_height) {
|
||||
|
|
@ -161,17 +166,12 @@ tRenderer* Window_Create(char* title, int width, int height, int pRender_width,
|
|||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
width, height,
|
||||
SDL_WINDOW_OPENGL);
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window");
|
||||
}
|
||||
|
||||
// Don't grab the mouse when a debugger is present
|
||||
if (!OS_IsDebuggerPresent()) {
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
}
|
||||
|
||||
sdl_window_scale.x = ((float)pRender_width) / width;
|
||||
sdl_window_scale.y = ((float)pRender_height) / height;
|
||||
|
||||
|
|
@ -192,14 +192,37 @@ tRenderer* Window_Create(char* title, int width, int height, int pRender_width,
|
|||
return &gl_renderer;
|
||||
}
|
||||
|
||||
// Checks whether the `flag_check` is the only modifier applied.
|
||||
// e.g. is_only_modifier(event.key.keysym.mod, KMOD_ALT) returns true when only the ALT key was pressed
|
||||
static int is_only_key_modifier(int modifier_flags, int flag_check) {
|
||||
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check);
|
||||
}
|
||||
|
||||
void Window_PollEvents() {
|
||||
SDL_Event event;
|
||||
int dethrace_key;
|
||||
int w_w, w_h;
|
||||
int vp_x, vp_y;
|
||||
int vp_w, vp_h;
|
||||
int r_w, r_h;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
if (event.key.keysym.sym == SDLK_RETURN) {
|
||||
if (event.key.type == SDL_KEYDOWN) {
|
||||
if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI))) {
|
||||
// Ignore keydown of RETURN when used together with some modifier
|
||||
return;
|
||||
}
|
||||
} else if (event.key.type == SDL_KEYUP) {
|
||||
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
|
||||
is_full_screen = !is_full_screen;
|
||||
SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
dethrace_key = scancodes_sdl2dethrace[event.key.keysym.scancode];
|
||||
if (dethrace_key == -1) {
|
||||
LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
|
||||
|
|
@ -213,6 +236,18 @@ void Window_PollEvents() {
|
|||
sdl_key_state[3] = sdl_key_state[2];
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
SDL_GetWindowSize(window, &w_w, &w_h);
|
||||
gl_renderer.SetWindowSize(w_w, w_h);
|
||||
gl_renderer.GetViewport(&vp_x, &vp_y, &vp_w, &vp_h);
|
||||
gl_renderer.GetRenderSize(&r_w, &r_h);
|
||||
sdl_window_scale.x = (float)r_w / vp_w;
|
||||
sdl_window_scale.y = (float)r_h / vp_h;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
LOG_PANIC("QuitGame");
|
||||
break;
|
||||
|
|
@ -251,7 +286,22 @@ int Input_IsKeyDown(unsigned char scan_code) {
|
|||
}
|
||||
|
||||
void Input_GetMousePosition(int* pX, int* pY) {
|
||||
int vp_x, vp_y, vp_w, vp_h;
|
||||
|
||||
SDL_GetMouseState(pX, pY);
|
||||
gl_renderer.GetViewport(&vp_x, &vp_y, &vp_w, &vp_h);
|
||||
if (*pX < vp_x) {
|
||||
*pX = vp_x;
|
||||
} else if (*pX >= vp_x + vp_w) {
|
||||
*pX = vp_x + vp_w - 1;
|
||||
}
|
||||
if (*pY < vp_y) {
|
||||
*pY = vp_y;
|
||||
} else if (*pY >= vp_y + vp_h) {
|
||||
*pY = vp_y + vp_h - 1;
|
||||
}
|
||||
*pX -= vp_x;
|
||||
*pY -= vp_y;
|
||||
*pX *= sdl_window_scale.x;
|
||||
*pY *= sdl_window_scale.y;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,21 +12,21 @@
|
|||
extern float gCamera_hither;
|
||||
extern float gCamera_yon;
|
||||
|
||||
GLuint screen_buffer_vao, screen_buffer_ebo;
|
||||
GLuint screen_texture, palette_texture, depth_texture;
|
||||
static GLuint screen_buffer_vao, screen_buffer_ebo;
|
||||
static GLuint screen_texture, palette_texture, depth_texture;
|
||||
|
||||
GLuint shader_program_2d;
|
||||
GLuint shader_program_3d;
|
||||
GLuint framebuffer_id, framebuffer_texture = 0;
|
||||
unsigned int rbo;
|
||||
uint8_t gl_palette[4 * 256]; // RGBA
|
||||
uint8_t* screen_buffer_flip_pixels;
|
||||
uint16_t* depth_buffer_flip_pixels;
|
||||
static GLuint shader_program_2d;
|
||||
static GLuint shader_program_3d;
|
||||
static GLuint framebuffer_id, framebuffer_texture = 0;
|
||||
static uint8_t gl_palette[4 * 256]; // RGBA
|
||||
static uint8_t* screen_buffer_flip_pixels;
|
||||
static uint16_t* depth_buffer_flip_pixels;
|
||||
|
||||
int window_width, window_height, render_width, render_height;
|
||||
static int window_width, window_height, render_width, render_height;
|
||||
static int vp_x, vp_y, vp_width, vp_height;
|
||||
|
||||
br_pixelmap* last_shade_table = NULL;
|
||||
int dirty_buffers = 0;
|
||||
static br_pixelmap* last_shade_table = NULL;
|
||||
static int dirty_buffers = 0;
|
||||
|
||||
struct {
|
||||
GLuint pixels, pixels_transform;
|
||||
|
|
@ -177,12 +177,29 @@ void SetupFullScreenRectGeometry() {
|
|||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GLRenderer_Init(int width, int height, int pRender_width, int pRender_height) {
|
||||
static void update_viewport() {
|
||||
const float target_aspect_ratio = (float)render_width / render_height;
|
||||
const float aspect_ratio = (float)window_width / window_height;
|
||||
|
||||
vp_width = window_width;
|
||||
vp_height = window_height;
|
||||
if (aspect_ratio != target_aspect_ratio) {
|
||||
if (aspect_ratio > target_aspect_ratio) {
|
||||
vp_width = window_height * target_aspect_ratio + .5f;
|
||||
} else {
|
||||
vp_height = window_width / target_aspect_ratio + .5f;
|
||||
}
|
||||
}
|
||||
vp_x = (window_width - vp_width) / 2;
|
||||
vp_y = (window_height - vp_height) / 2;
|
||||
}
|
||||
|
||||
void GLRenderer_Init(int width, int height, int pRender_width, int pRender_height) {
|
||||
window_width = width;
|
||||
window_height = height;
|
||||
render_width = pRender_width;
|
||||
render_height = pRender_height;
|
||||
update_viewport();
|
||||
|
||||
int maxTextureImageUnits;
|
||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
|
||||
|
|
@ -339,7 +356,7 @@ void GLRenderer_EndScene() {
|
|||
}
|
||||
|
||||
void GLRenderer_FullScreenQuad(uint8_t* screen_buffer, int width, int height) {
|
||||
glViewport(0, 0, window_width, window_height);
|
||||
glViewport(vp_x, vp_y, vp_width, vp_height);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
|
@ -637,3 +654,26 @@ void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffe
|
|||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
dirty_buffers = 0;
|
||||
}
|
||||
|
||||
void GLRenderer_GetRenderSize(int* width, int* height) {
|
||||
*width = render_width;
|
||||
*height = render_height;
|
||||
}
|
||||
|
||||
void GLRenderer_GetWindowSize(int* width, int* height) {
|
||||
*width = window_width;
|
||||
*height = window_height;
|
||||
}
|
||||
|
||||
void GLRenderer_SetWindowSize(int width, int height) {
|
||||
window_width = width;
|
||||
window_height = height;
|
||||
update_viewport();
|
||||
}
|
||||
|
||||
void GLRenderer_GetViewport(int* x, int* y, int* width, int* height) {
|
||||
*x = vp_x;
|
||||
*y = vp_y;
|
||||
*width = vp_width;
|
||||
*height = vp_height;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,5 +44,9 @@ void GLRenderer_BufferMaterial(br_material* mat);
|
|||
void GLRenderer_BufferModel(br_model* model);
|
||||
void GLRenderer_ClearBuffers();
|
||||
void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer);
|
||||
void GLRenderer_GetRenderSize(int* width, int* height);
|
||||
void GLRenderer_GetWindowSize(int* width, int* height);
|
||||
void GLRenderer_SetWindowSize(int width, int height);
|
||||
void GLRenderer_GetViewport(int* x, int* y, int* width, int* height);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ void Null_BufferTexture(br_pixelmap* pm) {}
|
|||
void Null_BufferMaterial(br_material* mat) {}
|
||||
void Null_BufferModel(br_model* model) {}
|
||||
void Null_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {}
|
||||
void Null_GetRenderSize(int* width, int* height) { *width = 640; *height = 480; }
|
||||
void Null_GetWindowSize(int* width, int* height) { *width = 640; *height = 480; }
|
||||
void Null_SetWindowSize(int width, int height) {}
|
||||
void Null_GetViewportSize(int* x, int* y, int* width, int* height) { *x = 0; *y = 0; *width = 640; *height = 480; }
|
||||
|
||||
tRenderer null_renderer = {
|
||||
Null_Init,
|
||||
|
|
@ -24,5 +28,9 @@ tRenderer null_renderer = {
|
|||
Null_BufferTexture,
|
||||
Null_BufferMaterial,
|
||||
Null_BufferModel,
|
||||
Null_FlushBuffers
|
||||
};
|
||||
Null_FlushBuffers,
|
||||
Null_GetRenderSize,
|
||||
Null_GetWindowSize,
|
||||
Null_SetWindowSize,
|
||||
Null_GetViewportSize
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ typedef struct tRenderer {
|
|||
void (*BufferMaterial)(br_material* mat);
|
||||
void (*BufferModel)(br_model* model);
|
||||
void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer);
|
||||
|
||||
void (*GetRenderSize)(int* width, int* height);
|
||||
void (*GetWindowSize)(int* width, int* height);
|
||||
void (*SetWindowSize)(int width, int height);
|
||||
void (*GetViewport)(int* x, int* y, int* width, int* height);
|
||||
} tRenderer;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue