mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	 cfacbd91be
			
		
	
	
		cfacbd91be
		
	
	
	
	
		
			
			This fixes the issue with certain compilers that have int set to different sizes by either explicitly casting or setting templates manually
		
			
				
	
	
		
			1842 lines
		
	
	
	
		
			47 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1842 lines
		
	
	
	
		
			47 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // DR. ROBOTNIK'S RING RACERS
 | |
| //-----------------------------------------------------------------------------
 | |
| // Copyright (C) 2024 by Kart Krew.
 | |
| // Copyright (C) 2020 by Sonic Team Junior.
 | |
| // Copyright (C) 2000 by DooM Legacy Team.
 | |
| // Copyright (C) 1996 by id Software, Inc.
 | |
| //
 | |
| // This program is free software distributed under the
 | |
| // terms of the GNU General Public License, version 2.
 | |
| // See the 'LICENSE' file for more details.
 | |
| //-----------------------------------------------------------------------------
 | |
| /// \file
 | |
| /// \brief SRB2 graphics stuff for SDL
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <errno.h>
 | |
| #include <memory>
 | |
| 
 | |
| #include <signal.h>
 | |
| 
 | |
| #include <imgui.h>
 | |
| 
 | |
| #include "../rhi/rhi.hpp"
 | |
| #include "../rhi/gl2/gl2_rhi.hpp"
 | |
| #include "rhi_gl2_platform.hpp"
 | |
| 
 | |
| #ifdef _MSC_VER
 | |
| #pragma warning(disable : 4214 4244)
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_SDL
 | |
| #define _MATH_DEFINES_DEFINED
 | |
| #include "SDL.h"
 | |
| 
 | |
| #ifdef _MSC_VER
 | |
| #include <windows.h>
 | |
| #pragma warning(default : 4214 4244)
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_TTF
 | |
| #include "i_ttf.h"
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_IMAGE
 | |
| #include "SDL_image.h"
 | |
| #elif defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) // Windows & Mac don't need this, as SDL will do it for us.
 | |
| #define LOAD_XPM //I want XPM!
 | |
| #include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so
 | |
| #define HAVE_IMAGE //I have SDL_Image, sortof
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_IMAGE
 | |
| #include "SDL_icon.xpm"
 | |
| #endif
 | |
| 
 | |
| #include "../doomdef.h"
 | |
| 
 | |
| #ifdef _WIN32
 | |
| #include "SDL_syswm.h"
 | |
| #endif
 | |
| 
 | |
| #include "../doomstat.h"
 | |
| #include "../i_system.h"
 | |
| #include "../v_video.h"
 | |
| #include "../m_argv.h"
 | |
| #include "../k_menu.h"
 | |
| #include "../d_main.h"
 | |
| #include "../s_sound.h"
 | |
| #include "../i_sound.h"  	// midi pause/unpause
 | |
| #include "../i_joy.h"
 | |
| #include "../st_stuff.h"
 | |
| #include "../hu_stuff.h"
 | |
| #include "../g_game.h"
 | |
| #include "../i_video.h"
 | |
| #include "../console.h"
 | |
| #include "../command.h"
 | |
| #include "../r_main.h"
 | |
| #include "../lua_hook.h"
 | |
| #include "sdlmain.h"
 | |
| #include "../i_system.h"
 | |
| #ifdef HWRENDER
 | |
| #include "../hardware/hw_main.h"
 | |
| #include "../hardware/hw_drv.h"
 | |
| // For dynamic referencing of HW rendering functions
 | |
| #include "hwsym_sdl.h"
 | |
| #include "ogl_sdl.h"
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_DISCORDRPC
 | |
| #include "../discord.h"
 | |
| #endif
 | |
| 
 | |
| // maximum number of windowed modes (see windowedModes[][])
 | |
| #define MAXWINMODES (18)
 | |
| 
 | |
| using namespace srb2;
 | |
| 
 | |
| /**	\brief
 | |
| */
 | |
| static INT32 numVidModes = -1;
 | |
| 
 | |
| /**	\brief
 | |
| */
 | |
| static char vidModeName[33][32]; // allow 33 different modes
 | |
| 
 | |
| rendermode_t rendermode = render_soft;
 | |
| rendermode_t chosenrendermode = render_none; // set by command line arguments
 | |
| 
 | |
| UINT8 graphics_started = 0; // Is used in console.c and screen.c
 | |
| 
 | |
| // To disable fullscreen at startup; is set in VID_PrepareModeList
 | |
| boolean allow_fullscreen = false;
 | |
| static SDL_bool disable_fullscreen = SDL_FALSE;
 | |
| #define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value
 | |
| static SDL_bool disable_mouse = SDL_FALSE;
 | |
| #define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus)
 | |
| #define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN)
 | |
| #define MOUSEBUTTONS_MAX MOUSEBUTTONS
 | |
| 
 | |
| // first entry in the modelist which is not bigger than MAXVIDWIDTHxMAXVIDHEIGHT
 | |
| static      INT32          firstEntry = 0;
 | |
| 
 | |
| // Total mouse motion X/Y offsets
 | |
| static      INT32        mousemovex = 0, mousemovey = 0;
 | |
| 
 | |
| // SDL vars
 | |
| static      SDL_Surface *vidSurface = NULL;
 | |
| static      SDL_Surface *bufSurface = NULL;
 | |
| static      SDL_Surface *icoSurface = NULL;
 | |
| static      SDL_Color    localPalette[256];
 | |
| Uint16      realwidth = BASEVIDWIDTH;
 | |
| Uint16      realheight = BASEVIDHEIGHT;
 | |
| static       SDL_bool    mousegrabok = SDL_TRUE;
 | |
| static       SDL_bool    wrapmouseok = SDL_FALSE;
 | |
| static       SDL_bool    exposevideo = SDL_FALSE;
 | |
| static       SDL_bool    borderlesswindow = SDL_FALSE;
 | |
| 
 | |
| // SDL2 vars
 | |
| SDL_Window   *window;
 | |
| static SDL_bool      havefocus = SDL_TRUE;
 | |
| static const char *fallback_resolution_name = "Fallback";
 | |
| 
 | |
| static std::unique_ptr<rhi::Rhi> g_rhi;
 | |
| static uint32_t g_rhi_generation = 0;
 | |
| 
 | |
| // windowed video modes from which to choose from.
 | |
| static INT32 windowedModes[MAXWINMODES][2] =
 | |
| {
 | |
| 	{1920,1200}, // 1.60,6.00
 | |
| 	{1920,1080}, // 1.66
 | |
| 	{1680,1050}, // 1.60,5.25
 | |
| 	{1600,1200}, // 1.33
 | |
| 	{1600, 900}, // 1.66
 | |
| 	{1366, 768}, // 1.66
 | |
| 	{1440, 900}, // 1.60,4.50
 | |
| 	{1280,1024}, // 1.33?
 | |
| 	{1280, 960}, // 1.33,4.00
 | |
| 	{1280, 800}, // 1.60,4.00
 | |
| 	{1280, 720}, // 1.66
 | |
| 	{1152, 864}, // 1.33,3.60
 | |
| 	{1024, 768}, // 1.33,3.20
 | |
| 	{ 800, 600}, // 1.33,2.50
 | |
| 	{ 640, 480}, // 1.33,2.00
 | |
| 	{ 640, 400}, // 1.60,2.00
 | |
| 	{ 320, 240}, // 1.33,1.00
 | |
| 	{ 320, 200}, // 1.60,1.00
 | |
| };
 | |
| 
 | |
| static void Impl_VideoSetupBuffer(void);
 | |
| static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
 | |
| //static void Impl_SetWindowName(const char *title);
 | |
| static void Impl_SetWindowIcon(void);
 | |
| 
 | |
| static void SDLSetMode(int width, int height, SDL_bool fullscreen, SDL_bool reposition)
 | |
| {
 | |
| 	static SDL_bool wasfullscreen = SDL_FALSE;
 | |
| 
 | |
| 	realwidth = vid.width;
 | |
| 	realheight = vid.height;
 | |
| 
 | |
| 	if (window)
 | |
| 	{
 | |
| 		if (fullscreen)
 | |
| 		{
 | |
| 			wasfullscreen = SDL_TRUE;
 | |
| 			SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
 | |
| 		}
 | |
| 		else // windowed mode
 | |
| 		{
 | |
| 			if (wasfullscreen)
 | |
| 			{
 | |
| 				wasfullscreen = SDL_FALSE;
 | |
| 				SDL_SetWindowFullscreen(window, 0);
 | |
| 			}
 | |
| 			// Reposition window only in windowed mode
 | |
| 			SDL_SetWindowSize(window, width, height);
 | |
| 			if (reposition)
 | |
| 			{
 | |
| 				SDL_SetWindowPosition(window,
 | |
| 					SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
 | |
| 					SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
 | |
| 				);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		Impl_CreateWindow(fullscreen);
 | |
| 		wasfullscreen = fullscreen;
 | |
| 		SDL_SetWindowSize(window, width, height);
 | |
| 		if (fullscreen)
 | |
| 		{
 | |
| 			SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| #ifdef HWRENDER
 | |
| 	if (rendermode == render_opengl)
 | |
| 	{
 | |
| 		OglSdlSurface(vid.width, vid.height);
 | |
| 	}
 | |
| 	else
 | |
| #endif
 | |
| 	{
 | |
| 		SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0);
 | |
| 	}
 | |
| 
 | |
| 	SDL_GetWindowSize(window, &width, &height);
 | |
| 	vid.realwidth = static_cast<uint32_t>(width);
 | |
| 	vid.realheight = static_cast<uint32_t>(height);
 | |
| 
 | |
| 	if (graphics_started)
 | |
| 	{
 | |
| 		I_UpdateNoVsync();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
 | |
| {
 | |
| 	if (code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z)
 | |
| 	{
 | |
| 		// get lowercase ASCII
 | |
| 		return code - SDL_SCANCODE_A + 'a';
 | |
| 	}
 | |
| 	if (code >= SDL_SCANCODE_1 && code <= SDL_SCANCODE_9)
 | |
| 	{
 | |
| 		return code - SDL_SCANCODE_1 + '1';
 | |
| 	}
 | |
| 	else if (code == SDL_SCANCODE_0)
 | |
| 	{
 | |
| 		return '0';
 | |
| 	}
 | |
| 	if (code >= SDL_SCANCODE_F1 && code <= SDL_SCANCODE_F10)
 | |
| 	{
 | |
| 		return KEY_F1 + (code - SDL_SCANCODE_F1);
 | |
| 	}
 | |
| 	switch (code)
 | |
| 	{
 | |
| 		// F11 and F12 are separated from the rest of the function keys
 | |
| 		case SDL_SCANCODE_F11: return KEY_F11;
 | |
| 		case SDL_SCANCODE_F12: return KEY_F12;
 | |
| 
 | |
| 		case SDL_SCANCODE_KP_0: return KEY_KEYPAD0;
 | |
| 		case SDL_SCANCODE_KP_1: return KEY_KEYPAD1;
 | |
| 		case SDL_SCANCODE_KP_2: return KEY_KEYPAD2;
 | |
| 		case SDL_SCANCODE_KP_3: return KEY_KEYPAD3;
 | |
| 		case SDL_SCANCODE_KP_4: return KEY_KEYPAD4;
 | |
| 		case SDL_SCANCODE_KP_5: return KEY_KEYPAD5;
 | |
| 		case SDL_SCANCODE_KP_6: return KEY_KEYPAD6;
 | |
| 		case SDL_SCANCODE_KP_7: return KEY_KEYPAD7;
 | |
| 		case SDL_SCANCODE_KP_8: return KEY_KEYPAD8;
 | |
| 		case SDL_SCANCODE_KP_9: return KEY_KEYPAD9;
 | |
| 
 | |
| 		case SDL_SCANCODE_RETURN:         return KEY_ENTER;
 | |
| 		case SDL_SCANCODE_ESCAPE:         return KEY_ESCAPE;
 | |
| 		case SDL_SCANCODE_BACKSPACE:      return KEY_BACKSPACE;
 | |
| 		case SDL_SCANCODE_TAB:            return KEY_TAB;
 | |
| 		case SDL_SCANCODE_SPACE:          return KEY_SPACE;
 | |
| 		case SDL_SCANCODE_MINUS:          return KEY_MINUS;
 | |
| 		case SDL_SCANCODE_EQUALS:         return KEY_EQUALS;
 | |
| 		case SDL_SCANCODE_LEFTBRACKET:    return '[';
 | |
| 		case SDL_SCANCODE_RIGHTBRACKET:   return ']';
 | |
| 		case SDL_SCANCODE_BACKSLASH:      return '\\';
 | |
| 		case SDL_SCANCODE_NONUSHASH:      return '#';
 | |
| 		case SDL_SCANCODE_SEMICOLON:      return ';';
 | |
| 		case SDL_SCANCODE_APOSTROPHE:     return '\'';
 | |
| 		case SDL_SCANCODE_GRAVE:          return '`';
 | |
| 		case SDL_SCANCODE_COMMA:          return ',';
 | |
| 		case SDL_SCANCODE_PERIOD:         return '.';
 | |
| 		case SDL_SCANCODE_SLASH:          return '/';
 | |
| 		case SDL_SCANCODE_CAPSLOCK:       return KEY_CAPSLOCK;
 | |
| 		case SDL_SCANCODE_PRINTSCREEN:    return 0; // undefined?
 | |
| 		case SDL_SCANCODE_SCROLLLOCK:     return KEY_SCROLLLOCK;
 | |
| 		case SDL_SCANCODE_PAUSE:          return KEY_PAUSE;
 | |
| 		case SDL_SCANCODE_INSERT:         return KEY_INS;
 | |
| 		case SDL_SCANCODE_HOME:           return KEY_HOME;
 | |
| 		case SDL_SCANCODE_PAGEUP:         return KEY_PGUP;
 | |
| 		case SDL_SCANCODE_DELETE:         return KEY_DEL;
 | |
| 		case SDL_SCANCODE_END:            return KEY_END;
 | |
| 		case SDL_SCANCODE_PAGEDOWN:       return KEY_PGDN;
 | |
| 		case SDL_SCANCODE_RIGHT:          return KEY_RIGHTARROW;
 | |
| 		case SDL_SCANCODE_LEFT:           return KEY_LEFTARROW;
 | |
| 		case SDL_SCANCODE_DOWN:           return KEY_DOWNARROW;
 | |
| 		case SDL_SCANCODE_UP:             return KEY_UPARROW;
 | |
| 		case SDL_SCANCODE_NUMLOCKCLEAR:   return KEY_NUMLOCK;
 | |
| 		case SDL_SCANCODE_KP_DIVIDE:      return KEY_KPADSLASH;
 | |
| 		case SDL_SCANCODE_KP_MULTIPLY:    return '*'; // undefined?
 | |
| 		case SDL_SCANCODE_KP_MINUS:       return KEY_MINUSPAD;
 | |
| 		case SDL_SCANCODE_KP_PLUS:        return KEY_PLUSPAD;
 | |
| 		case SDL_SCANCODE_KP_ENTER:       return KEY_ENTER;
 | |
| 		case SDL_SCANCODE_KP_PERIOD:      return KEY_KPADDEL;
 | |
| 		case SDL_SCANCODE_NONUSBACKSLASH: return '\\';
 | |
| 
 | |
| 		case SDL_SCANCODE_LSHIFT: return KEY_LSHIFT;
 | |
| 		case SDL_SCANCODE_RSHIFT: return KEY_RSHIFT;
 | |
| 		case SDL_SCANCODE_LCTRL:  return KEY_LCTRL;
 | |
| 		case SDL_SCANCODE_RCTRL:  return KEY_RCTRL;
 | |
| 		case SDL_SCANCODE_LALT:   return KEY_LALT;
 | |
| 		case SDL_SCANCODE_RALT:   return KEY_RALT;
 | |
| 		case SDL_SCANCODE_LGUI:   return KEY_LEFTWIN;
 | |
| 		case SDL_SCANCODE_RGUI:   return KEY_RIGHTWIN;
 | |
| 		default:                  break;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static boolean IgnoreMouse(void)
 | |
| {
 | |
| 	extern consvar_t cv_alwaysgrabmouse;
 | |
| 	if (cv_alwaysgrabmouse.value)
 | |
| 		return false;
 | |
| 	if (menuactive)
 | |
| 		return false; // return !M_MouseNeeded();
 | |
| 	if (paused || con_destlines || chat_on)
 | |
| 		return true;
 | |
| 	if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION &&
 | |
| 			gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE)
 | |
| 		return true;
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| static void SDLdoGrabMouse(void)
 | |
| {
 | |
| 	SDL_ShowCursor(SDL_DISABLE);
 | |
| 	SDL_SetWindowGrab(window, SDL_TRUE);
 | |
| 	if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
 | |
| 		wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
 | |
| }
 | |
| 
 | |
| static void SDLdoUngrabMouse(void)
 | |
| {
 | |
| 	SDL_ShowCursor(SDL_ENABLE);
 | |
| 	SDL_SetWindowGrab(window, SDL_FALSE);
 | |
| 	wrapmouseok = SDL_FALSE;
 | |
| 	SDL_SetRelativeMouseMode(SDL_FALSE);
 | |
| }
 | |
| 
 | |
| void SDLforceUngrabMouse(void)
 | |
| {
 | |
| 	if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO && window != NULL)
 | |
| 		SDLdoUngrabMouse();
 | |
| }
 | |
| 
 | |
| void I_UpdateMouseGrab(void)
 | |
| {
 | |
| 	if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO && window != NULL
 | |
| 	&& SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window
 | |
| 	&& USE_MOUSEINPUT && !IgnoreMouse())
 | |
| 		SDLdoGrabMouse();
 | |
| }
 | |
| 
 | |
| static void VID_Command_NumModes_f (void)
 | |
| {
 | |
| 	CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes());
 | |
| }
 | |
| 
 | |
| // SDL2 doesn't have SDL_GetVideoSurface or a lot of the SDL_Surface flags that SDL 1.2 had
 | |
| static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
 | |
| {
 | |
| 	INT32 vfBPP;
 | |
| 
 | |
| 	if (!infoSurface)
 | |
| 		return;
 | |
| 
 | |
| 	if (!SurfaceText)
 | |
| 		SurfaceText = M_GetText("Unknown Surface");
 | |
| 
 | |
| 	vfBPP = infoSurface->format?infoSurface->format->BitsPerPixel:0;
 | |
| 
 | |
| 	CONS_Printf("\x82" "%s\n", SurfaceText);
 | |
| 	CONS_Printf(M_GetText(" %ix%i at %i bit color\n"), infoSurface->w, infoSurface->h, vfBPP);
 | |
| 
 | |
| 	if (infoSurface->flags&SDL_PREALLOC)
 | |
| 		CONS_Printf("%s", M_GetText(" Uses preallocated memory\n"));
 | |
| 	else
 | |
| 		CONS_Printf("%s", M_GetText(" Stored in system memory\n"));
 | |
| 	if (infoSurface->flags&SDL_RLEACCEL)
 | |
| 		CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n"));
 | |
| }
 | |
| 
 | |
| static void VID_Command_Info_f (void)
 | |
| {
 | |
| 	SurfaceInfo(bufSurface, M_GetText("Current Engine Mode"));
 | |
| 	SurfaceInfo(vidSurface, M_GetText("Current Video Mode"));
 | |
| }
 | |
| 
 | |
| static void VID_Command_ModeList_f(void)
 | |
| {
 | |
| 	// List windowed modes
 | |
| 	INT32 i = 0;
 | |
| 	CONS_Printf("NOTE: Under SDL2, all modes are supported on all platforms.\n");
 | |
| 	CONS_Printf("Under opengl, fullscreen only supports native desktop resolution.\n");
 | |
| 	CONS_Printf("Under software, the mode is stretched up to desktop resolution.\n");
 | |
| 	for (i = 0; i < MAXWINMODES; i++)
 | |
| 	{
 | |
| 		CONS_Printf("%2d: %dx%d\n", i, windowedModes[i][0], windowedModes[i][1]);
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| static void VID_Command_Mode_f (void)
 | |
| {
 | |
| 	INT32 modenum;
 | |
| 
 | |
| 	if (COM_Argc()!= 2)
 | |
| 	{
 | |
| 		CONS_Printf(M_GetText("vid_mode <modenum> : set video mode, current video mode %i\n"), vid.modenum);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	modenum = atoi(COM_Argv(1));
 | |
| 
 | |
| 	if (modenum >= VID_NumModes())
 | |
| 		CONS_Printf(M_GetText("Video mode not present\n"));
 | |
| 	else
 | |
| 		setmodeneeded = modenum+1; // request vid mode change
 | |
| }
 | |
| 
 | |
| static inline void SDLJoyRemap(event_t *event)
 | |
| {
 | |
| 	(void)event;
 | |
| }
 | |
| 
 | |
| static INT32 SDLJoyAxis(const Sint16 axis, UINT8 pid)
 | |
| {
 | |
| 	// -32768 to 32767
 | |
| 	INT32 raxis = axis / 32;
 | |
| 
 | |
| 	if (Joystick[pid].bGamepadStyle)
 | |
| 	{
 | |
| 		// gamepad control type, on or off, live or die
 | |
| 		if (raxis < -(JOYAXISRANGE/2))
 | |
| 			raxis = -1;
 | |
| 		else if (raxis > (JOYAXISRANGE/2))
 | |
| 			raxis = 1;
 | |
| 		else
 | |
| 			raxis = 0;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		raxis = (abs(JoyInfo[pid].scale) > 1) ? ((raxis / JoyInfo[pid].scale) * JoyInfo[pid].scale) : raxis;
 | |
| 
 | |
| #ifdef SDL_JDEADZONE
 | |
| 		if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE)
 | |
| 			raxis = 0;
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	return raxis;
 | |
| }
 | |
| 
 | |
| static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
 | |
| {
 | |
| #define FOCUSUNION static_cast<unsigned int>(mousefocus | (kbfocus << 1))
 | |
| 	static SDL_bool firsttimeonmouse = SDL_TRUE;
 | |
| 	static SDL_bool mousefocus = SDL_TRUE;
 | |
| 	static SDL_bool kbfocus = SDL_TRUE;
 | |
| 
 | |
| 	const unsigned int oldfocus = FOCUSUNION;
 | |
| 
 | |
| 	switch (evt.event)
 | |
| 	{
 | |
| 		case SDL_WINDOWEVENT_ENTER:
 | |
| 			mousefocus = SDL_TRUE;
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_LEAVE:
 | |
| 			mousefocus = SDL_FALSE;
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_FOCUS_GAINED:
 | |
| 			kbfocus = SDL_TRUE;
 | |
| 			mousefocus = SDL_TRUE;
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_FOCUS_LOST:
 | |
| 			kbfocus = SDL_FALSE;
 | |
| 			mousefocus = SDL_FALSE;
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_MAXIMIZED:
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_MOVED:
 | |
| 			window_x = evt.data1;
 | |
| 			window_y = evt.data2;
 | |
| 			break;
 | |
| 		case SDL_WINDOWEVENT_SIZE_CHANGED:
 | |
| 			vid.realwidth = evt.data1;
 | |
| 			vid.realheight = evt.data2;
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	if (FOCUSUNION == oldfocus) // No state change
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (mousefocus && kbfocus)
 | |
| 	{
 | |
| 		// Tell game we got focus back, resume music if necessary
 | |
| 		window_notinfocus = false;
 | |
| 
 | |
| 		S_SetMusicVolume();
 | |
| 
 | |
| 		if (!firsttimeonmouse)
 | |
| 		{
 | |
| 			if (cv_usemouse.value) I_StartupMouse();
 | |
| 		}
 | |
| 		//else firsttimeonmouse = SDL_FALSE;
 | |
| 
 | |
| 		if (USE_MOUSEINPUT && !IgnoreMouse())
 | |
| 			SDLdoGrabMouse();
 | |
| 	}
 | |
| 	else if (!mousefocus && !kbfocus)
 | |
| 	{
 | |
| 		// Tell game we lost focus, pause music
 | |
| 		window_notinfocus = true;
 | |
| 		if (!(cv_bgaudio.value & 1))
 | |
| 			I_SetMusicVolume(0);
 | |
| 		if (!(cv_bgaudio.value & 2))
 | |
| 			S_StopSounds();
 | |
| 
 | |
| 		if (!disable_mouse)
 | |
| 		{
 | |
| 			SDLforceUngrabMouse();
 | |
| 		}
 | |
| 		G_ResetAllDeviceGameKeyDown();
 | |
| 		G_ResetAllDeviceResponding();
 | |
| 
 | |
| 		if (MOUSE_MENU)
 | |
| 		{
 | |
| 			SDLdoUngrabMouse();
 | |
| 		}
 | |
| 	}
 | |
| #undef FOCUSUNION
 | |
| }
 | |
| 
 | |
| static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
 | |
| {
 | |
| 	event_t event;
 | |
| 
 | |
| 	event.device = 0;
 | |
| 
 | |
| 	if (type == SDL_KEYUP)
 | |
| 	{
 | |
| 		event.type = ev_keyup;
 | |
| 	}
 | |
| 	else if (type == SDL_KEYDOWN)
 | |
| 	{
 | |
| 		event.type = ev_keydown;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 	event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
 | |
| 	event.data2 = evt.repeat;
 | |
| 	if (event.data1) D_PostEvent(&event);
 | |
| }
 | |
| 
 | |
| static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
 | |
| {
 | |
| 	static boolean firstmove = true;
 | |
| 
 | |
| 	if (USE_MOUSEINPUT)
 | |
| 	{
 | |
| 		if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IgnoreMouse() && !firstmove))
 | |
| 		{
 | |
| 			SDLdoUngrabMouse();
 | |
| 			firstmove = false;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// If using relative mouse mode, don't post an event_t just now,
 | |
| 		// add on the offsets so we can make an overall event later.
 | |
| 		if (SDL_GetRelativeMouseMode())
 | |
| 		{
 | |
| 			if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window)
 | |
| 			{
 | |
| 				mousemovex +=  evt.xrel;
 | |
| 				mousemovey += -evt.yrel;
 | |
| 				SDL_SetWindowGrab(window, SDL_TRUE);
 | |
| 			}
 | |
| 			firstmove = false;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// If the event is from warping the pointer to middle
 | |
| 		// of the screen then ignore it.
 | |
| 		if ((evt.x == realwidth/2) && (evt.y == realheight/2))
 | |
| 		{
 | |
| 			firstmove = false;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Don't send an event_t if not in relative mouse mode anymore,
 | |
| 		// just grab and set relative mode
 | |
| 		// this fixes the stupid camera jerk on mouse entering bug
 | |
| 		// -- Monster Iestyn
 | |
| 		if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window)
 | |
| 		{
 | |
| 			SDLdoGrabMouse();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	firstmove = false;
 | |
| }
 | |
| 
 | |
| static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
 | |
| {
 | |
| 	event_t event;
 | |
| 
 | |
| 	SDL_memset(&event, 0, sizeof(event_t));
 | |
| 
 | |
| 	// Ignore the event if the mouse is not actually focused on the window.
 | |
| 	// This can happen if you used the mouse to restore keyboard focus;
 | |
| 	// this apparently makes a mouse button down event but not a mouse button up event,
 | |
| 	// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
 | |
| 	// -- Monster Iestyn (28/05/18)
 | |
| 	if (SDL_GetMouseFocus() != window || IgnoreMouse())
 | |
| 		return;
 | |
| 
 | |
| 	/// \todo inputEvent.button.which
 | |
| 	if (USE_MOUSEINPUT)
 | |
| 	{
 | |
| 		event.device = 0;
 | |
| 
 | |
| 		if (type == SDL_MOUSEBUTTONUP)
 | |
| 		{
 | |
| 			event.type = ev_keyup;
 | |
| 		}
 | |
| 		else if (type == SDL_MOUSEBUTTONDOWN)
 | |
| 		{
 | |
| 			event.type = ev_keydown;
 | |
| 		}
 | |
| 		else return;
 | |
| 		if (evt.button == SDL_BUTTON_MIDDLE)
 | |
| 			event.data1 = KEY_MOUSE1+2;
 | |
| 		else if (evt.button == SDL_BUTTON_RIGHT)
 | |
| 			event.data1 = KEY_MOUSE1+1;
 | |
| 		else if (evt.button == SDL_BUTTON_LEFT)
 | |
| 			event.data1 = KEY_MOUSE1;
 | |
| 		else if (evt.button == SDL_BUTTON_X1)
 | |
| 			event.data1 = KEY_MOUSE1+3;
 | |
| 		else if (evt.button == SDL_BUTTON_X2)
 | |
| 			event.data1 = KEY_MOUSE1+4;
 | |
| 		if (event.type == ev_keyup || event.type == ev_keydown)
 | |
| 		{
 | |
| 			D_PostEvent(&event);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
 | |
| {
 | |
| 	event_t event;
 | |
| 
 | |
| 	SDL_memset(&event, 0, sizeof(event_t));
 | |
| 
 | |
| 	event.device = 0;
 | |
| 
 | |
| 	if (evt.y > 0)
 | |
| 	{
 | |
| 		event.data1 = KEY_MOUSEWHEELUP;
 | |
| 		event.type = ev_keydown;
 | |
| 	}
 | |
| 	if (evt.y < 0)
 | |
| 	{
 | |
| 		event.data1 = KEY_MOUSEWHEELDOWN;
 | |
| 		event.type = ev_keydown;
 | |
| 	}
 | |
| 	if (evt.y == 0)
 | |
| 	{
 | |
| 		event.data1 = 0;
 | |
| 		event.type = ev_keyup;
 | |
| 	}
 | |
| 	if (event.type == ev_keyup || event.type == ev_keydown)
 | |
| 	{
 | |
| 		D_PostEvent(&event);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt)
 | |
| {
 | |
| 	event_t event;
 | |
| 	INT32 value;
 | |
| 
 | |
| 	event.type = ev_gamepad_axis;
 | |
| 
 | |
| 	event.device = 1 + evt.which;
 | |
| 	if (event.device == INT32_MAX)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	event.data1 = event.data2 = event.data3 = INT32_MAX;
 | |
| 
 | |
| 	//axis
 | |
| 	if (evt.axis > 2 * JOYAXISSETS)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	//vaule[sic]
 | |
| 	value = SDLJoyAxis(evt.value, evt.which);
 | |
| 
 | |
| 	if (evt.axis & 1)
 | |
| 	{
 | |
| 		event.data3 = value;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		event.data2 = value;
 | |
| 	}
 | |
| 
 | |
| 	event.data1 = evt.axis / 2;
 | |
| 
 | |
| 	D_PostEvent(&event);
 | |
| }
 | |
| 
 | |
| static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type)
 | |
| {
 | |
| 	event_t event;
 | |
| 
 | |
| 	event.device = 1 + evt.which;
 | |
| 
 | |
| 	if (event.device == INT32_MAX)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	event.data1 = KEY_JOY1;
 | |
| 	event.data2 = 0;
 | |
| 
 | |
| 	if (type == SDL_CONTROLLERBUTTONUP)
 | |
| 	{
 | |
| 		event.type = ev_keyup;
 | |
| 	}
 | |
| 	else if (type == SDL_CONTROLLERBUTTONDOWN)
 | |
| 	{
 | |
| 		event.type = ev_keydown;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (evt.button < JOYBUTTONS)
 | |
| 	{
 | |
| 		event.data1 += evt.button;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	SDLJoyRemap(&event);
 | |
| 
 | |
| 	if (event.type != ev_console)
 | |
| 	{
 | |
| 		D_PostEvent(&event);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void Impl_HandleControllerDeviceAddedEvent(SDL_ControllerDeviceEvent event)
 | |
| {
 | |
| 	// The game is always interested in controller events, even if they aren't internally assigned to a player.
 | |
| 	// Thus, we *always* open SDL controllers as they become available, to begin receiving their events.
 | |
| 
 | |
| 	SDL_GameController* controller = SDL_GameControllerOpen(event.which);
 | |
| 	if (controller == NULL)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
 | |
| 	SDL_JoystickID joystick_instance_id = SDL_JoystickInstanceID(joystick);
 | |
| 
 | |
| 	event_t engine_event {};
 | |
| 
 | |
| 	engine_event.type = ev_gamepad_device_added;
 | |
| 	engine_event.device = 1 + joystick_instance_id;
 | |
| 
 | |
| 	D_PostEvent(&engine_event);
 | |
| }
 | |
| 
 | |
| static void Impl_HandleControllerDeviceRemovedEvent(SDL_ControllerDeviceEvent event)
 | |
| {
 | |
| 	// SDL only posts Device Removed events for controllers that have actually been opened.
 | |
| 	// Thus, we don't need to filter out controllers that may not have opened successfully prior to this event.
 | |
| 	event_t engine_event {};
 | |
| 
 | |
| 	engine_event.type = ev_gamepad_device_removed;
 | |
| 	engine_event.device = 1 + event.which;
 | |
| 
 | |
| 	D_PostEvent(&engine_event);
 | |
| }
 | |
| 
 | |
| static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
 | |
| {
 | |
| 	switch (keycode)
 | |
| 	{
 | |
| 		case SDLK_TAB: return ImGuiKey_Tab;
 | |
| 		case SDLK_LEFT: return ImGuiKey_LeftArrow;
 | |
| 		case SDLK_RIGHT: return ImGuiKey_RightArrow;
 | |
| 		case SDLK_UP: return ImGuiKey_UpArrow;
 | |
| 		case SDLK_DOWN: return ImGuiKey_DownArrow;
 | |
| 		case SDLK_PAGEUP: return ImGuiKey_PageUp;
 | |
| 		case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
 | |
| 		case SDLK_HOME: return ImGuiKey_Home;
 | |
| 		case SDLK_END: return ImGuiKey_End;
 | |
| 		case SDLK_INSERT: return ImGuiKey_Insert;
 | |
| 		case SDLK_DELETE: return ImGuiKey_Delete;
 | |
| 		case SDLK_BACKSPACE: return ImGuiKey_Backspace;
 | |
| 		case SDLK_SPACE: return ImGuiKey_Space;
 | |
| 		case SDLK_RETURN: return ImGuiKey_Enter;
 | |
| 		case SDLK_ESCAPE: return ImGuiKey_Escape;
 | |
| 		case SDLK_QUOTE: return ImGuiKey_Apostrophe;
 | |
| 		case SDLK_COMMA: return ImGuiKey_Comma;
 | |
| 		case SDLK_MINUS: return ImGuiKey_Minus;
 | |
| 		case SDLK_PERIOD: return ImGuiKey_Period;
 | |
| 		case SDLK_SLASH: return ImGuiKey_Slash;
 | |
| 		case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
 | |
| 		case SDLK_EQUALS: return ImGuiKey_Equal;
 | |
| 		case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
 | |
| 		case SDLK_BACKSLASH: return ImGuiKey_Backslash;
 | |
| 		case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
 | |
| 		case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
 | |
| 		case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
 | |
| 		case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
 | |
| 		case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
 | |
| 		case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
 | |
| 		case SDLK_PAUSE: return ImGuiKey_Pause;
 | |
| 		case SDLK_KP_0: return ImGuiKey_Keypad0;
 | |
| 		case SDLK_KP_1: return ImGuiKey_Keypad1;
 | |
| 		case SDLK_KP_2: return ImGuiKey_Keypad2;
 | |
| 		case SDLK_KP_3: return ImGuiKey_Keypad3;
 | |
| 		case SDLK_KP_4: return ImGuiKey_Keypad4;
 | |
| 		case SDLK_KP_5: return ImGuiKey_Keypad5;
 | |
| 		case SDLK_KP_6: return ImGuiKey_Keypad6;
 | |
| 		case SDLK_KP_7: return ImGuiKey_Keypad7;
 | |
| 		case SDLK_KP_8: return ImGuiKey_Keypad8;
 | |
| 		case SDLK_KP_9: return ImGuiKey_Keypad9;
 | |
| 		case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal;
 | |
| 		case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide;
 | |
| 		case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
 | |
| 		case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract;
 | |
| 		case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
 | |
| 		case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
 | |
| 		case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
 | |
| 		case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
 | |
| 		case SDLK_LSHIFT: return ImGuiKey_LeftShift;
 | |
| 		case SDLK_LALT: return ImGuiKey_LeftAlt;
 | |
| 		case SDLK_LGUI: return ImGuiKey_LeftSuper;
 | |
| 		case SDLK_RCTRL: return ImGuiKey_RightCtrl;
 | |
| 		case SDLK_RSHIFT: return ImGuiKey_RightShift;
 | |
| 		case SDLK_RALT: return ImGuiKey_RightAlt;
 | |
| 		case SDLK_RGUI: return ImGuiKey_RightSuper;
 | |
| 		case SDLK_APPLICATION: return ImGuiKey_Menu;
 | |
| 		case SDLK_0: return ImGuiKey_0;
 | |
| 		case SDLK_1: return ImGuiKey_1;
 | |
| 		case SDLK_2: return ImGuiKey_2;
 | |
| 		case SDLK_3: return ImGuiKey_3;
 | |
| 		case SDLK_4: return ImGuiKey_4;
 | |
| 		case SDLK_5: return ImGuiKey_5;
 | |
| 		case SDLK_6: return ImGuiKey_6;
 | |
| 		case SDLK_7: return ImGuiKey_7;
 | |
| 		case SDLK_8: return ImGuiKey_8;
 | |
| 		case SDLK_9: return ImGuiKey_9;
 | |
| 		case SDLK_a: return ImGuiKey_A;
 | |
| 		case SDLK_b: return ImGuiKey_B;
 | |
| 		case SDLK_c: return ImGuiKey_C;
 | |
| 		case SDLK_d: return ImGuiKey_D;
 | |
| 		case SDLK_e: return ImGuiKey_E;
 | |
| 		case SDLK_f: return ImGuiKey_F;
 | |
| 		case SDLK_g: return ImGuiKey_G;
 | |
| 		case SDLK_h: return ImGuiKey_H;
 | |
| 		case SDLK_i: return ImGuiKey_I;
 | |
| 		case SDLK_j: return ImGuiKey_J;
 | |
| 		case SDLK_k: return ImGuiKey_K;
 | |
| 		case SDLK_l: return ImGuiKey_L;
 | |
| 		case SDLK_m: return ImGuiKey_M;
 | |
| 		case SDLK_n: return ImGuiKey_N;
 | |
| 		case SDLK_o: return ImGuiKey_O;
 | |
| 		case SDLK_p: return ImGuiKey_P;
 | |
| 		case SDLK_q: return ImGuiKey_Q;
 | |
| 		case SDLK_r: return ImGuiKey_R;
 | |
| 		case SDLK_s: return ImGuiKey_S;
 | |
| 		case SDLK_t: return ImGuiKey_T;
 | |
| 		case SDLK_u: return ImGuiKey_U;
 | |
| 		case SDLK_v: return ImGuiKey_V;
 | |
| 		case SDLK_w: return ImGuiKey_W;
 | |
| 		case SDLK_x: return ImGuiKey_X;
 | |
| 		case SDLK_y: return ImGuiKey_Y;
 | |
| 		case SDLK_z: return ImGuiKey_Z;
 | |
| 		case SDLK_F1: return ImGuiKey_F1;
 | |
| 		case SDLK_F2: return ImGuiKey_F2;
 | |
| 		case SDLK_F3: return ImGuiKey_F3;
 | |
| 		case SDLK_F4: return ImGuiKey_F4;
 | |
| 		case SDLK_F5: return ImGuiKey_F5;
 | |
| 		case SDLK_F6: return ImGuiKey_F6;
 | |
| 		case SDLK_F7: return ImGuiKey_F7;
 | |
| 		case SDLK_F8: return ImGuiKey_F8;
 | |
| 		case SDLK_F9: return ImGuiKey_F9;
 | |
| 		case SDLK_F10: return ImGuiKey_F10;
 | |
| 		case SDLK_F11: return ImGuiKey_F11;
 | |
| 		case SDLK_F12: return ImGuiKey_F12;
 | |
| 	}
 | |
| 	return ImGuiKey_None;
 | |
| }
 | |
| 
 | |
| static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
 | |
| {
 | |
| 	ImGuiIO& io = ImGui::GetIO();
 | |
| 	io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0);
 | |
| 	io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0);
 | |
| 	io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0);
 | |
| 	io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0);
 | |
| }
 | |
| 
 | |
| // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
 | |
| // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
 | |
| // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
 | |
| // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
 | |
| // If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
 | |
| bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
 | |
| {
 | |
| 	ImGuiIO& io = ImGui::GetIO();
 | |
| 
 | |
| 	switch (event->type)
 | |
| 	{
 | |
| 		case SDL_MOUSEMOTION:
 | |
| 		{
 | |
| 			io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y);
 | |
| 			return true;
 | |
| 		}
 | |
| 		case SDL_MOUSEWHEEL:
 | |
| 		{
 | |
| 			float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f;
 | |
| 			float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
 | |
| 			io.AddMouseWheelEvent(wheel_x, wheel_y);
 | |
| 			return true;
 | |
| 		}
 | |
| 		case SDL_MOUSEBUTTONDOWN:
 | |
| 		case SDL_MOUSEBUTTONUP:
 | |
| 		{
 | |
| 			int mouse_button = -1;
 | |
| 			if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
 | |
| 			if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
 | |
| 			if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
 | |
| 			if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
 | |
| 			if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
 | |
| 			if (mouse_button == -1)
 | |
| 				break;
 | |
| 			io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
 | |
| 			// bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
 | |
| 			return true;
 | |
| 		}
 | |
| 		case SDL_TEXTINPUT:
 | |
| 		{
 | |
| 			io.AddInputCharactersUTF8(event->text.text);
 | |
| 			return true;
 | |
| 		}
 | |
| 		case SDL_KEYDOWN:
 | |
| 		case SDL_KEYUP:
 | |
| 		{
 | |
| 			ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
 | |
| 			ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym);
 | |
| 			io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
 | |
| 			io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
 | |
| 			return true;
 | |
| 		}
 | |
| 		case SDL_WINDOWEVENT:
 | |
| 		{
 | |
| 			// - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
 | |
| 			// - However we won't get a correct LEAVE event for a captured window.
 | |
| 			// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
 | |
| 			//   causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
 | |
| 			//   we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
 | |
| 			Uint8 window_event = event->window.event;
 | |
| 			if (window_event == SDL_WINDOWEVENT_ENTER)
 | |
| 				(void)0;
 | |
| 				// bd->PendingMouseLeaveFrame = 0;
 | |
| 			if (window_event == SDL_WINDOWEVENT_LEAVE)
 | |
| 				(void)0;
 | |
| 				// bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
 | |
| 			if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
 | |
| 				io.AddFocusEvent(true);
 | |
| 			else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
 | |
| 				io.AddFocusEvent(false);
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| void I_GetEvent(void)
 | |
| {
 | |
| 	SDL_Event evt;
 | |
| 
 | |
| 	// We only want the first motion event,
 | |
| 	// otherwise we'll end up catching the warp back to center.
 | |
| 	//int mouseMotionOnce = 0;
 | |
| 
 | |
| 	if (!graphics_started)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	mousemovex = mousemovey = 0;
 | |
| 
 | |
| 	ImGuiIO& io = ImGui::GetIO();
 | |
| 
 | |
| 	while (SDL_PollEvent(&evt))
 | |
| 	{
 | |
| 		ImGui_ImplSDL2_ProcessEvent(&evt);
 | |
| 		if (io.WantCaptureMouse || io.WantCaptureKeyboard)
 | |
| 		{
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		switch (evt.type)
 | |
| 		{
 | |
| 			case SDL_WINDOWEVENT:
 | |
| 				Impl_HandleWindowEvent(evt.window);
 | |
| 				break;
 | |
| 			case SDL_KEYUP:
 | |
| 			case SDL_KEYDOWN:
 | |
| 				Impl_HandleKeyboardEvent(evt.key, evt.type);
 | |
| 				break;
 | |
| 			case SDL_MOUSEMOTION:
 | |
| 				//if (!mouseMotionOnce)
 | |
| 				Impl_HandleMouseMotionEvent(evt.motion);
 | |
| 				//mouseMotionOnce = 1;
 | |
| 				break;
 | |
| 			case SDL_MOUSEBUTTONUP:
 | |
| 			case SDL_MOUSEBUTTONDOWN:
 | |
| 				Impl_HandleMouseButtonEvent(evt.button, evt.type);
 | |
| 				break;
 | |
| 			case SDL_MOUSEWHEEL:
 | |
| 				Impl_HandleMouseWheelEvent(evt.wheel);
 | |
| 				break;
 | |
| 			case SDL_CONTROLLERAXISMOTION:
 | |
| 				Impl_HandleControllerAxisEvent(evt.caxis);
 | |
| 				break;
 | |
| 			case SDL_CONTROLLERBUTTONUP:
 | |
| 			case SDL_CONTROLLERBUTTONDOWN:
 | |
| 				Impl_HandleControllerButtonEvent(evt.cbutton, evt.type);
 | |
| 				break;
 | |
| 
 | |
| 			case SDL_CONTROLLERDEVICEADDED:
 | |
| 				Impl_HandleControllerDeviceAddedEvent(evt.cdevice);
 | |
| 				break;
 | |
| 
 | |
| 			case SDL_CONTROLLERDEVICEREMOVED:
 | |
| 				Impl_HandleControllerDeviceRemovedEvent(evt.cdevice);
 | |
| 				break;
 | |
| 
 | |
| 			case SDL_QUIT:
 | |
| 				LUA_HookBool(true, HOOK(GameQuit));
 | |
| 				I_Quit();
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Send all relative mouse movement as one single mouse event.
 | |
| 	if (mousemovex || mousemovey)
 | |
| 	{
 | |
| 		event_t event;
 | |
| 		int wwidth, wheight;
 | |
| 		SDL_GetWindowSize(window, &wwidth, &wheight);
 | |
| 		//SDL_memset(&event, 0, sizeof(event_t));
 | |
| 		event.type = ev_mouse;
 | |
| 		event.data1 = 0;
 | |
| 		event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
 | |
| 		event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
 | |
| 		D_PostEvent(&event);
 | |
| 	}
 | |
| 
 | |
| 	// In order to make wheels act like buttons, we have to set their state to Up.
 | |
| 	// This is because wheel messages don't have an up/down state.
 | |
| 	G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELDOWN] = G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELUP] = 0;
 | |
| }
 | |
| 
 | |
| static void half_warp_mouse(uint16_t x, uint16_t y) {
 | |
| 	if (wrapmouseok)
 | |
| 	{
 | |
| 		SDL_WarpMouseInWindow(window, (Uint16)(x/2),(Uint16)(y/2));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void I_StartupMouse(void)
 | |
| {
 | |
| 	static SDL_bool firsttimeonmouse = SDL_TRUE;
 | |
| 
 | |
| 	if (disable_mouse)
 | |
| 		return;
 | |
| 
 | |
| 	if (!firsttimeonmouse)
 | |
| 	{
 | |
| 		half_warp_mouse(realwidth, realheight); // warp to center
 | |
| 	}
 | |
| 	else
 | |
| 		firsttimeonmouse = SDL_FALSE;
 | |
| 	if (cv_usemouse.value && !IgnoreMouse())
 | |
| 		SDLdoGrabMouse();
 | |
| 	else
 | |
| 		SDLdoUngrabMouse();
 | |
| }
 | |
| 
 | |
| //
 | |
| // I_OsPolling
 | |
| //
 | |
| void I_OsPolling(void)
 | |
| {
 | |
| 	SDL_Keymod mod;
 | |
| 
 | |
| 	if (consolevent)
 | |
| 		I_GetConsoleEvents();
 | |
| 
 | |
| 	if (SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER))
 | |
| 		SDL_GameControllerUpdate();
 | |
| 
 | |
| 	I_GetEvent();
 | |
| 
 | |
| 	mod = SDL_GetModState();
 | |
| 	/* Handle here so that our state is always synched with the system. */
 | |
| 	shiftdown = ctrldown = altdown = 0;
 | |
| 	capslock = false;
 | |
| 	if (mod & KMOD_LSHIFT) shiftdown |= 1;
 | |
| 	if (mod & KMOD_RSHIFT) shiftdown |= 2;
 | |
| 	if (mod & KMOD_LCTRL)   ctrldown |= 1;
 | |
| 	if (mod & KMOD_RCTRL)   ctrldown |= 2;
 | |
| 	if (mod & KMOD_LALT)     altdown |= 1;
 | |
| 	if (mod & KMOD_RALT)     altdown |= 2;
 | |
| 	if (mod & KMOD_CAPS) capslock = true;
 | |
| }
 | |
| 
 | |
| //
 | |
| // I_UpdateNoBlit
 | |
| //
 | |
| void I_UpdateNoBlit(void)
 | |
| {
 | |
| 	if (rendermode == render_none)
 | |
| 		return;
 | |
| 	if (exposevideo)
 | |
| 	{
 | |
| #ifdef HWRENDER
 | |
| 		if (rendermode == render_opengl)
 | |
| 		{
 | |
| 			OglSdlFinishUpdate(cv_vidwait.value);
 | |
| 		}
 | |
| #endif
 | |
| 	}
 | |
| 	exposevideo = SDL_FALSE;
 | |
| }
 | |
| 
 | |
| //
 | |
| // I_FinishUpdate
 | |
| //
 | |
| static SDL_Rect src_rect = { 0, 0, 0, 0 };
 | |
| 
 | |
| //
 | |
| // I_UpdateNoVsync
 | |
| //
 | |
| void I_UpdateNoVsync(void)
 | |
| {
 | |
| 	INT32 real_vidwait = cv_vidwait.value;
 | |
| 	cv_vidwait.value = 0;
 | |
| 	I_FinishUpdate();
 | |
| 	cv_vidwait.value = real_vidwait;
 | |
| }
 | |
| 
 | |
| //
 | |
| // I_ReadScreen
 | |
| //
 | |
| void I_ReadScreen(UINT8 *scr)
 | |
| {
 | |
| 	if (rendermode != render_soft)
 | |
| 		I_Error ("I_ReadScreen: called while in non-software mode");
 | |
| 	else
 | |
| 		VID_BlitLinearScreen(screens[0], scr,
 | |
| 			vid.width*vid.bpp, vid.height,
 | |
| 			vid.rowbytes, vid.rowbytes);
 | |
| }
 | |
| 
 | |
| //
 | |
| // I_SetPalette
 | |
| //
 | |
| void I_SetPalette(RGBA_t *palette)
 | |
| {
 | |
| 	size_t i;
 | |
| 	for (i=0; i<256; i++)
 | |
| 	{
 | |
| 		localPalette[i].r = palette[i].s.red;
 | |
| 		localPalette[i].g = palette[i].s.green;
 | |
| 		localPalette[i].b = palette[i].s.blue;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // return number of fullscreen + X11 modes
 | |
| INT32 VID_NumModes(void)
 | |
| {
 | |
| 	if (USE_FULLSCREEN && numVidModes != -1)
 | |
| 		return numVidModes - firstEntry;
 | |
| 	else
 | |
| 		return MAXWINMODES;
 | |
| }
 | |
| 
 | |
| const char *VID_GetModeName(INT32 modeNum)
 | |
| {
 | |
| #if 0
 | |
| 	if (USE_FULLSCREEN && numVidModes != -1) // fullscreen modes
 | |
| 	{
 | |
| 		modeNum += firstEntry;
 | |
| 		if (modeNum >= numVidModes)
 | |
| 			return NULL;
 | |
| 
 | |
| 		sprintf(&vidModeName[modeNum][0], "%dx%d",
 | |
| 			modeList[modeNum]->w,
 | |
| 			modeList[modeNum]->h);
 | |
| 	}
 | |
| 	else // windowed modes
 | |
| 	{
 | |
| #endif
 | |
| 	if (modeNum == -1)
 | |
| 	{
 | |
| 		return fallback_resolution_name;
 | |
| 	}
 | |
| 		if (modeNum > MAXWINMODES)
 | |
| 			return NULL;
 | |
| 
 | |
| 		sprintf(&vidModeName[modeNum][0], "%dx%d",
 | |
| 			windowedModes[modeNum][0],
 | |
| 			windowedModes[modeNum][1]);
 | |
| 	//}
 | |
| 	return &vidModeName[modeNum][0];
 | |
| }
 | |
| 
 | |
| INT32 VID_GetModeForSize(INT32 w, INT32 h)
 | |
| {
 | |
| 	int i;
 | |
| 	for (i = 0; i < MAXWINMODES; i++)
 | |
| 	{
 | |
| 		if (windowedModes[i][0] == w && windowedModes[i][1] == h)
 | |
| 		{
 | |
| 			return i;
 | |
| 		}
 | |
| 	}
 | |
| 	return -1;
 | |
| #if 0
 | |
| 	INT32 matchMode = -1, i;
 | |
| 	VID_PrepareModeList();
 | |
| 	if (USE_FULLSCREEN && numVidModes != -1)
 | |
| 	{
 | |
| 		for (i=firstEntry; i<numVidModes; i++)
 | |
| 		{
 | |
| 			if (modeList[i]->w == w &&
 | |
| 			    modeList[i]->h == h)
 | |
| 			{
 | |
| 				matchMode = i;
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 		if (-1 == matchMode) // use smaller mode
 | |
| 		{
 | |
| 			w -= w%BASEVIDWIDTH;
 | |
| 			h -= h%BASEVIDHEIGHT;
 | |
| 			for (i=firstEntry; i<numVidModes; i++)
 | |
| 			{
 | |
| 				if (modeList[i]->w == w &&
 | |
| 				    modeList[i]->h == h)
 | |
| 				{
 | |
| 					matchMode = i;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 			if (-1 == matchMode) // use smallest mode
 | |
| 				matchMode = numVidModes-1;
 | |
| 		}
 | |
| 		matchMode -= firstEntry;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for (i=0; i<MAXWINMODES; i++)
 | |
| 		{
 | |
| 			if (windowedModes[i][0] == w &&
 | |
| 			    windowedModes[i][1] == h)
 | |
| 			{
 | |
| 				matchMode = i;
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 		if (-1 == matchMode) // use smaller mode
 | |
| 		{
 | |
| 			w -= w%BASEVIDWIDTH;
 | |
| 			h -= h%BASEVIDHEIGHT;
 | |
| 			for (i=0; i<MAXWINMODES; i++)
 | |
| 			{
 | |
| 				if (windowedModes[i][0] == w &&
 | |
| 				    windowedModes[i][1] == h)
 | |
| 				{
 | |
| 					matchMode = i;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 			if (-1 == matchMode) // use smallest mode
 | |
| 				matchMode = MAXWINMODES-1;
 | |
| 		}
 | |
| 	}
 | |
| 	return matchMode;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void VID_PrepareModeList(void)
 | |
| {
 | |
| 	// Under SDL2, we just use the windowed modes list, and scale in windowed fullscreen.
 | |
| 	allow_fullscreen = true;
 | |
| #if 0
 | |
| 	INT32 i;
 | |
| 
 | |
| 	firstEntry = 0;
 | |
| 
 | |
| #ifdef HWRENDER
 | |
| 	if (rendermode == render_opengl)
 | |
| 		modeList = SDL_ListModes(NULL, SDL_OPENGL|SDL_FULLSCREEN);
 | |
| 	else
 | |
| #endif
 | |
| 	modeList = SDL_ListModes(NULL, surfaceFlagsF|SDL_HWSURFACE); //Alam: At least hardware surface
 | |
| 
 | |
| 	if (disable_fullscreen?0:cv_fullscreen.value) // only fullscreen needs preparation
 | |
| 	{
 | |
| 		if (-1 != numVidModes)
 | |
| 		{
 | |
| 			for (i=0; i<numVidModes; i++)
 | |
| 			{
 | |
| 				if (modeList[i]->w <= MAXVIDWIDTH &&
 | |
| 					modeList[i]->h <= MAXVIDHEIGHT)
 | |
| 				{
 | |
| 					firstEntry = i;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	allow_fullscreen = true;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void init_imgui()
 | |
| {
 | |
| 	if (ImGui::GetCurrentContext() != NULL)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	ImGui::CreateContext();
 | |
|     ImGuiIO& io = ImGui::GetIO(); (void)io;
 | |
| 	io.IniFilename = NULL;
 | |
| 	io.BackendFlags = 0;
 | |
| 	io.BackendRendererName = "SRB2 SDL 2 RHI";
 | |
| 	io.Fonts->AddFontDefault();
 | |
| 	{
 | |
| 		unsigned char* pixels;
 | |
| 		int width;
 | |
| 		int height;
 | |
| 		io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
 | |
| 	}
 | |
| 	ImGui::StyleColorsDark();
 | |
| }
 | |
| 
 | |
| static SDL_bool Impl_CreateContext(void)
 | |
| {
 | |
| #ifdef HWRENDER
 | |
| 	if (rendermode == render_opengl)
 | |
| 	{
 | |
| 		if (!g_legacy_gl_context)
 | |
| 		{
 | |
| 			SDL_GL_ResetAttributes();
 | |
| 			g_legacy_gl_context = SDL_GL_CreateContext(window);
 | |
| 		}
 | |
| 		if (g_legacy_gl_context == NULL)
 | |
| 		{
 | |
| 			SDL_DestroyWindow(window);
 | |
| 			I_Error("Failed to create a Legacy GL context: %s\n", SDL_GetError());
 | |
| 		}
 | |
| 		init_imgui();
 | |
| 		SDL_GL_MakeCurrent(window, g_legacy_gl_context);
 | |
| 		return SDL_TRUE;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	// RHI always uses OpenGL 2.0 (for now)
 | |
| 
 | |
| 	if (!sdlglcontext)
 | |
| 	{
 | |
| 		SDL_GL_ResetAttributes();
 | |
| 		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
 | |
| 		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
 | |
| 		sdlglcontext = SDL_GL_CreateContext(window);
 | |
| 	}
 | |
| 	if (sdlglcontext == NULL)
 | |
| 	{
 | |
| 		SDL_DestroyWindow(window);
 | |
| 		I_Error("Failed to create an RHI GL context: %s\n", SDL_GetError());
 | |
| 	}
 | |
| 	init_imgui();
 | |
| 	SDL_GL_MakeCurrent(window, sdlglcontext);
 | |
| 
 | |
| 	if (!g_rhi)
 | |
| 	{
 | |
| 		std::unique_ptr<rhi::SdlGl2Platform> platform = std::make_unique<rhi::SdlGl2Platform>();
 | |
| 		platform->window = window;
 | |
| 		g_rhi = std::make_unique<rhi::Gl2Rhi>(std::move(platform), reinterpret_cast<rhi::GlLoadFunc>(SDL_GL_GetProcAddress));
 | |
| 		g_rhi_generation += 1;
 | |
| 	}
 | |
| 
 | |
| 	return SDL_TRUE;
 | |
| }
 | |
| 
 | |
| void VID_CheckGLLoaded(rendermode_t oldrender)
 | |
| {
 | |
| 	(void)oldrender;
 | |
| }
 | |
| 
 | |
| boolean VID_CheckRenderer(void)
 | |
| {
 | |
| 	boolean rendererchanged = false;
 | |
| 
 | |
| 	if (dedicated)
 | |
| 		return false;
 | |
| 
 | |
| 	if (setrenderneeded)
 | |
| 	{
 | |
| 		rendermode = static_cast<rendermode_t>(setrenderneeded);
 | |
| 		rendererchanged = true;
 | |
| 
 | |
| 		if (rendererchanged)
 | |
| 		{
 | |
| 			Impl_CreateContext();
 | |
| #ifdef HWRENDER
 | |
| 			if (rendermode == render_opengl)
 | |
| 			{
 | |
| 				VID_StartupOpenGL();
 | |
| 				if (vid.glstate != VID_GL_LIBRARY_LOADED)
 | |
| 				{
 | |
| 					rendererchanged = false;
 | |
| 				}
 | |
| 			}
 | |
| #endif
 | |
| 		}
 | |
| 
 | |
| 		setrenderneeded = 0;
 | |
| 	}
 | |
| 
 | |
| 	SDLSetMode(vid.width, vid.height, static_cast<SDL_bool>(USE_FULLSCREEN), (setmodeneeded ? SDL_TRUE : SDL_FALSE));
 | |
| 	Impl_VideoSetupBuffer();
 | |
| 
 | |
| 	if (rendermode == render_soft)
 | |
| 	{
 | |
| 		SCR_SetDrawFuncs();
 | |
| 	}
 | |
| #ifdef HWRENDER
 | |
| 	else if (rendermode == render_opengl && rendererchanged)
 | |
| 	{
 | |
| 		HWR_Switch();
 | |
| 		V_SetPalette(0);
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	M_RefreshAdvancedVideoOptions();
 | |
| 
 | |
| 	return rendererchanged;
 | |
| }
 | |
| 
 | |
| static UINT32 refresh_rate;
 | |
| static UINT32 VID_GetRefreshRate(void)
 | |
| {
 | |
| 	int index = SDL_GetWindowDisplayIndex(window);
 | |
| 	SDL_DisplayMode m;
 | |
| 
 | |
| 	if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
 | |
| 	{
 | |
| 		// Video not init yet.
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	if (SDL_GetCurrentDisplayMode(index, &m) != 0)
 | |
| 	{
 | |
| 		// Error has occurred.
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return m.refresh_rate;
 | |
| }
 | |
| 
 | |
| INT32 VID_SetMode(INT32 modeNum)
 | |
| {
 | |
| 	SDLdoUngrabMouse();
 | |
| 
 | |
| 	vid.recalc = 1;
 | |
| 	vid.bpp = 1;
 | |
| 
 | |
| 	if (modeNum < 0)
 | |
| 		modeNum = 0;
 | |
| 	if (modeNum >= MAXWINMODES)
 | |
| 		modeNum = MAXWINMODES-1;
 | |
| 
 | |
| 	vid.width = windowedModes[modeNum][0];
 | |
| 	vid.height = windowedModes[modeNum][1];
 | |
| 	vid.realwidth = vid.width;
 | |
| 	vid.realheight = vid.height;
 | |
| 	vid.modenum = modeNum;
 | |
| 
 | |
| 	src_rect.w = vid.width;
 | |
| 	src_rect.h = vid.height;
 | |
| 
 | |
| 	refresh_rate = VID_GetRefreshRate();
 | |
| 
 | |
| 	VID_CheckRenderer();
 | |
| 	return SDL_TRUE;
 | |
| }
 | |
| 
 | |
| static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 | |
| {
 | |
| 	uint32_t flags = SDL_WINDOW_RESIZABLE;
 | |
| 
 | |
| 	if (rendermode == render_none) // dedicated
 | |
| 		return SDL_TRUE; // Monster Iestyn -- not sure if it really matters what we return here tbh
 | |
| 
 | |
| 	if (window != NULL)
 | |
| 		return SDL_FALSE;
 | |
| 
 | |
| 	if (fullscreen)
 | |
| 		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
 | |
| 
 | |
| 	if (borderlesswindow)
 | |
| 		flags |= SDL_WINDOW_BORDERLESS;
 | |
| 
 | |
| 	// RHI: always create window as OPENGL
 | |
| 	flags |= SDL_WINDOW_OPENGL;
 | |
| 
 | |
| 	// Create a window
 | |
| 	window = SDL_CreateWindow("Dr. Robotnik's Ring Racers " VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 | |
| 			realwidth, realheight, flags);
 | |
| 
 | |
| 	if (window == NULL)
 | |
| 	{
 | |
| 		CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError());
 | |
| 		return SDL_FALSE;
 | |
| 	}
 | |
| 
 | |
| 	Impl_SetWindowIcon();
 | |
| 
 | |
| 	return Impl_CreateContext();
 | |
| }
 | |
| 
 | |
| static void Impl_SetWindowIcon(void)
 | |
| {
 | |
| 	if (window && icoSurface)
 | |
| 		SDL_SetWindowIcon(window, icoSurface);
 | |
| }
 | |
| 
 | |
| static void Impl_VideoSetupBuffer(void)
 | |
| {
 | |
| 	// Set up game's software render buffer
 | |
| 	vid.rowbytes = vid.width * vid.bpp;
 | |
| 	vid.direct = NULL;
 | |
| 	if (vid.buffer)
 | |
| 		free(vid.buffer);
 | |
| 	vid.buffer = static_cast<uint8_t*>(calloc(vid.rowbytes*vid.height, NUMSCREENS));
 | |
| 	if (!vid.buffer)
 | |
| 	{
 | |
| 		I_Error("%s", M_GetText("Not enough memory for video buffer\n"));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void I_StartupGraphics(void)
 | |
| {
 | |
| 	if (dedicated)
 | |
| 	{
 | |
| 		rendermode = render_none;
 | |
| 		return;
 | |
| 	}
 | |
| 	if (graphics_started)
 | |
| 		return;
 | |
| 
 | |
| 	COM_AddCommand ("vid_nummodes", VID_Command_NumModes_f);
 | |
| 	COM_AddCommand ("vid_info", VID_Command_Info_f);
 | |
| 	COM_AddCommand ("vid_modelist", VID_Command_ModeList_f);
 | |
| 	COM_AddCommand ("vid_mode", VID_Command_Mode_f);
 | |
| 	{
 | |
| 		extern CVarList *cvlist_graphics_driver;
 | |
| 		CV_RegisterList(cvlist_graphics_driver);
 | |
| 	}
 | |
| 	disable_mouse = static_cast<SDL_bool>(M_CheckParm("-nomouse"));
 | |
| 	disable_fullscreen = M_CheckParm("-win") ? SDL_TRUE : SDL_FALSE;
 | |
| 
 | |
| 	keyboard_started = true;
 | |
| 
 | |
| #if !defined(HAVE_TTF)
 | |
| 	// Previously audio was init here for questionable reasons?
 | |
| 	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
 | |
| 	{
 | |
| 		CONS_Printf(M_GetText("Couldn't initialize SDL's Video System: %s\n"), SDL_GetError());
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	// Renderer choices
 | |
| 	// Takes priority over the config.
 | |
| 	if (M_CheckParm("-renderer"))
 | |
| 	{
 | |
| 		INT32 i = 0;
 | |
| 		CV_PossibleValue_t *renderer_list = cv_renderer_t;
 | |
| 		const char *modeparm = M_GetNextParm();
 | |
| 		while (renderer_list[i].strvalue)
 | |
| 		{
 | |
| 			if (!stricmp(modeparm, renderer_list[i].strvalue))
 | |
| 			{
 | |
| 				chosenrendermode = static_cast<rendermode_t>(renderer_list[i].value);
 | |
| 				break;
 | |
| 			}
 | |
| 			i++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Choose Software renderer
 | |
| 	else if (M_CheckParm("-software"))
 | |
| 		chosenrendermode = render_soft;
 | |
| 
 | |
| #ifdef HWRENDER
 | |
| 	// Choose OpenGL renderer
 | |
| 	else if (M_CheckParm("-opengl"))
 | |
| 		chosenrendermode = render_opengl;
 | |
| 
 | |
| 	// Don't startup OpenGL
 | |
| 	if (M_CheckParm("-nogl"))
 | |
| 	{
 | |
| 		vid.glstate = VID_GL_LIBRARY_ERROR;
 | |
| 		if (chosenrendermode == render_opengl)
 | |
| 			chosenrendermode = render_none;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	if (chosenrendermode != render_none)
 | |
| 		rendermode = chosenrendermode;
 | |
| 
 | |
| 	borderlesswindow = M_CheckParm("-borderless") ? SDL_TRUE : SDL_FALSE;
 | |
| 
 | |
| 	VID_Command_ModeList_f();
 | |
| 
 | |
| #ifdef HWRENDER
 | |
| 	if (rendermode == render_opengl)
 | |
| 		VID_StartupOpenGL();
 | |
| #endif
 | |
| 
 | |
| 	// Window icon
 | |
| #ifdef HAVE_IMAGE
 | |
| 	icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm);
 | |
| #endif
 | |
| 
 | |
| 	VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT));
 | |
| 
 | |
| 	vid.width = BASEVIDWIDTH; // Default size for startup
 | |
| 	vid.height = BASEVIDHEIGHT; // BitsPerPixel is the SDL interface's
 | |
| 	vid.recalc = true; // Set up the console stufff
 | |
| 	vid.direct = NULL; // Maybe direct access?
 | |
| 	vid.bpp = 1; // This is the game engine's Bpp
 | |
| 	vid.WndParent = NULL; //For the window?
 | |
| 
 | |
| 	VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT));
 | |
| 
 | |
| 	if (M_CheckParm("-nomousegrab"))
 | |
| 		mousegrabok = SDL_FALSE;
 | |
| 	realwidth = (Uint16)vid.width;
 | |
| 	realheight = (Uint16)vid.height;
 | |
| 
 | |
| 	VID_Command_Info_f();
 | |
| 	SDLdoUngrabMouse();
 | |
| 
 | |
| 	SDL_RaiseWindow(window);
 | |
| 
 | |
| 	if (mousegrabok && !disable_mouse)
 | |
| 		SDLdoGrabMouse();
 | |
| 
 | |
| 	graphics_started = true;
 | |
| }
 | |
| 
 | |
| void VID_StartupOpenGL(void)
 | |
| {
 | |
| #ifdef HWRENDER
 | |
| 	static boolean glstartup = false;
 | |
| 	if (!glstartup)
 | |
| 	{
 | |
| 		CONS_Printf("VID_StartupOpenGL()...\n");
 | |
| 		*(void**)&HWD.pfnInit             = hwSym("Init",NULL);
 | |
| 		*(void**)&HWD.pfnFinishUpdate     = NULL;
 | |
| 		*(void**)&HWD.pfnDraw2DLine       = hwSym("Draw2DLine",NULL);
 | |
| 		*(void**)&HWD.pfnDrawPolygon      = hwSym("DrawPolygon",NULL);
 | |
| 		*(void**)&HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL);
 | |
| 		*(void**)&HWD.pfnRenderSkyDome    = hwSym("RenderSkyDome",NULL);
 | |
| 		*(void**)&HWD.pfnSetBlend         = hwSym("SetBlend",NULL);
 | |
| 		*(void**)&HWD.pfnClearBuffer      = hwSym("ClearBuffer",NULL);
 | |
| 		*(void**)&HWD.pfnSetTexture       = hwSym("SetTexture",NULL);
 | |
| 		*(void**)&HWD.pfnUpdateTexture    = hwSym("UpdateTexture",NULL);
 | |
| 		*(void**)&HWD.pfnDeleteTexture    = hwSym("DeleteTexture",NULL);
 | |
| 		*(void**)&HWD.pfnReadRect         = hwSym("ReadRect",NULL);
 | |
| 		*(void**)&HWD.pfnGClipRect        = hwSym("GClipRect",NULL);
 | |
| 		*(void**)&HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
 | |
| 		*(void**)&HWD.pfnSetSpecialState  = hwSym("SetSpecialState",NULL);
 | |
| 		*(void**)&HWD.pfnSetPalette       = hwSym("SetPalette",NULL);
 | |
| 		*(void**)&HWD.pfnGetTextureUsed   = hwSym("GetTextureUsed",NULL);
 | |
| 		*(void**)&HWD.pfnDrawModel        = hwSym("DrawModel",NULL);
 | |
| 		*(void**)&HWD.pfnCreateModelVBOs  = hwSym("CreateModelVBOs",NULL);
 | |
| 		*(void**)&HWD.pfnSetTransform     = hwSym("SetTransform",NULL);
 | |
| 		*(void**)&HWD.pfnPostImgRedraw    = hwSym("PostImgRedraw",NULL);
 | |
| 		*(void**)&HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
 | |
| 		*(void**)&HWD.pfnStartScreenWipe  = hwSym("StartScreenWipe",NULL);
 | |
| 		*(void**)&HWD.pfnEndScreenWipe    = hwSym("EndScreenWipe",NULL);
 | |
| 		*(void**)&HWD.pfnDoScreenWipe     = hwSym("DoScreenWipe",NULL);
 | |
| 		*(void**)&HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
 | |
| 		*(void**)&HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
 | |
| 		*(void**)&HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
 | |
| 		*(void**)&HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
 | |
| 
 | |
| 		*(void**)&HWD.pfnCompileShaders   = hwSym("CompileShaders",NULL);
 | |
| 		*(void**)&HWD.pfnCleanShaders     = hwSym("CleanShaders",NULL);
 | |
| 		*(void**)&HWD.pfnSetShader        = hwSym("SetShader",NULL);
 | |
| 		*(void**)&HWD.pfnUnSetShader      = hwSym("UnSetShader",NULL);
 | |
| 
 | |
| 		*(void**)&HWD.pfnSetShaderInfo    = hwSym("SetShaderInfo",NULL);
 | |
| 		*(void**)&HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
 | |
| 		glstartup = true;
 | |
| 	}
 | |
| 
 | |
| 	// For RHI-Legacy GL compatibility: Init always fetches GL functions, but only dlsym's libraries once.
 | |
| 	vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library
 | |
| 
 | |
| 	if (vid.glstate == VID_GL_LIBRARY_ERROR)
 | |
| 	{
 | |
| 		rendermode = render_soft;
 | |
| 		setrenderneeded = 0;
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void I_ShutdownGraphics(void)
 | |
| {
 | |
| 	rendermode = render_none;
 | |
| 	if (icoSurface) SDL_FreeSurface(icoSurface);
 | |
| 	icoSurface = NULL;
 | |
| 
 | |
| 	I_OutputMsg("I_ShutdownGraphics(): ");
 | |
| 
 | |
| 	// was graphics initialized anyway?
 | |
| 	if (!graphics_started)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 	graphics_started = false;
 | |
| 
 | |
| #ifdef HWRENDER
 | |
| 	if (GLUhandle)
 | |
| 		hwClose(GLUhandle);
 | |
| 	if (sdlglcontext)
 | |
| 	{
 | |
| 		SDL_GL_DeleteContext(sdlglcontext);
 | |
| 	}
 | |
| #endif
 | |
| 	SDL_QuitSubSystem(SDL_INIT_VIDEO);
 | |
| 	framebuffer = SDL_FALSE;
 | |
| }
 | |
| 
 | |
| rhi::Rhi* srb2::sys::get_rhi(rhi::Handle<rhi::Rhi> handle)
 | |
| {
 | |
| 	// TODO actually use handle...
 | |
| 	return g_rhi.get();
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| UINT32 I_GetRefreshRate(void)
 | |
| {
 | |
| 	// Moved to VID_GetRefreshRate.
 | |
| 	// Precalculating it like that won't work as
 | |
| 	// well for windowed mode since you can drag
 | |
| 	// the window around, but very slow PCs might have
 | |
| 	// trouble querying mode over and over again.
 | |
| 	return refresh_rate;
 | |
| }
 | |
| 
 | |
| namespace srb2::cvarhandler
 | |
| {
 | |
| void on_set_vid_wait();
 | |
| }
 | |
| 
 | |
| void srb2::cvarhandler::on_set_vid_wait()
 | |
| {
 | |
| 	int interval = 0;
 | |
| 	if (cv_vidwait.value > 0)
 | |
| 	{
 | |
| 		interval = 1;
 | |
| 	}
 | |
| 
 | |
| 	switch (rendermode)
 | |
| 	{
 | |
| 	case render_soft:
 | |
| 		if (sdlglcontext == nullptr || SDL_GL_GetCurrentContext() != sdlglcontext)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		SDL_GL_SetSwapInterval(interval);
 | |
| 		break;
 | |
| #ifdef HWRENDER
 | |
| 	case render_opengl:
 | |
| 		if (g_legacy_gl_context == nullptr || SDL_GL_GetCurrentContext() != g_legacy_gl_context)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		SDL_GL_SetSwapInterval(interval);
 | |
| #endif
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| }
 |