2021-06-17 21:32:24 +00:00
# include <unistd.h>
# include <SDL/SDL.h>
2022-06-11 01:59:57 +00:00
# include <libreborn/libreborn.h>
2021-06-17 21:32:24 +00:00
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
# define GLFW_INCLUDE_NONE
# include <GLFW/glfw3.h>
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
2021-09-12 03:18:12 +00:00
# include <media-layer/core.h>
# include <media-layer/internal.h>
2021-06-17 21:32:24 +00:00
2021-09-14 22:10:32 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-09-12 03:18:12 +00:00
# include "audio/engine.h"
2022-03-14 23:09:25 +00:00
# endif
2021-09-12 03:18:12 +00:00
2021-11-14 04:29:48 +00:00
// Allow Disabling Interaction
static void update_cursor ( ) ;
static int is_interactable = 1 ;
void media_set_interactable ( int toggle ) {
is_interactable = toggle ;
update_cursor ( ) ;
}
2021-09-12 03:18:12 +00:00
// GLFW Code Not Needed In Headless Mode
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
2022-03-07 01:07:49 +00:00
static GLFWwindow * glfw_window = NULL ;
2021-06-17 21:32:24 +00:00
// Handle GLFW Error
static void glfw_error ( __attribute__ ( ( unused ) ) int error , const char * description ) {
WARN ( " GLFW Error: %s " , description ) ;
}
2021-07-04 23:02:45 +00:00
// Pass Character Event
static void character_event ( char c ) {
// SDL_UserEvent Is Never Used In MCPI, So It Is Repurposed For Character Events
SDL_Event event ;
event . type = SDL_USEREVENT ;
event . user . code = ( int ) c ;
SDL_PushEvent ( & event ) ;
}
2021-06-17 21:32:24 +00:00
// Convert GLFW Key To SDL Key
static SDLKey glfw_key_to_sdl_key ( int key ) {
switch ( key ) {
// Movement
case GLFW_KEY_W :
return SDLK_w ;
case GLFW_KEY_A :
return SDLK_a ;
case GLFW_KEY_S :
return SDLK_s ;
case GLFW_KEY_D :
return SDLK_d ;
case GLFW_KEY_SPACE :
return SDLK_SPACE ;
case GLFW_KEY_LEFT_SHIFT :
return SDLK_LSHIFT ;
case GLFW_KEY_RIGHT_SHIFT :
return SDLK_RSHIFT ;
// Inventory
case GLFW_KEY_E :
return SDLK_e ;
2021-07-04 23:02:45 +00:00
// Drop Item
case GLFW_KEY_Q :
return SDLK_q ;
2021-06-17 21:32:24 +00:00
// Hotbar
case GLFW_KEY_1 :
return SDLK_1 ;
case GLFW_KEY_2 :
return SDLK_2 ;
case GLFW_KEY_3 :
return SDLK_3 ;
case GLFW_KEY_4 :
return SDLK_4 ;
case GLFW_KEY_5 :
return SDLK_5 ;
case GLFW_KEY_6 :
return SDLK_6 ;
case GLFW_KEY_7 :
return SDLK_7 ;
case GLFW_KEY_8 :
return SDLK_8 ;
2021-10-27 22:14:30 +00:00
case GLFW_KEY_9 :
return SDLK_9 ;
case GLFW_KEY_0 :
return SDLK_0 ;
2021-06-17 21:32:24 +00:00
// UI Control
case GLFW_KEY_ESCAPE :
return SDLK_ESCAPE ;
case GLFW_KEY_UP :
return SDLK_UP ;
case GLFW_KEY_DOWN :
return SDLK_DOWN ;
case GLFW_KEY_LEFT :
return SDLK_LEFT ;
case GLFW_KEY_RIGHT :
return SDLK_RIGHT ;
case GLFW_KEY_TAB :
return SDLK_TAB ;
case GLFW_KEY_ENTER :
return SDLK_RETURN ;
case GLFW_KEY_BACKSPACE :
return SDLK_BACKSPACE ;
// Fullscreen
case GLFW_KEY_F11 :
return SDLK_F11 ;
// Screenshot
case GLFW_KEY_F2 :
return SDLK_F2 ;
// Hide GUI
case GLFW_KEY_F1 :
return SDLK_F1 ;
// Third Person
case GLFW_KEY_F5 :
return SDLK_F5 ;
// Chat
case GLFW_KEY_T :
return SDLK_t ;
// Unknown
default :
return SDLK_UNKNOWN ;
}
}
2021-07-04 23:02:45 +00:00
// Convert GLFW Key Modifier To SDL Key Modifier
static SDLMod glfw_modifier_to_sdl_modifier ( int mods ) {
SDLMod ret = KMOD_NONE ;
// Control
if ( ( mods & GLFW_MOD_CONTROL ) ! = 0 ) {
ret | = KMOD_CTRL ;
}
// Shift
if ( ( mods & GLFW_MOD_SHIFT ) ! = 0 ) {
ret | = KMOD_SHIFT ;
}
// Alt
if ( ( mods & GLFW_MOD_ALT ) ! = 0 ) {
ret | = KMOD_ALT ;
}
// Return
return ret ;
2021-06-17 21:32:24 +00:00
}
// Pass Key Presses To SDL
2022-03-06 20:53:27 +00:00
static void glfw_key ( __attribute__ ( ( unused ) ) GLFWwindow * window , int key , int scancode , int action , int mods ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable ) {
SDL_Event event ;
int up = action = = GLFW_RELEASE ;
event . type = up ? SDL_KEYUP : SDL_KEYDOWN ;
event . key . state = up ? SDL_RELEASED : SDL_PRESSED ;
event . key . keysym . scancode = scancode ;
event . key . keysym . mod = glfw_modifier_to_sdl_modifier ( mods ) ;
event . key . keysym . sym = glfw_key_to_sdl_key ( key ) ;
SDL_PushEvent ( & event ) ;
2021-06-17 21:32:24 +00:00
}
}
// Pass Text To Minecraft
2022-07-31 03:52:50 +00:00
static void codepoint_to_utf8 ( unsigned char * const buffer , const unsigned int code ) {
// https://stackoverflow.com/a/42013433/16198887
if ( code < = 0x7f ) {
buffer [ 0 ] = code ;
} else if ( code < = 0x7ff ) {
buffer [ 0 ] = 0xc0 | ( code > > 6 ) ; // 110xxxxx
buffer [ 1 ] = 0x80 | ( code & 0x3f ) ; // 10xxxxxx
} else if ( code < = 0xffff ) {
buffer [ 0 ] = 0xe0 | ( code > > 12 ) ; // 1110xxxx
buffer [ 1 ] = 0x80 | ( ( code > > 6 ) & 0x3f ) ; // 10xxxxxx
buffer [ 2 ] = 0x80 | ( code & 0x3f ) ; // 10xxxxxx
} else if ( code < = 0x10ffff ) {
buffer [ 0 ] = 0xf0 | ( code > > 18 ) ; // 11110xxx
buffer [ 1 ] = 0x80 | ( ( code > > 12 ) & 0x3f ) ; // 10xxxxxx
buffer [ 2 ] = 0x80 | ( ( code > > 6 ) & 0x3f ) ; // 10xxxxxx
buffer [ 3 ] = 0x80 | ( code & 0x3f ) ; // 10xxxxxx
}
}
2021-06-17 21:32:24 +00:00
static void glfw_char ( __attribute__ ( ( unused ) ) GLFWwindow * window , unsigned int codepoint ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable ) {
2022-07-31 03:52:50 +00:00
// Convert
size_t str_size = 4 /* Maximum UTF-8 character size */ + 1 /* NULL-terminator */ ;
char str [ str_size ] ;
memset ( str , 0 , str_size ) ;
codepoint_to_utf8 ( ( unsigned char * ) str , codepoint ) ;
char * cp437_str = to_cp437 ( str ) ;
// Send Event·
for ( int i = 0 ; cp437_str [ i ] ! = ' \0 ' ; i + + ) {
character_event ( cp437_str [ i ] ) ;
2022-07-20 06:58:14 +00:00
}
// Free
2022-07-31 03:52:50 +00:00
free ( cp437_str ) ;
2021-11-14 04:29:48 +00:00
}
2021-06-17 21:32:24 +00:00
}
2021-11-14 04:29:48 +00:00
// Last Mouse Location
2021-06-17 21:32:24 +00:00
static double last_mouse_x = 0 ;
static double last_mouse_y = 0 ;
2021-11-14 04:29:48 +00:00
// Ignore Relative Cursor Motion
static int ignore_relative_motion = 0 ;
2021-06-17 21:32:24 +00:00
// Pass Mouse Movement To SDL
static void glfw_motion ( __attribute__ ( ( unused ) ) GLFWwindow * window , double xpos , double ypos ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable ) {
SDL_Event event ;
event . type = SDL_MOUSEMOTION ;
event . motion . x = xpos ;
event . motion . y = ypos ;
event . motion . xrel = ! ignore_relative_motion ? ( xpos - last_mouse_x ) : 0 ;
event . motion . yrel = ! ignore_relative_motion ? ( ypos - last_mouse_y ) : 0 ;
SDL_PushEvent ( & event ) ;
}
ignore_relative_motion = 0 ;
2021-06-17 21:32:24 +00:00
last_mouse_x = xpos ;
last_mouse_y = ypos ;
}
// Create And Push SDL Mouse Click Event
static void click_event ( int button , int up ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable ) {
SDL_Event event ;
event . type = up ? SDL_MOUSEBUTTONUP : SDL_MOUSEBUTTONDOWN ;
event . button . x = last_mouse_x ;
event . button . y = last_mouse_y ;
event . button . state = up ? SDL_RELEASED : SDL_PRESSED ;
event . button . button = button ;
SDL_PushEvent ( & event ) ;
}
2021-06-17 21:32:24 +00:00
}
// Pass Mouse Click To SDL
static void glfw_click ( __attribute__ ( ( unused ) ) GLFWwindow * window , int button , int action , __attribute__ ( ( unused ) ) int mods ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable ) {
int up = action = = GLFW_RELEASE ;
int sdl_button = button = = GLFW_MOUSE_BUTTON_RIGHT ? SDL_BUTTON_RIGHT : ( button = = GLFW_MOUSE_BUTTON_LEFT ? SDL_BUTTON_LEFT : SDL_BUTTON_MIDDLE ) ;
click_event ( sdl_button , up ) ;
}
2021-06-17 21:32:24 +00:00
}
// Pass Mouse Scroll To SDL
static void glfw_scroll ( __attribute__ ( ( unused ) ) GLFWwindow * window , __attribute__ ( ( unused ) ) double xoffset , double yoffset ) {
2021-11-14 04:29:48 +00:00
if ( is_interactable & & yoffset ! = 0 ) {
2021-06-17 21:32:24 +00:00
int sdl_button = yoffset > 0 ? SDL_BUTTON_WHEELUP : SDL_BUTTON_WHEELDOWN ;
click_event ( sdl_button , 0 ) ;
click_event ( sdl_button , 1 ) ;
}
}
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
2021-09-12 03:18:12 +00:00
// Track Media Layer State
2022-05-29 22:44:27 +00:00
static volatile int is_running = 0 ;
2021-09-12 03:18:12 +00:00
2022-03-07 01:07:49 +00:00
// Track If Raw Mouse Motion Is Enabled
static int raw_mouse_motion_enabled = 1 ;
void media_set_raw_mouse_motion_enabled ( int enabled ) {
raw_mouse_motion_enabled = enabled ;
# ifndef MCPI_HEADLESS_MODE
if ( is_running ) {
glfwSetInputMode ( glfw_window , GLFW_RAW_MOUSE_MOTION , GLFW_FALSE ) ;
}
2022-03-14 23:09:25 +00:00
# endif
2022-03-07 01:07:49 +00:00
if ( ! raw_mouse_motion_enabled ) {
2022-04-15 01:12:42 +00:00
WARN ( " Raw mouse motion has been DISABLED, this IS NOT recommended, and should only ever be used on systems that don't support or have broken raw mouse motion. " ) ;
2022-03-07 01:07:49 +00:00
}
}
2021-11-14 04:29:48 +00:00
// Disable V-Sync
static int disable_vsync = 0 ;
void media_disable_vsync ( ) {
disable_vsync = 1 ;
# ifndef MCPI_HEADLESS_MODE
if ( is_running ) {
glfwSwapInterval ( 0 ) ;
}
2022-03-14 23:09:25 +00:00
# endif
2021-11-14 04:29:48 +00:00
}
2022-07-16 02:08:12 +00:00
// Force EGL
static int force_egl = 0 ;
void media_force_egl ( ) {
if ( force_egl = = - 1 ) {
IMPOSSIBLE ( ) ;
}
force_egl = 1 ;
}
2021-09-12 03:18:12 +00:00
// Init Media Layer
2022-05-29 22:44:27 +00:00
# define GL_VERSION 0x1f02
typedef const unsigned char * ( * glGetString_t ) ( unsigned int name ) ;
2021-06-17 21:32:24 +00:00
void SDL_WM_SetCaption ( const char * title , __attribute__ ( ( unused ) ) const char * icon ) {
2021-09-12 03:18:12 +00:00
// Don't Enable GLFW In Headless Mode
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-09-12 03:18:12 +00:00
// Init GLFW
2021-06-17 21:32:24 +00:00
glfwSetErrorCallback ( glfw_error ) ;
if ( ! glfwInit ( ) ) {
2022-04-15 01:12:42 +00:00
ERR ( " Unable To Initialize GLFW " ) ;
2021-06-17 21:32:24 +00:00
}
2022-05-29 22:44:27 +00:00
// Create OpenGL ES Context
2021-06-17 21:32:24 +00:00
glfwWindowHint ( GLFW_CLIENT_API , GLFW_OPENGL_ES_API ) ;
2022-05-29 22:44:27 +00:00
# ifdef MCPI_USE_GLES1_COMPATIBILITY_LAYER
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 2 ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 0 ) ;
# else
2021-06-17 21:32:24 +00:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 1 ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 1 ) ;
2022-05-29 22:44:27 +00:00
# endif
2022-07-16 02:08:12 +00:00
// Use EGL
if ( force_egl ) {
glfwWindowHint ( GLFW_CONTEXT_CREATION_API , GLFW_EGL_CONTEXT_API ) ;
}
force_egl = - 1 ;
2021-06-17 21:32:24 +00:00
// Extra Settings
glfwWindowHint ( GLFW_AUTO_ICONIFY , GLFW_FALSE ) ;
glfwWindowHint ( GLFW_ALPHA_BITS , 0 ) ; // Fix Transparent Window On Wayland
2022-07-30 02:13:03 +00:00
// App ID
glfwWindowHintString ( GLFW_X11_CLASS_NAME , MCPI_APP_ID ) ;
glfwWindowHintString ( GLFW_WAYLAND_APP_ID , MCPI_APP_ID ) ;
2021-06-17 21:32:24 +00:00
2022-05-14 02:36:12 +00:00
// Create Window
2021-06-17 21:32:24 +00:00
glfw_window = glfwCreateWindow ( DEFAULT_WIDTH , DEFAULT_HEIGHT , title , NULL , NULL ) ;
if ( ! glfw_window ) {
2022-04-15 01:12:42 +00:00
ERR ( " Unable To Create GLFW Window " ) ;
2021-06-17 21:32:24 +00:00
}
2022-05-14 02:36:12 +00:00
// Event Handlers
2021-06-17 21:32:24 +00:00
glfwSetKeyCallback ( glfw_window , glfw_key ) ;
glfwSetCharCallback ( glfw_window , glfw_char ) ;
glfwSetCursorPosCallback ( glfw_window , glfw_motion ) ;
glfwSetMouseButtonCallback ( glfw_window , glfw_click ) ;
glfwSetScrollCallback ( glfw_window , glfw_scroll ) ;
2022-05-14 02:36:12 +00:00
// Make Window Context Current
2021-06-17 21:32:24 +00:00
glfwMakeContextCurrent ( glfw_window ) ;
2021-09-12 03:18:12 +00:00
2022-05-29 22:44:27 +00:00
// Debug
glGetString_t glGetString = ( glGetString_t ) glfwGetProcAddress ( " glGetString " ) ;
DEBUG ( " Using %s " , ( * glGetString ) ( GL_VERSION ) ) ;
2021-09-12 03:18:12 +00:00
// Init OpenAL
_media_audio_init ( ) ;
2022-03-14 23:09:25 +00:00
# else
2021-06-17 21:32:24 +00:00
( void ) title ; // Mark As Used
2022-03-14 23:09:25 +00:00
# endif
2021-09-12 03:18:12 +00:00
// Set State
is_running = 1 ;
2021-11-14 04:29:48 +00:00
// Update State
update_cursor ( ) ;
if ( disable_vsync ) {
media_disable_vsync ( ) ;
}
2022-05-29 22:44:27 +00:00
// Always Cleanup Media Layer
atexit ( media_cleanup ) ;
2021-06-17 21:32:24 +00:00
}
void media_swap_buffers ( ) {
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
// Don't Swap Buffers In A Context-Less Window
glfwSwapBuffers ( glfw_window ) ;
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
}
2021-09-12 03:18:12 +00:00
// Fullscreen Not Needed In Headless Mode
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
static int is_fullscreen = 0 ;
// Old Size And Position To Use When Exiting Fullscreen
static int old_width = - 1 ;
static int old_height = - 1 ;
static int old_x = - 1 ;
static int old_y = - 1 ;
// Toggle Fullscreen
void media_toggle_fullscreen ( ) {
if ( is_fullscreen ) {
glfwSetWindowMonitor ( glfw_window , NULL , old_x , old_y , old_width , old_height , GLFW_DONT_CARE ) ;
old_width = - 1 ;
old_height = - 1 ;
old_x = - 1 ;
old_y = - 1 ;
} else {
glfwGetWindowSize ( glfw_window , & old_width , & old_height ) ;
glfwGetWindowPos ( glfw_window , & old_x , & old_y ) ;
GLFWmonitor * monitor = glfwGetPrimaryMonitor ( ) ;
const GLFWvidmode * mode = glfwGetVideoMode ( monitor ) ;
glfwSetWindowMonitor ( glfw_window , monitor , 0 , 0 , mode - > width , mode - > height , GLFW_DONT_CARE ) ;
}
is_fullscreen = ! is_fullscreen ;
}
2022-03-14 23:09:25 +00:00
# else
2021-06-17 21:32:24 +00:00
void media_toggle_fullscreen ( ) {
}
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
// Intercept SDL Events
void _media_handle_SDL_PollEvent ( ) {
2021-09-12 03:18:12 +00:00
// GLFW And Audio Are Disabled Disabled In Headless Mode
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
// Process GLFW Events
glfwPollEvents ( ) ;
// Close Window
if ( glfwWindowShouldClose ( glfw_window ) ) {
SDL_Event event ;
event . type = SDL_QUIT ;
SDL_PushEvent ( & event ) ;
glfwSetWindowShouldClose ( glfw_window , GLFW_FALSE ) ;
}
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
}
2021-09-12 03:18:12 +00:00
// Cleanup Media Layer
2021-06-17 21:32:24 +00:00
void media_cleanup ( ) {
2021-09-12 03:18:12 +00:00
if ( is_running ) {
// GLFW And Audio Are Disabled In Headless Mode
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-09-12 20:38:41 +00:00
// Ignore GLFW Errors During Termination
glfwSetErrorCallback ( NULL ) ;
2021-09-12 03:18:12 +00:00
// Terminate GLFW
glfwDestroyWindow ( glfw_window ) ;
glfwTerminate ( ) ;
// Cleanup OpenAL
_media_audio_cleanup ( ) ;
2022-03-14 23:09:25 +00:00
# endif
2021-09-12 03:18:12 +00:00
// Update State
is_running = 0 ;
}
2021-06-17 21:32:24 +00:00
}
2021-06-19 23:07:09 +00:00
// Store Cursor State
static int cursor_grabbed = 0 ;
static int cursor_visible = 1 ;
// Update GLFW Cursor State (Client Only)
2021-11-14 04:29:48 +00:00
static void update_cursor ( ) {
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-11-14 04:29:48 +00:00
if ( is_running ) {
// Get New State
int new_cursor_visible = is_interactable ? cursor_visible : 1 ;
int new_cursor_grabbed = is_interactable ? cursor_grabbed : 0 ;
// Store Old Mode
int old_mode = glfwGetInputMode ( glfw_window , GLFW_CURSOR ) ;
// Handle Cursor Visibility
int new_mode ;
if ( ! new_cursor_visible ) {
if ( new_cursor_grabbed ) {
new_mode = GLFW_CURSOR_DISABLED ;
} else {
new_mode = GLFW_CURSOR_HIDDEN ;
}
2021-06-19 23:07:09 +00:00
} else {
2021-11-14 04:29:48 +00:00
new_mode = GLFW_CURSOR_NORMAL ;
2021-06-19 23:07:09 +00:00
}
2021-11-14 04:29:48 +00:00
if ( new_mode ! = old_mode ) {
// Ignore Relative Cursor Motion When Locking
if ( new_mode = = GLFW_CURSOR_DISABLED & & old_mode ! = GLFW_CURSOR_DISABLED ) {
ignore_relative_motion = 1 ;
}
// Set New Mode
glfwSetInputMode ( glfw_window , GLFW_CURSOR , new_mode ) ;
// Handle Cursor Lock/Unlock
2022-03-07 01:07:49 +00:00
if ( raw_mouse_motion_enabled & & ( ( new_mode = = GLFW_CURSOR_DISABLED & & old_mode ! = GLFW_CURSOR_DISABLED ) | | ( new_mode ! = GLFW_CURSOR_DISABLED & & old_mode = = GLFW_CURSOR_DISABLED ) ) ) {
2021-11-14 04:29:48 +00:00
// Use Raw Mouse Motion
glfwSetInputMode ( glfw_window , GLFW_RAW_MOUSE_MOTION , new_mode = = GLFW_CURSOR_DISABLED ? GLFW_TRUE : GLFW_FALSE ) ;
}
// Reset Mouse Position When Unlocking
if ( new_mode ! = GLFW_CURSOR_DISABLED & & old_mode = = GLFW_CURSOR_DISABLED ) {
double cursor_x ;
double cursor_y ;
glfwGetCursorPos ( glfw_window , & cursor_x , & cursor_y ) ;
glfw_motion ( glfw_window , cursor_x , cursor_y ) ;
}
2021-06-19 23:07:09 +00:00
}
}
2022-03-14 23:09:25 +00:00
# endif
2021-06-19 23:07:09 +00:00
}
2021-06-17 21:32:24 +00:00
// Fix SDL Cursor Visibility/Grabbing
SDL_GrabMode SDL_WM_GrabInput ( SDL_GrabMode mode ) {
2021-06-19 23:07:09 +00:00
if ( mode = = SDL_GRAB_QUERY ) {
// Query
return cursor_grabbed ? SDL_GRAB_ON : SDL_GRAB_OFF ;
} else if ( mode = = SDL_GRAB_ON ) {
// Store State
cursor_grabbed = 1 ;
} else if ( mode = = SDL_GRAB_OFF ) {
// Store State
cursor_grabbed = 0 ;
2021-06-17 21:32:24 +00:00
}
2021-06-19 23:07:09 +00:00
// Update Cursor GLFW State (Client Only)
2021-11-14 04:29:48 +00:00
update_cursor ( ) ;
2021-06-19 23:07:09 +00:00
// Return
return mode ;
2021-06-17 21:32:24 +00:00
}
// Stub SDL Cursor Visibility
int SDL_ShowCursor ( int toggle ) {
2021-06-19 23:07:09 +00:00
if ( toggle = = SDL_QUERY ) {
// Query
return cursor_visible ? SDL_ENABLE : SDL_DISABLE ;
} else if ( toggle = = SDL_ENABLE ) {
// Store State
cursor_visible = 1 ;
} else if ( toggle = = SDL_DISABLE ) {
// Store State
cursor_visible = 0 ;
}
// Update Cursor GLFW State (Client Only)
2021-11-14 04:29:48 +00:00
update_cursor ( ) ;
2021-06-19 23:07:09 +00:00
// Return
return toggle ;
2021-06-17 21:32:24 +00:00
}
// Get Framebuffer Size
void media_get_framebuffer_size ( int * width , int * height ) {
2021-08-27 02:52:18 +00:00
# ifndef MCPI_HEADLESS_MODE
2021-06-17 21:32:24 +00:00
if ( glfw_window ! = NULL ) {
glfwGetFramebufferSize ( glfw_window , width , height ) ;
return ;
}
2022-03-14 23:09:25 +00:00
# endif
2021-06-17 21:32:24 +00:00
* width = DEFAULT_WIDTH ;
* height = DEFAULT_HEIGHT ;
}