mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-04-01 07:20:42 +00:00
Merge branch 'SDL3'
This commit is contained in:
commit
c142dac6f7
25 changed files with 1080 additions and 298 deletions
|
@ -46,17 +46,19 @@ set(DHEWM3BINARY "dhewm3")
|
|||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(GNUInstallDirs OPTIONAL RESULT_VARIABLE GNUINSTALLDIRS)
|
||||
include(TestBigEndian)
|
||||
|
||||
option(CORE "Build the core" ON)
|
||||
option(BASE "Build the base game code" ON)
|
||||
option(D3XP "Build the d3xp game code" ON)
|
||||
if(MSVC)
|
||||
option(TOOLS "Build the tools game code (Visual Studio+SDL2 only)" OFF)
|
||||
option(TOOLS "Build the tools game code (Visual Studio+SDL2/SDL3 only)" OFF)
|
||||
endif()
|
||||
option(DEDICATED "Build the dedicated server" OFF)
|
||||
option(ONATIVE "Optimize for the host CPU" OFF)
|
||||
option(SDL2 "Use SDL2 instead of SDL1.2" ON)
|
||||
option(IMGUI "Build with Dear ImGui integration - requires SDL2 and C++11" ON)
|
||||
option(SDL3 "Use SDL3 instead of SDL2 or SDL1.2" OFF)
|
||||
option(IMGUI "Build with Dear ImGui integration - requires SDL2/SDL3 and C++11" ON)
|
||||
option(REPRODUCIBLE_BUILD "Replace __DATE__ and __TIME__ by hardcoded values for reproducible builds" OFF)
|
||||
|
||||
option(HARDLINK_GAME "Compile gamecode into executable (no game DLLs)" OFF)
|
||||
|
@ -193,7 +195,19 @@ endif()
|
|||
find_package(OpenAL REQUIRED)
|
||||
include_directories(${OPENAL_INCLUDE_DIR})
|
||||
|
||||
if (SDL2)
|
||||
if (SDL3)
|
||||
if(SDL2)
|
||||
message(WARNING "You enabled both SDL2 and SDL3. Only one can be used at a time, disabling SDL2")
|
||||
set(SDL2 OFF CACHE BOOL "Use SDL2 (make sure SDL3 is disabled!)" FORCE)
|
||||
endif()
|
||||
# 1. Look for a SDL3 package,
|
||||
# 2. look for the SDL3-shared component, and
|
||||
# 3. fail if the shared component cannot be found.
|
||||
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared)
|
||||
# TODO: include dirs?
|
||||
set(SDLx_LIBRARY SDL3::SDL3)
|
||||
add_definitions(-DD3_SDL3=1)
|
||||
elseif (SDL2)
|
||||
# skip SDL2main
|
||||
if(APPLE OR WIN32)
|
||||
set(SDL2_BUILDING_LIBRARY TRUE)
|
||||
|
@ -217,12 +231,12 @@ if(REPRODUCIBLE_BUILD)
|
|||
endif()
|
||||
|
||||
if(IMGUI)
|
||||
if(SDL2)
|
||||
if(SDL2 OR SDL3)
|
||||
# we need C++11 for ImGui
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
message(STATUS "Dear ImGui integration enabled")
|
||||
else()
|
||||
message(WARNING "Disabling IMGUI because SDL1.2 is used - it needs SDL2!")
|
||||
message(WARNING "Disabling IMGUI because SDL1.2 is used - it needs SDL2 or SDL3!")
|
||||
set(IMGUI OFF)
|
||||
add_definitions(-DIMGUI_DISABLE)
|
||||
endif()
|
||||
|
@ -273,7 +287,7 @@ if(NOT WIN32)
|
|||
endif()
|
||||
|
||||
# check if our SDL2 supports X11 in SDL_syswm so we can use it for DPI scaling ImGui
|
||||
if(SDL2)
|
||||
if(SDL2) # TODO: SDL3? Or just kick this feature?
|
||||
set(CMAKE_REQUIRED_LIBRARIES SDL2)
|
||||
check_c_source_compiles( "#include <SDL_syswm.h>
|
||||
int main() { SDL_SysWMinfo wmInfo = {}; wmInfo.info.x11.display = NULL; return 0; }" HAVE_SDL_X11)
|
||||
|
@ -300,6 +314,15 @@ unset(compiler_id_lower)
|
|||
|
||||
endif() # not MSVC
|
||||
|
||||
TEST_BIG_ENDIAN(is_big_endian)
|
||||
if(is_big_endian)
|
||||
message(STATUS "Detected Big Endian architecture, setting -DD3_IS_BIG_ENDIAN=1")
|
||||
add_definitions(-DD3_IS_BIG_ENDIAN=1)
|
||||
else()
|
||||
message(STATUS "Detected Little Endian architecture, setting -DD3_IS_BIG_ENDIAN=0")
|
||||
add_definitions(-DD3_IS_BIG_ENDIAN=0)
|
||||
endif()
|
||||
|
||||
# compiler specific flags
|
||||
if(D3_COMPILER_IS_GCC_OR_CLANG)
|
||||
add_compile_options(-pipe)
|
||||
|
@ -799,8 +822,14 @@ set(src_idlib
|
|||
add_globbed_headers(src_idlib "idlib")
|
||||
|
||||
if(IMGUI)
|
||||
set(src_imgui
|
||||
libs/imgui/backends/imgui_impl_sdl2.cpp
|
||||
|
||||
if(SDL3)
|
||||
set(src_imgui libs/imgui/backends/imgui_impl_sdl3.cpp)
|
||||
else()
|
||||
set(src_imgui libs/imgui/backends/imgui_impl_sdl2.cpp)
|
||||
endif()
|
||||
|
||||
set(src_imgui ${src_imgui}
|
||||
libs/imgui/backends/imgui_impl_opengl2.cpp
|
||||
|
||||
libs/imgui/imgui.h
|
||||
|
@ -1152,9 +1181,13 @@ elseif(WIN32)
|
|||
sys/win32/win_net.cpp
|
||||
sys/win32/win_shared.cpp
|
||||
sys/win32/win_syscon.cpp
|
||||
sys/win32/SDL_win32_main.c
|
||||
)
|
||||
|
||||
if(NOT SDL2 AND NOT SDL3)
|
||||
# only SDL1.2 still uses SDL_win32_main.c
|
||||
set(src_sys_base ${src_sys_base} sys/win32/SDL_win32_main.c)
|
||||
endif()
|
||||
|
||||
# adding the few relevant headers in sys/ manually..
|
||||
set(src_sys_base ${src_sys_base}
|
||||
sys/platform.h
|
||||
|
@ -1195,6 +1228,9 @@ include_directories(${CMAKE_BINARY_DIR})
|
|||
include_directories(${CMAKE_SOURCE_DIR})
|
||||
|
||||
add_library(idlib STATIC ${src_idlib})
|
||||
if(SDL3)
|
||||
target_link_libraries(idlib SDL3::Headers) # so it can use SDL_Endian.h
|
||||
endif()
|
||||
if (AROS)
|
||||
add_library(dll STATIC ${src_arosdll})
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")
|
||||
|
|
|
@ -26,8 +26,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL_endian.h>
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/LangDict.h"
|
||||
#include "idlib/Timer.h"
|
||||
|
@ -527,7 +525,12 @@ void idGameLocal::SaveGame( idFile *f ) {
|
|||
savegame.WriteString( D3_ARCH ); // CPU architecture (e.g. "x86" or "x86_64") - from CMake
|
||||
savegame.WriteString( ENGINE_VERSION );
|
||||
savegame.WriteShort( (short)sizeof(void*) ); // tells us if it's from a 32bit (4) or 64bit system (8)
|
||||
savegame.WriteShort( SDL_BYTEORDER ) ; // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN
|
||||
const short byteOrder = 4321; // SDL_BIG_ENDIAN
|
||||
#else
|
||||
const short byteOrder = 1234; // SDL_LIL_ENDIAN
|
||||
#endif
|
||||
savegame.WriteShort( byteOrder ) ;
|
||||
// DG end
|
||||
|
||||
// go through all entities and threads and add them to the object list
|
||||
|
|
|
@ -26,7 +26,12 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// DG: compat with SDL2
|
||||
#define SDL_setenv SDL_setenv_unsafe
|
||||
#endif
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/containers/HashTable.h"
|
||||
|
@ -2799,7 +2804,12 @@ void idCommonLocal::SetMachineSpec( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int AsyncTimer(unsigned int interval, void *) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
static Uint32 AsyncTimer(void * /*userdata*/, SDL_TimerID /* timerID */, Uint32 interval)
|
||||
#else // SDL2 or SDL1.2
|
||||
static unsigned int AsyncTimer(unsigned int interval, void *)
|
||||
#endif
|
||||
{
|
||||
common->Async();
|
||||
Sys_TriggerEvent(TRIGGER_EVENT_ONE);
|
||||
|
||||
|
@ -2939,7 +2949,9 @@ void idCommonLocal::Init( int argc, char **argv ) {
|
|||
// we want to use the SDL event queue for dedicated servers. That
|
||||
// requires video to be initialized, so we just use the dummy
|
||||
// driver for headless boxen
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "dummy");
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_setenv("SDL_VIDEODRIVER", "dummy", 1);
|
||||
#else
|
||||
char dummy[] = "SDL_VIDEODRIVER=dummy\0";
|
||||
|
@ -2947,13 +2959,19 @@ void idCommonLocal::Init( int argc, char **argv ) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( ! SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) )
|
||||
{
|
||||
if ( SDL_Init(SDL_INIT_VIDEO) ) { // retry without joystick/gamepad if it failed
|
||||
Sys_Printf( "WARNING: Couldn't get SDL gamepad support! Gamepads won't work!\n" );
|
||||
} else
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) == 0) { // retry without joystick/gamecontroller if it failed
|
||||
Sys_Printf( "WARNING: Couldn't get SDL gamecontroller support! Gamepads won't work!\n" );
|
||||
} else
|
||||
#else
|
||||
#else // SDL1.2
|
||||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) // no gamecontroller support in SDL1
|
||||
{
|
||||
#endif
|
||||
|
@ -3005,14 +3023,22 @@ void idCommonLocal::Init( int argc, char **argv ) {
|
|||
idCVar::RegisterStaticVars();
|
||||
|
||||
// print engine version
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
int sdlv = SDL_GetVersion();
|
||||
int sdlvmaj = SDL_VERSIONNUM_MAJOR(sdlv);
|
||||
int sdlvmin = SDL_VERSIONNUM_MINOR(sdlv);
|
||||
int sdlvmicro = SDL_VERSIONNUM_MICRO(sdlv);
|
||||
Printf( "%s using SDL v%d.%d.%d\n", version.string, sdlvmaj, sdlvmin, sdlvmicro );
|
||||
#else
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_version sdlv;
|
||||
SDL_GetVersion(&sdlv);
|
||||
#else
|
||||
#else
|
||||
SDL_version sdlv = *SDL_Linked_Version();
|
||||
#endif
|
||||
#endif
|
||||
Printf( "%s using SDL v%u.%u.%u\n",
|
||||
version.string, sdlv.major, sdlv.minor, sdlv.patch );
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
Printf( "SDL video driver: %s\n", SDL_GetCurrentVideoDriver() );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <algorithm> // std::sort - TODO: replace with something custom..
|
||||
|
||||
#include <SDL.h> // to show display size
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
|
@ -1903,9 +1903,15 @@ static void DrawVideoOptionsMenu()
|
|||
}
|
||||
|
||||
// resolution info text
|
||||
int sdlDisplayIdx = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// in SDL3 it's a Display ID, in SDL2 a Display Index, in both cases the value
|
||||
// can be fed into SDL_GetDisplayBounds()
|
||||
SDL_DisplayID sdlDisplayId_x = SDL_GetDisplayForWindow( SDL_GL_GetCurrentWindow() );
|
||||
#else // SDL2
|
||||
int sdlDisplayId_x = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
|
||||
#endif
|
||||
SDL_Rect displayRect = {};
|
||||
SDL_GetDisplayBounds( sdlDisplayIdx, &displayRect );
|
||||
SDL_GetDisplayBounds( sdlDisplayId_x, &displayRect );
|
||||
if ( (int)glConfig.winWidth != glConfig.vidWidth ) {
|
||||
ImGui::TextDisabled( "Current Resolution: %g x %g (Physical: %d x %d)",
|
||||
glConfig.winWidth, glConfig.winHeight, glConfig.vidWidth, glConfig.vidHeight );
|
||||
|
|
|
@ -26,8 +26,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL_endian.h>
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/LangDict.h"
|
||||
#include "idlib/Timer.h"
|
||||
|
@ -469,7 +467,12 @@ void idGameLocal::SaveGame( idFile *f ) {
|
|||
savegame.WriteString( D3_ARCH ); // CPU architecture (e.g. "x86" or "x86_64") - from CMake
|
||||
savegame.WriteString( ENGINE_VERSION );
|
||||
savegame.WriteShort( (short)sizeof(void*) ); // tells us if it's from a 32bit (4) or 64bit system (8)
|
||||
savegame.WriteShort( SDL_BYTEORDER ) ; // SDL_LIL_ENDIAN or SDL_BIG_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN
|
||||
const short byteOrder = 4321; // SDL_BIG_ENDIAN
|
||||
#else
|
||||
const short byteOrder = 1234; // SDL_LIL_ENDIAN
|
||||
#endif
|
||||
savegame.WriteShort( byteOrder ) ;
|
||||
// DG end
|
||||
|
||||
// go through all entities and threads and add them to the object list
|
||||
|
|
|
@ -35,7 +35,32 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <SDL_endian.h>
|
||||
#ifdef D3_SDL3
|
||||
#include <SDL3/SDL_endian.h>
|
||||
// some defines for backwards-compat with SDL2
|
||||
#define SDL_SwapBE16(X) SDL_Swap16BE(X)
|
||||
#define SDL_SwapLE16(X) SDL_Swap16LE(X)
|
||||
#define SDL_SwapBE32(X) SDL_Swap32BE(X)
|
||||
#define SDL_SwapLE32(X) SDL_Swap32LE(X)
|
||||
#else // SDL1.2 or SDL2
|
||||
#include <SDL_endian.h>
|
||||
#endif
|
||||
|
||||
#ifndef D3_IS_BIG_ENDIAN
|
||||
#error "D3_IS_BIG_ENDIAN should be defined by the build system (CMake)!"
|
||||
#endif
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN != 1
|
||||
#error "CMake (which sets D3_IS_BIG_ENDIAN) and SDL disagree about the endianess! CMake says little, SDL says big"
|
||||
#endif
|
||||
#elif SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN != 0
|
||||
#error "CMake (which sets D3_IS_BIG_ENDIAN) and SDL disagree about the endianess! CMake says big, SDL says little"
|
||||
#endif
|
||||
#else
|
||||
#error "According to SDL, endianess is neither Big nor Little - dhewm3 doesn't support other byteorders!"
|
||||
#endif
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/math/Vector.h"
|
||||
|
|
|
@ -42,7 +42,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include <SDL_opengl.h>
|
||||
#ifdef D3_SDL3
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
#else // SDL1.2 or SDL2
|
||||
#include <SDL_opengl.h>
|
||||
#endif
|
||||
|
||||
#if defined( ID_DEDICATED ) && defined( _WIN32 )
|
||||
// restore WINGDIAPI
|
||||
|
|
|
@ -30,7 +30,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "renderer/tr_local.h"
|
||||
|
||||
static idCVar r_fillWindowAlphaChan( "r_fillWindowAlphaChan", "-1", CVAR_SYSTEM | CVAR_NOCHEAT | CVAR_ARCHIVE, "Make sure alpha channel of windows default framebuffer is completely opaque at the end of each frame. Needed at least when using Wayland.\n 1: do this, 0: don't do it, -1: let dhewm3 decide (default)" );
|
||||
static idCVar r_fillWindowAlphaChan( "r_fillWindowAlphaChan", "-1", CVAR_SYSTEM | CVAR_NOCHEAT | CVAR_ARCHIVE, "Make sure alpha channel of windows default framebuffer is completely opaque at the end of each frame. Needed at least when using Wayland with older drivers.\n 1: do this, 0: don't do it, -1: let dhewm3 decide (default)" );
|
||||
|
||||
frameData_t *frameData;
|
||||
backEndState_t backEnd;
|
||||
|
|
|
@ -1073,7 +1073,7 @@ typedef struct {
|
|||
bool fullScreen;
|
||||
bool fullScreenDesktop;
|
||||
bool stereo;
|
||||
int displayHz;
|
||||
int displayHz; // TODO: SDL3 uses float
|
||||
int multiSamples;
|
||||
} glimpParms_t;
|
||||
|
||||
|
@ -1119,6 +1119,7 @@ void GLimp_DeactivateContext( void );
|
|||
const int GRAB_GRABMOUSE = (1 << 0);
|
||||
const int GRAB_HIDECURSOR = (1 << 1);
|
||||
const int GRAB_RELATIVEMOUSE = (1 << 2);
|
||||
const int GRAB_ENABLETEXTINPUT = (1 << 3); // only used with SDL3, where textinput must be explicitly activated
|
||||
|
||||
void GLimp_GrabInput(int flags);
|
||||
|
||||
|
|
|
@ -26,9 +26,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN
|
||||
#define STB_VORBIS_BIG_ENDIAN
|
||||
#endif
|
||||
#define STB_VORBIS_NO_STDIO
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
// (I'm doing this instead of renaming stb_vorbis.h to stb_vorbis.c so the configuration
|
||||
// like STB_VORBIS_BIG_ENDIAN etc can be done here in code)
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#if D3_IS_BIG_ENDIAN
|
||||
#define STB_VORBIS_BIG_ENDIAN
|
||||
#endif
|
||||
#define STB_VORBIS_NO_STDIO
|
||||
|
|
|
@ -28,7 +28,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include <float.h>
|
||||
|
||||
#include <SDL_cpuinfo.h>
|
||||
#ifdef D3_SDL3
|
||||
#include <SDL3/SDL_cpuinfo.h>
|
||||
#else // SDL1.2 or SDL2
|
||||
#include <SDL_cpuinfo.h>
|
||||
#endif
|
||||
|
||||
// MSVC header intrin.h uses strcmp and errors out when not set
|
||||
#define IDSTR_NO_REDIRECT
|
||||
|
@ -201,8 +205,11 @@ int Sys_GetProcessorId( void ) {
|
|||
if (SDL_HasMMX())
|
||||
flags |= CPUID_MMX;
|
||||
|
||||
// SDL3 doesn't support detecting 3DNow, and current CPUs (even from AMD) don't support it either
|
||||
#ifndef D3_SDL3
|
||||
if (SDL_Has3DNow())
|
||||
flags |= CPUID_3DNOW;
|
||||
#endif
|
||||
|
||||
if (SDL_HasSSE())
|
||||
flags |= CPUID_SSE;
|
||||
|
|
|
@ -26,7 +26,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/containers/List.h"
|
||||
|
@ -61,6 +61,103 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define SDLK_PRINTSCREEN SDLK_PRINT
|
||||
#endif
|
||||
|
||||
// unholy hacks to make it work with SDL3 (and also SDL2 and partly SDL1.2)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// in SDL3 SDL_GetKeyFromScancode() got additional arguments that I don't care about
|
||||
#define SDL_GetKeyFromScancode(SC) SDL_GetKeyFromScancode(SC, 0, true)
|
||||
|
||||
#define SDLK_z SDLK_Z
|
||||
|
||||
#define SDL_TEXTINPUT SDL_EVENT_TEXT_INPUT
|
||||
#define SDL_KEYDOWN SDL_EVENT_KEY_DOWN
|
||||
#define SDL_KEYUP SDL_EVENT_KEY_UP
|
||||
|
||||
#define SDL_USEREVENT SDL_EVENT_USER
|
||||
#define SDL_QUIT SDL_EVENT_QUIT
|
||||
|
||||
#define SDL_MOUSEBUTTONDOWN SDL_EVENT_MOUSE_BUTTON_DOWN
|
||||
#define SDL_MOUSEBUTTONUP SDL_EVENT_MOUSE_BUTTON_UP
|
||||
#define SDL_MOUSEMOTION SDL_EVENT_MOUSE_MOTION
|
||||
#define SDL_MOUSEWHEEL SDL_EVENT_MOUSE_WHEEL
|
||||
|
||||
#define SDL_JoystickGUID SDL_GUID
|
||||
#define SDL_JoystickGetGUID SDL_GetJoystickGUID
|
||||
#define SDL_JoystickName SDL_GetJoystickName
|
||||
#define SDL_JoystickGetGUIDString SDL_GUIDToString
|
||||
|
||||
#define SDL_JOYDEVICEADDED SDL_EVENT_JOYSTICK_ADDED
|
||||
#define SDL_JOYDEVICEREMOVED SDL_EVENT_JOYSTICK_REMOVED
|
||||
|
||||
// game controllers have been renamed to gamepads and the
|
||||
// corresponding SDL_Event members are now prefixed with g instead of c
|
||||
#define cbutton gbutton
|
||||
#define caxis gaxis
|
||||
|
||||
#define SDL_GameController SDL_Gamepad
|
||||
#define SDL_GameControllerAxis SDL_GamepadAxis
|
||||
#define SDL_GameControllerButton SDL_GamepadButton
|
||||
|
||||
#define SDL_GameControllerGetType SDL_GetGamepadType
|
||||
#define SDL_GameControllerName SDL_GetGamepadName
|
||||
#define SDL_GameControllerGetJoystick SDL_GetGamepadJoystick
|
||||
#define SDL_GameControllerGetVendor SDL_GetGamepadVendor
|
||||
#define SDL_GameControllerGetProduct SDL_GetGamepadProduct
|
||||
#define SDL_GameControllerOpen SDL_OpenGamepad
|
||||
|
||||
#define SDL_CONTROLLERAXISMOTION SDL_EVENT_GAMEPAD_AXIS_MOTION
|
||||
#define SDL_CONTROLLERBUTTONDOWN SDL_EVENT_GAMEPAD_BUTTON_DOWN
|
||||
#define SDL_CONTROLLERBUTTONUP SDL_EVENT_GAMEPAD_BUTTON_UP
|
||||
|
||||
#define SDL_CONTROLLER_AXIS_LEFTX SDL_GAMEPAD_AXIS_LEFTX
|
||||
#define SDL_CONTROLLER_AXIS_LEFTY SDL_GAMEPAD_AXIS_LEFTY
|
||||
#define SDL_CONTROLLER_AXIS_MAX SDL_GAMEPAD_AXIS_MAX
|
||||
#define SDL_CONTROLLER_AXIS_RIGHTX SDL_GAMEPAD_AXIS_RIGHTX
|
||||
#define SDL_CONTROLLER_AXIS_RIGHTY SDL_GAMEPAD_AXIS_RIGHTY
|
||||
#define SDL_CONTROLLER_AXIS_TRIGGERLEFT SDL_GAMEPAD_AXIS_LEFT_TRIGGER
|
||||
#define SDL_CONTROLLER_AXIS_TRIGGERRIGHT SDL_GAMEPAD_AXIS_RIGHT_TRIGGER
|
||||
#define SDL_CONTROLLER_BUTTON_A SDL_GAMEPAD_BUTTON_SOUTH
|
||||
#define SDL_CONTROLLER_BUTTON_B SDL_GAMEPAD_BUTTON_EAST
|
||||
#define SDL_CONTROLLER_BUTTON_X SDL_GAMEPAD_BUTTON_WEST
|
||||
#define SDL_CONTROLLER_BUTTON_Y SDL_GAMEPAD_BUTTON_NORTH
|
||||
#define SDL_CONTROLLER_BUTTON_BACK SDL_GAMEPAD_BUTTON_BACK
|
||||
#define SDL_CONTROLLER_BUTTON_DPAD_DOWN SDL_GAMEPAD_BUTTON_DPAD_DOWN
|
||||
#define SDL_CONTROLLER_BUTTON_DPAD_LEFT SDL_GAMEPAD_BUTTON_DPAD_LEFT
|
||||
#define SDL_CONTROLLER_BUTTON_DPAD_RIGHT SDL_GAMEPAD_BUTTON_DPAD_RIGHT
|
||||
#define SDL_CONTROLLER_BUTTON_DPAD_UP SDL_GAMEPAD_BUTTON_DPAD_UP
|
||||
#define SDL_CONTROLLER_BUTTON_GUIDE SDL_GAMEPAD_BUTTON_GUIDE
|
||||
#define SDL_CONTROLLER_BUTTON_INVALID SDL_GAMEPAD_BUTTON_INVALID
|
||||
#define SDL_CONTROLLER_BUTTON_LEFTSHOULDER SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
|
||||
#define SDL_CONTROLLER_BUTTON_LEFTSTICK SDL_GAMEPAD_BUTTON_LEFT_STICK
|
||||
#define SDL_CONTROLLER_BUTTON_MISC1 SDL_GAMEPAD_BUTTON_MISC1
|
||||
#define SDL_CONTROLLER_BUTTON_PADDLE1 SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1
|
||||
#define SDL_CONTROLLER_BUTTON_PADDLE2 SDL_GAMEPAD_BUTTON_LEFT_PADDLE1
|
||||
#define SDL_CONTROLLER_BUTTON_PADDLE3 SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2
|
||||
#define SDL_CONTROLLER_BUTTON_PADDLE4 SDL_GAMEPAD_BUTTON_LEFT_PADDLE2
|
||||
#define SDL_CONTROLLER_BUTTON_RIGHTSHOULDER SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
|
||||
#define SDL_CONTROLLER_BUTTON_RIGHTSTICK SDL_GAMEPAD_BUTTON_RIGHT_STICK
|
||||
#define SDL_CONTROLLER_BUTTON_START SDL_GAMEPAD_BUTTON_START
|
||||
#define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_GAMEPAD_BUTTON_TOUCHPAD
|
||||
|
||||
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
|
||||
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
|
||||
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
|
||||
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
|
||||
#define SDL_CONTROLLER_TYPE_PS3 SDL_GAMEPAD_TYPE_PS3
|
||||
#define SDL_CONTROLLER_TYPE_PS4 SDL_GAMEPAD_TYPE_PS4
|
||||
#define SDL_CONTROLLER_TYPE_PS5 SDL_GAMEPAD_TYPE_PS5
|
||||
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_GAMEPAD_TYPE_STANDARD
|
||||
#define SDL_CONTROLLER_TYPE_VIRTUAL SDL_GAMEPAD_TYPE_VIRTUAL
|
||||
#define SDL_CONTROLLER_TYPE_XBOX360 SDL_GAMEPAD_TYPE_XBOX360
|
||||
#define SDL_CONTROLLER_TYPE_XBOXONE SDL_GAMEPAD_TYPE_XBOXONE
|
||||
|
||||
#define IS_SDL_BTN_DOWN(EV) EV.down
|
||||
|
||||
#else // SDL2 and SDL1.2
|
||||
|
||||
#define IS_SDL_BTN_DOWN(EV) (EV.state == SDL_PRESSED)
|
||||
|
||||
#endif // SDL_VERSION_ATLEAST(3, 0, 0) - unholy hacks
|
||||
|
||||
extern idCVar in_useGamepad; // from UsercmdGen.cpp
|
||||
extern idCVar joy_deadZone; // ditto
|
||||
|
||||
|
@ -78,7 +175,7 @@ static idCVar in_ignoreConsoleKey("in_ignoreConsoleKey", "0", CVAR_SYSTEM | CVAR
|
|||
"Console only opens with Shift+Esc, not ` or ^ etc");
|
||||
|
||||
static idCVar in_nograb("in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents input grabbing");
|
||||
static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
|
||||
idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
|
||||
"if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)");
|
||||
|
||||
idCVar joy_gamepadLayout("joy_gamepadLayout", "-1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_INTEGER,
|
||||
|
@ -100,7 +197,7 @@ struct kbd_poll_t {
|
|||
int key;
|
||||
bool state;
|
||||
|
||||
kbd_poll_t() {
|
||||
kbd_poll_t() : key(0), state(false) {
|
||||
}
|
||||
|
||||
kbd_poll_t(int k, bool s) {
|
||||
|
@ -113,7 +210,7 @@ struct mouse_poll_t {
|
|||
int action;
|
||||
int value;
|
||||
|
||||
mouse_poll_t() {
|
||||
mouse_poll_t() : action(0), value(0) {
|
||||
}
|
||||
|
||||
mouse_poll_t(int a, int v) {
|
||||
|
@ -269,10 +366,11 @@ const char* Sys_GetLocalizedJoyKeyName( int key ) {
|
|||
if (key >= K_FIRST_JOY && key <= K_LAST_JOY) {
|
||||
|
||||
if (key <= K_JOY_BTN_BACK) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
#if 0 //SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// TODO: or use the SDL2 code and just set joy_gamepadLayout automatically based on SDL_GetGamepadType() ?
|
||||
SDL_GamepadButton gpbtn = SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH);
|
||||
SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabelForType(TODO, gpbtn);
|
||||
SDL_GamepadButton gpbtn = (SDL_GamepadButton)(SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH));
|
||||
SDL_GamepadType sdlGamepadType = TODO;
|
||||
SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabelForType(sdlGamepadType, gpbtn);
|
||||
switch(label) {
|
||||
case SDL_GAMEPAD_BUTTON_LABEL_A:
|
||||
return "Pad A";
|
||||
|
@ -421,13 +519,14 @@ static const char* getLocalizedScancodeName( int key, bool useUtf8 )
|
|||
}
|
||||
} else if ( k != SDLK_UNKNOWN ) {
|
||||
const char *ret = SDL_GetKeyName( k );
|
||||
// the keyname from SDL2 is in UTF-8, which Doom3 can't print,
|
||||
// so only return the name if it's ASCII, otherwise fall back to "SC_bla"
|
||||
if ( ret && *ret != '\0' ) {
|
||||
if( useUtf8 ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// the keyname from SDL2 is in UTF-8, which Doom3 can't print (except with ImGui),
|
||||
// so only return the name directly if it's ASCII, otherwise try to translate it
|
||||
// to ISO8859-1, and if that fails fall back to SC_*
|
||||
if( isAscii( ret ) ) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -844,7 +943,8 @@ void Sys_InitInput() {
|
|||
in_kbd.SetModified();
|
||||
Sys_GetConsoleKey(false); // initialize consoleKeymappingIdx from in_kbd
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
const char* grabKeyboardEnv = SDL_getenv(SDL_HINT_GRAB_KEYBOARD);
|
||||
// NOTE: SDL3 doesn't support that hint/env var, but whatever, support the env var anyway
|
||||
const char* grabKeyboardEnv = SDL_getenv("SDL_GRAB_KEYBOARD");
|
||||
if ( grabKeyboardEnv ) {
|
||||
common->Printf( "The SDL_GRAB_KEYBOARD environment variable is set, setting the in_grabKeyboard CVar to the same value (%s)\n", grabKeyboardEnv );
|
||||
in_grabKeyboard.SetString( grabKeyboardEnv );
|
||||
|
@ -861,7 +961,19 @@ void Sys_InitInput() {
|
|||
memset( buttonStates, 0, sizeof( buttonStates ) );
|
||||
memset( joyAxis, 0, sizeof( joyAxis ) );
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0) // gamecontroller/gamepad not supported in SDL1
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
int numJoysticks = 0;
|
||||
SDL_JoystickID* joysticks = SDL_GetJoysticks(&numJoysticks);
|
||||
for( int i = 0; i < numJoysticks; ++i )
|
||||
{
|
||||
SDL_GameController* gc = SDL_GameControllerOpen( joysticks[i] );
|
||||
if ( gc != NULL ) {
|
||||
setGamepadType( gc );
|
||||
}
|
||||
}
|
||||
SDL_free(joysticks);
|
||||
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// use button positions instead of button labels,
|
||||
// Sys_GetLocalizedJoyKeyName() will do the translation
|
||||
// (I think this also was the default before 2.0.12?)
|
||||
|
@ -875,7 +987,7 @@ void Sys_InitInput() {
|
|||
setGamepadType( gc );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // gamecontroller/gamepad not supported in SDL1
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1082,6 +1194,7 @@ sysEvent_t Sys_GetEvent() {
|
|||
SDL_Event ev;
|
||||
sysEvent_t res = { };
|
||||
int key;
|
||||
bool isDown = false;
|
||||
|
||||
static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };
|
||||
|
||||
|
@ -1094,7 +1207,11 @@ sysEvent_t Sys_GetEvent() {
|
|||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
static char s[SDL_TEXTINPUTEVENT_TEXT_SIZE] = {0};
|
||||
// s holds the string from the last SDL_TEXTINPUT event, to generate SE_CHARS D3 events,
|
||||
// one event per call to this function until all chars have been handled
|
||||
// it used to have SDL_TEXTINPUTEVENT_TEXT_SIZE (32) bytes, but in SDL3 the string can have
|
||||
// arbitrary size, however I assume that 128 should still be more than enough
|
||||
static char s[128] = {0};
|
||||
static size_t s_pos = 0;
|
||||
|
||||
if (s[0] != '\0') {
|
||||
|
@ -1103,7 +1220,7 @@ sysEvent_t Sys_GetEvent() {
|
|||
|
||||
++s_pos;
|
||||
|
||||
if (!s[s_pos] || s_pos == SDL_TEXTINPUTEVENT_TEXT_SIZE) {
|
||||
if (!s[s_pos] || s_pos == sizeof(s)) {
|
||||
memset(s, 0, sizeof(s));
|
||||
s_pos = 0;
|
||||
}
|
||||
|
@ -1112,6 +1229,9 @@ sysEvent_t Sys_GetEvent() {
|
|||
}
|
||||
#endif
|
||||
|
||||
// c holds a single char for a SE_CHAR event, probably coming from a SDL_KEYDOWN event
|
||||
// (that was also returned as SE_KEY), or from a SDL_TEXTINPUT event that contained just one char.
|
||||
// It's 0 when not currently holding a char to generate an event
|
||||
static byte c = 0;
|
||||
|
||||
if (c) {
|
||||
|
@ -1131,7 +1251,35 @@ sysEvent_t Sys_GetEvent() {
|
|||
}
|
||||
|
||||
switch (ev.type) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED: {
|
||||
// unset modifier, in case alt-tab was used to leave window and ALT is still set
|
||||
// as that can cause fullscreen-toggling when pressing enter...
|
||||
SDL_Keymod currentmod = SDL_GetModState();
|
||||
|
||||
int newmod = SDL_KMOD_NONE;
|
||||
if (currentmod & SDL_KMOD_CAPS) // preserve capslock
|
||||
newmod |= SDL_KMOD_CAPS;
|
||||
|
||||
SDL_SetModState((SDL_Keymod)newmod);
|
||||
} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST
|
||||
|
||||
in_hasFocus = true;
|
||||
|
||||
// start playing the game sound world again (when coming from editor)
|
||||
session->SetPlayingSoundWorld();
|
||||
continue; // handle next event
|
||||
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
in_hasFocus = false;
|
||||
continue; // handle next event
|
||||
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
GLimp_UpdateWindowSize();
|
||||
continue; // handle next event
|
||||
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (ev.window.event) {
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED: {
|
||||
|
@ -1146,7 +1294,6 @@ sysEvent_t Sys_GetEvent() {
|
|||
SDL_SetModState((SDL_Keymod)newmod);
|
||||
} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST
|
||||
|
||||
|
||||
in_hasFocus = true;
|
||||
|
||||
// start playing the game sound world again (when coming from editor)
|
||||
|
@ -1188,7 +1335,11 @@ sysEvent_t Sys_GetEvent() {
|
|||
#endif
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if (ev.key.key == SDLK_RETURN && (ev.key.mod & SDL_KMOD_ALT) > 0) {
|
||||
#else
|
||||
if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
|
||||
#endif
|
||||
cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
|
||||
PushConsoleEvent("vid_restart partial");
|
||||
return res_none;
|
||||
|
@ -1196,7 +1347,7 @@ sysEvent_t Sys_GetEvent() {
|
|||
|
||||
// fall through
|
||||
case SDL_KEYUP:
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0) // SDL1.2
|
||||
key = mapkey(ev.key.keysym.sym);
|
||||
if (!key) {
|
||||
if ( !in_ignoreConsoleKey.GetBool() ) {
|
||||
|
@ -1213,12 +1364,18 @@ sysEvent_t Sys_GetEvent() {
|
|||
continue; // handle next event
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else // SDL2+
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_Scancode sc = ev.key.scancode;
|
||||
SDL_Keycode keycode = ev.key.key;
|
||||
#else // SDL2
|
||||
SDL_Scancode sc = ev.key.keysym.scancode;
|
||||
SDL_Keycode keycode = ev.key.keysym.sym;
|
||||
#endif
|
||||
// workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
|
||||
// always map those physical keys (scancodes) to those keycodes anyway
|
||||
// see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
|
||||
SDL_Scancode sc = ev.key.keysym.scancode;
|
||||
if(sc == SDL_SCANCODE_0)
|
||||
{
|
||||
key = '0';
|
||||
|
@ -1232,10 +1389,10 @@ sysEvent_t Sys_GetEvent() {
|
|||
}
|
||||
else
|
||||
{
|
||||
key = mapkey(ev.key.keysym.sym);
|
||||
key = mapkey(keycode);
|
||||
}
|
||||
|
||||
if ( !in_ignoreConsoleKey.GetBool() && ev.key.keysym.scancode == SDL_SCANCODE_GRAVE ) {
|
||||
if ( !in_ignoreConsoleKey.GetBool() && sc == SDL_SCANCODE_GRAVE ) {
|
||||
// that key between Esc, Tab and 1 is the console key
|
||||
key = K_CONSOLE;
|
||||
}
|
||||
|
@ -1245,27 +1402,29 @@ sysEvent_t Sys_GetEvent() {
|
|||
key = getKeynumForSDLscancode(sc);
|
||||
if(!key) {
|
||||
if (ev.type == SDL_KEYDOWN) {
|
||||
common->Warning("unmapped SDL key %d (scancode %d)", ev.key.keysym.sym, (int)sc);
|
||||
common->Warning("unmapped SDL key %d (scancode %d)", keycode, (int)sc);
|
||||
}
|
||||
continue; // handle next event
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
isDown = IS_SDL_BTN_DOWN( ev.key );
|
||||
|
||||
res.evType = SE_KEY;
|
||||
res.evValue = key;
|
||||
res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;
|
||||
res.evValue2 = isDown;
|
||||
|
||||
kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));
|
||||
kbd_polls.Append( kbd_poll_t( key, isDown ) );
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
|
||||
if (key == K_BACKSPACE && isDown)
|
||||
c = key;
|
||||
#else
|
||||
if (ev.key.state == SDL_PRESSED && (ev.key.keysym.unicode & 0xff00) == 0)
|
||||
c = ev.key.keysym.unicode & 0xff;
|
||||
#endif
|
||||
// Note: c will be sent as SE_CHAR next time this function is called
|
||||
|
||||
return res;
|
||||
|
||||
|
@ -1277,8 +1436,17 @@ sysEvent_t Sys_GetEvent() {
|
|||
if ( isAscii(ev.text.text) ) {
|
||||
res.evValue = ev.text.text[0];
|
||||
if ( ev.text.text[1] != '\0' ) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// yes, it's ok if this is not 0-terminated, the code generating
|
||||
// events from s handles that
|
||||
strncpy(s, ev.text.text, sizeof(s));
|
||||
#else // SDL2
|
||||
memcpy( s, ev.text.text, SDL_TEXTINPUTEVENT_TEXT_SIZE );
|
||||
s_pos = 1; // pos 0 is returned
|
||||
s[SDL_TEXTINPUTEVENT_TEXT_SIZE] = '\0';
|
||||
#endif
|
||||
// pos 0 is returned, the rest of s is returned as SE_CHAR events
|
||||
// at the next times this function is called
|
||||
s_pos = 1;
|
||||
}
|
||||
return res;
|
||||
} else if( D3_UTF8toISO8859_1( ev.text.text, s, sizeof(s) ) && s[0] != '\0' ) {
|
||||
|
@ -1287,17 +1455,15 @@ sysEvent_t Sys_GetEvent() {
|
|||
s_pos = 0;
|
||||
s[0] = '\0';
|
||||
} else {
|
||||
s_pos = 1; // pos 0 is returned
|
||||
// pos 0 is returned, the rest of s is returned as SE_CHAR events
|
||||
// at the next times this function is called
|
||||
s_pos = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
continue; // handle next event
|
||||
|
||||
case SDL_TEXTEDITING:
|
||||
// on windows we get this event whenever the window gains focus.. just ignore it.
|
||||
continue;
|
||||
#endif
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
|
@ -1335,20 +1501,21 @@ sysEvent_t Sys_GetEvent() {
|
|||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
isDown = IS_SDL_BTN_DOWN(ev.button);
|
||||
res.evType = SE_KEY;
|
||||
|
||||
switch (ev.button.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
res.evValue = K_MOUSE1;
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION1, isDown));
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
res.evValue = K_MOUSE3;
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION3, isDown));
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
res.evValue = K_MOUSE2;
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
|
||||
mouse_polls.Append(mouse_poll_t(M_ACTION2, isDown));
|
||||
break;
|
||||
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
@ -1370,14 +1537,14 @@ sysEvent_t Sys_GetEvent() {
|
|||
{
|
||||
int buttonIndex = ev.button.button - SDL_BUTTON_LEFT;
|
||||
res.evValue = K_MOUSE1 + buttonIndex;
|
||||
mouse_polls.Append( mouse_poll_t( M_ACTION1 + buttonIndex, ev.button.state == SDL_PRESSED ? 1 : 0 ) );
|
||||
mouse_polls.Append( mouse_poll_t( M_ACTION1 + buttonIndex, isDown ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
continue; // handle next event
|
||||
}
|
||||
|
||||
res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;
|
||||
res.evValue2 = isDown;
|
||||
|
||||
return res;
|
||||
|
||||
|
@ -1390,8 +1557,10 @@ sysEvent_t Sys_GetEvent() {
|
|||
continue;
|
||||
}
|
||||
|
||||
isDown = IS_SDL_BTN_DOWN(ev.cbutton);
|
||||
|
||||
res.evType = SE_KEY;
|
||||
res.evValue2 = ev.cbutton.state == SDL_PRESSED ? 1 : 0;
|
||||
res.evValue2 = isDown;
|
||||
|
||||
// special case: always treat the start button as escape so it opens/closes the menu
|
||||
// (also makes that button non-bindable)
|
||||
|
@ -1410,7 +1579,7 @@ sysEvent_t Sys_GetEvent() {
|
|||
}
|
||||
|
||||
sys_jEvents jEvent = mapjoybutton( (SDL_GameControllerButton)ev.cbutton.button );
|
||||
joystick_polls.Append( joystick_poll_t(jEvent, ev.cbutton.state == SDL_PRESSED ? 1 : 0) );
|
||||
joystick_polls.Append( joystick_poll_t(jEvent, isDown) );
|
||||
|
||||
if ( ( jEvent >= J_ACTION_FIRST ) && ( jEvent <= J_ACTION_MAX ) ) {
|
||||
res.evValue = K_FIRST_JOY + ( jEvent - J_ACTION_FIRST );
|
||||
|
@ -1571,9 +1740,12 @@ static void handleMouseGrab() {
|
|||
bool showCursor = true;
|
||||
bool grabMouse = false;
|
||||
bool relativeMouse = false;
|
||||
bool enableTextInput = false;
|
||||
|
||||
const bool imguiHasFocus = D3::ImGuiHooks::ShouldShowCursor();
|
||||
|
||||
// if com_editorActive, release everything, just like when we have no focus
|
||||
if ( in_hasFocus && !com_editorActive && !D3::ImGuiHooks::ShouldShowCursor() ) {
|
||||
if ( in_hasFocus && !com_editorActive && !imguiHasFocus ) {
|
||||
// Note: this generally handles fullscreen menus, but not the PDA, because the PDA
|
||||
// is an ugly hack in gamecode that doesn't go through sessLocal.guiActive.
|
||||
// It goes through weapon input code or sth? That's also the reason only
|
||||
|
@ -1585,9 +1757,11 @@ static void handleMouseGrab() {
|
|||
showCursor = false;
|
||||
relativeMouse = false;
|
||||
grabMouse = false; // TODO: or still grab to window? (maybe only if in exclusive fullscreen mode?)
|
||||
enableTextInput = true;
|
||||
} else if ( console->Active() ) {
|
||||
showCursor = true;
|
||||
relativeMouse = grabMouse = false;
|
||||
enableTextInput = true;
|
||||
} else { // in game
|
||||
showCursor = false;
|
||||
grabMouse = relativeMouse = true;
|
||||
|
@ -1603,6 +1777,10 @@ static void handleMouseGrab() {
|
|||
}
|
||||
} else {
|
||||
in_relativeMouseMode = false;
|
||||
// if an ImGui window has focus, enable text input so one can write in there
|
||||
// TODO: add explicit GRAB_DISABLETEXTINPUT and don't set it at all here for ImGui?
|
||||
// in theory, ImGui handles that itself, but currently GLimp_GrabInput() seems to override it
|
||||
enableTextInput = imguiHasFocus;
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
|
@ -1612,6 +1790,8 @@ static void handleMouseGrab() {
|
|||
flags |= GRAB_GRABMOUSE;
|
||||
if ( relativeMouse )
|
||||
flags |= GRAB_RELATIVEMOUSE;
|
||||
if ( enableTextInput )
|
||||
flags |= GRAB_ENABLETEXTINPUT;
|
||||
|
||||
GLimp_GrabInput( flags );
|
||||
}
|
||||
|
@ -1630,7 +1810,8 @@ void Sys_GenerateEvents() {
|
|||
if (s)
|
||||
PushConsoleEvent(s);
|
||||
|
||||
#ifndef ID_DEDICATED // doesn't make sense on dedicated server
|
||||
// doesn't make sense on dedicated server and SDL3 handles this in GLimp_GrabInput()
|
||||
#if !defined(ID_DEDICATED) && ! SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( in_grabKeyboard.IsModified() ) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_SetHint( SDL_HINT_GRAB_KEYBOARD, in_grabKeyboard.GetString() );
|
||||
|
|
|
@ -26,7 +26,17 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// backwards-compat with SDL2
|
||||
#define SDL_WINDOW_ALLOW_HIGHDPI SDL_WINDOW_HIGH_PIXEL_DENSITY
|
||||
#define SDL_GL_DeleteContext SDL_GL_DestroyContext
|
||||
typedef SDL_WindowFlags My_SDL_WindowFlags;
|
||||
#else // SDL1.2 or SDL2
|
||||
// for compat with SDL3 - unfortunately SDL2 also has a SDL_WindowFlags type, but it's an enum
|
||||
typedef Uint32 My_SDL_WindowFlags;
|
||||
#endif
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "framework/Licensee.h"
|
||||
|
@ -37,7 +47,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#if defined(_WIN32) && defined(ID_ALLOW_TOOLS)
|
||||
#include "sys/win32/win_local.h"
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
// SDL3 doesn't have SDL_syswm.h
|
||||
#if ! SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
#include <SDL_syswm.h>
|
||||
#endif
|
||||
|
||||
// from SDL_windowsopengl.h (internal SDL2 header)
|
||||
#ifndef WGL_ARB_pixel_format
|
||||
|
@ -99,7 +113,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#endif // _WIN32 and ID_ALLOW_TOOLS
|
||||
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_GLContext context = NULL;
|
||||
|
@ -109,6 +122,24 @@ static SDL_Surface *window = NULL;
|
|||
#define SDL_WINDOW_FULLSCREEN SDL_FULLSCREEN
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
|
||||
extern idCVar in_grabKeyboard;
|
||||
|
||||
static void SetSDLIcon()
|
||||
{
|
||||
#include "doom_icon.h" // contains the struct d3_icon
|
||||
|
||||
SDL_Surface* icon = SDL_CreateSurfaceFrom(d3_icon.width, d3_icon.height,
|
||||
SDL_PIXELFORMAT_RGBA32, (void*)d3_icon.pixel_data,
|
||||
d3_icon.bytes_per_pixel*d3_icon.width);
|
||||
|
||||
SDL_SetWindowIcon(window, icon);
|
||||
SDL_DestroySurface(icon);
|
||||
}
|
||||
|
||||
#else // SDL2 and SDL1.2
|
||||
|
||||
static void SetSDLIcon()
|
||||
{
|
||||
Uint32 rmask, gmask, bmask, amask;
|
||||
|
@ -141,6 +172,7 @@ static void SetSDLIcon()
|
|||
|
||||
SDL_FreeSurface(icon);
|
||||
}
|
||||
#endif // SDL2 and SDL1.2
|
||||
|
||||
/*
|
||||
===================
|
||||
|
@ -152,16 +184,23 @@ bool GLimp_Init(glimpParms_t parms) {
|
|||
|
||||
assert(SDL_WasInit(SDL_INIT_VIDEO));
|
||||
|
||||
Uint32 flags = SDL_WINDOW_OPENGL;
|
||||
My_SDL_WindowFlags flags = SDL_WINDOW_OPENGL;
|
||||
|
||||
if (parms.fullScreen == 1)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if(parms.fullScreenDesktop)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
else
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// in SDL3 windows with SDL_WINDOW_FULLSCREEN set are fullscreen-desktop by default
|
||||
// and for exclusive fullscreen SDL_SetWindowFullscreenMode() must be called
|
||||
// after creating the window, so only set the flag if we want fullscreen-desktop mode
|
||||
if(parms.fullScreen && parms.fullScreenDesktop) {
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
flags |= parms.fullScreenDesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN;
|
||||
#else // SDL1.2
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
r_windowResizable.ClearModified();
|
||||
|
@ -180,17 +219,23 @@ bool GLimp_Init(glimpParms_t parms) {
|
|||
* rendering bugs (the window is partly transparent or very white in areas with low alpha).
|
||||
* Mesa introduced an EGL extension that's supposed to fix that (EGL_EXT_present_opaque)
|
||||
* and newer SDL2 versions use it by default (in the Wayland backend).
|
||||
* Unfortunately, the implementation of that extension is (currently?) broken (at least
|
||||
* in Mesa), seems like they just give you a visual without any alpha chan - which doesn't
|
||||
* Unfortunately, the implementation of that extension was broken (at least in Mesa before 24.1),
|
||||
* seems like they just give you a visual without any alpha chan - which doesn't
|
||||
* work for Doom3, as it needs a functioning alpha chan for blending operations, see above.
|
||||
* See also: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5886
|
||||
*
|
||||
* So to make sure dhewm3 (finally) works as expected on Wayland, we tell SDL2 to
|
||||
* allow transparency and then fill the alpha-chan ourselves in RB_SwapBuffers()
|
||||
* (unless the user disables that with r_fillWindowAlphaChan 0) */
|
||||
* (unless the user disables that with r_fillWindowAlphaChan 0)
|
||||
*
|
||||
* NOTE: This bug is fixed in Mesa 24.1 and newer, and doesn't seem to occur with recent
|
||||
* NVIDIA drivers either, so for SDL3 (which should be mostly used with current drivers/mesa)
|
||||
* I don't enable this hack by default. If r_fillWindowAlphaChan == 1, it's enabled
|
||||
* when creating the window, though.
|
||||
*/
|
||||
#ifdef SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY
|
||||
SDL_SetHint(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, "1");
|
||||
#else // little hack so this works if the SDL2 version used for building is older than runtime version
|
||||
#elif SDL_MAJOR_VERSION == 2 // little hack so this works if the SDL2 version used for building is older than runtime version
|
||||
SDL_SetHint("SDL_VIDEO_EGL_ALLOW_TRANSPARENCY", "1");
|
||||
#endif
|
||||
#endif
|
||||
|
@ -277,7 +322,7 @@ try_again:
|
|||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (multisamples > 1) ? 1 : 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisamples);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0) // SDL2 and SDL3 window creation
|
||||
|
||||
if ( r_glDebugContext.GetBool() ) {
|
||||
common->Printf( "Requesting an OpenGL Debug Context (r_glDebugContext is enabled)\n" );
|
||||
|
@ -292,37 +337,150 @@ try_again:
|
|||
windowMode, parms.width, parms.height, r_mode.GetInteger());
|
||||
}
|
||||
|
||||
int displayIndex = 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
||||
Uint32 selectedDisplay = 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
||||
// try to put the window on the display the mousecursor currently is on
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
float x, y;
|
||||
int numDisplays = 0;
|
||||
SDL_DisplayID* displayIDs = SDL_GetDisplays(&numDisplays);
|
||||
#else // SDL2
|
||||
int numDisplays = SDL_GetNumVideoDisplays();
|
||||
int x, y;
|
||||
#endif
|
||||
|
||||
SDL_GetGlobalMouseState(&x, &y);
|
||||
|
||||
int numDisplays = SDL_GetNumVideoDisplays();
|
||||
common->Printf("SDL detected %d displays: \n", numDisplays);
|
||||
bool found = false;
|
||||
for ( int j=0; j<numDisplays; ++j ) {
|
||||
SDL_Rect rect;
|
||||
if (SDL_GetDisplayBounds(j, &rect) == 0) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_DisplayID displayId_x = displayIDs[j];
|
||||
int numModes = 0;
|
||||
SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayId_x, &numModes);
|
||||
common->Printf( " Display %d (ID %u) has the following modes:\n", j, displayId_x );
|
||||
for ( int dmIdx=0; dmIdx < numModes; ++dmIdx ) {
|
||||
SDL_DisplayMode* mode = modes[dmIdx];
|
||||
common->Printf( " - %d x %d @ %g Hz, density %g \n", mode->w, mode->h, mode->refresh_rate, mode->pixel_density );
|
||||
}
|
||||
SDL_free( modes );
|
||||
if ( SDL_GetDisplayBounds(displayId_x, &rect) ) {
|
||||
common->Printf(" Currently: %dx%d at (%d, %d) to (%d, %d)\n", rect.w, rect.h,
|
||||
rect.x, rect.y, rect.x+rect.w, rect.y+rect.h);
|
||||
#else // SDL2
|
||||
int displayId_x = j;
|
||||
if (SDL_GetDisplayBounds(displayId_x, &rect) == 0) {
|
||||
common->Printf(" %d: %dx%d at (%d, %d) to (%d, %d)\n", j, rect.w, rect.h,
|
||||
rect.x, rect.y, rect.x+rect.w, rect.y+rect.h);
|
||||
#endif
|
||||
if ( !found && x >= rect.x && x < rect.x + rect.w
|
||||
&& y >= rect.y && y < rect.y + rect.h )
|
||||
{
|
||||
displayIndex = j;
|
||||
selectedDisplay = j;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
common->Printf("Will use display %d because mouse cursor is at (%d, %d).\n",
|
||||
displayIndex, x, y);
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if(displayIDs != NULL) {
|
||||
SDL_DisplayID displayID = displayIDs[selectedDisplay];
|
||||
common->Printf("Will use display %u (%u) because mouse cursor is at (%g, %g).\n",
|
||||
selectedDisplay, displayID, x, y);
|
||||
selectedDisplay = displayID;
|
||||
SDL_free(displayIDs);
|
||||
}
|
||||
#else // SDL2
|
||||
common->Printf("Will use display %u because mouse cursor is at (%d, %d).\n",
|
||||
selectedDisplay, x, y);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif // SDL_VERSION_ATLEAST(2, 0, 4)
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, ENGINE_VERSION);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay));
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay));
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, parms.width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, parms.height);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags);
|
||||
|
||||
// See above for the big comment about Wayland and alpha channels.
|
||||
// When using SDL3 I assume that people usually won't be affected by this bug,
|
||||
// because it's fixed in recent Mesa versions (and also works with the NVIDIA driver).
|
||||
// However, with `r_fillWindowAlphaChan 1` its usage can still be enforced
|
||||
// on Unix-like platforms (I don't think there's a point in this on Windows or Mac)
|
||||
#if defined(__unix__) && !defined(__APPLE__)
|
||||
if ( cvarSystem->GetCVarInteger( "r_fillWindowAlphaChan" ) == 1 ) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
window = SDL_CreateWindowWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (window == NULL) {
|
||||
common->Warning("Couldn't set GL mode %d/%d/%d with %dx MSAA: %s",
|
||||
channelcolorbits, tdepthbits, tstencilbits, parms.multiSamples, SDL_GetError());
|
||||
|
||||
// before trying to reduce color channel size or whatever, first try reducing MSAA, if possible
|
||||
if (multisamples > 1) {
|
||||
multisamples = (multisamples <= 2) ? 0 : (multisamples/2);
|
||||
|
||||
// using goto because enhancing that logic which reduces attributes
|
||||
// based on i (so it'd first try reducing MSAA) would be too painful
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
// creating the window succeeded, so adjust r_multiSamples to the value that was actually used
|
||||
parms.multiSamples = multisamples;
|
||||
r_multiSamples.SetInteger(multisamples);
|
||||
}
|
||||
|
||||
// handle exclusive fullscreen mode (windowed mode and fullscreen
|
||||
// desktop were set when creating the window)
|
||||
// TODO: just call GLimp_SetScreenParms() ?
|
||||
if (parms.fullScreen && !parms.fullScreenDesktop) {
|
||||
SDL_DisplayID displayID = SDL_GetDisplayForWindow( window );
|
||||
SDL_DisplayMode mode = {};
|
||||
if ( SDL_GetClosestFullscreenDisplayMode(displayID, parms.width, parms.height,
|
||||
parms.displayHz, true, &mode) )
|
||||
{
|
||||
if ( ! SDL_SetWindowFullscreenMode(window, &mode) ) {
|
||||
common->Warning("Can't set window fullscreen mode: %s\n", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
window = NULL;
|
||||
return false; // trying other color depth etc is unlikely to help with this issue
|
||||
}
|
||||
|
||||
if ( ! SDL_SetWindowFullscreen(window, true) ) {
|
||||
common->Warning("Can't switch window to fullscreen mode: %s\n", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
window = NULL;
|
||||
return false; // trying other color depth etc is unlikely to help with this issue
|
||||
}
|
||||
} else {
|
||||
common->Warning("Can't get display mode: %s\n", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
window = NULL;
|
||||
return false; // trying other color depth etc is unlikely to help with this issue
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! SDL_SyncWindow(window) ) {
|
||||
common->Warning("SDL_SyncWindow() failed: %s\n", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
window = NULL;
|
||||
return false; // trying other color depth etc is unlikely to help with this issue
|
||||
}
|
||||
|
||||
#else // SDL2
|
||||
window = SDL_CreateWindow(ENGINE_VERSION,
|
||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
|
||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
|
||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay),
|
||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay),
|
||||
parms.width, parms.height, flags);
|
||||
|
||||
if (!window) {
|
||||
|
@ -364,8 +522,8 @@ try_again:
|
|||
common->Warning("Current display mode isn't requested display mode\n");
|
||||
common->Warning("Likely SDL bug #4700, trying to work around it..\n");
|
||||
int dIdx = SDL_GetWindowDisplayIndex(window);
|
||||
if(dIdx != displayIndex) {
|
||||
common->Warning("Window's display index is %d, but we wanted %d!\n", dIdx, displayIndex);
|
||||
if(dIdx != selectedDisplay) {
|
||||
common->Warning("Window's display index is %d, but we wanted %d!\n", dIdx, selectedDisplay);
|
||||
}
|
||||
|
||||
/* Mkay, try to hack around that. */
|
||||
|
@ -413,6 +571,7 @@ try_again:
|
|||
common->Warning("Now we have the requested resolution (%d x %d)\n", parms.width, parms.height);
|
||||
}
|
||||
}
|
||||
#endif // SDL2
|
||||
|
||||
context = SDL_GL_CreateContext(window);
|
||||
|
||||
|
@ -424,7 +583,8 @@ try_again:
|
|||
|
||||
SetSDLIcon(); // for SDL2 this must be done after creating the window
|
||||
|
||||
glConfig.isFullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN;
|
||||
// TODO: also check for fullscreen-desktop?
|
||||
glConfig.isFullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
const char* fsStr = glConfig.isFullscreen ? "fullscreen " : "";
|
||||
if ( (int)glConfig.winWidth != glConfig.vidWidth ) {
|
||||
common->Printf( "Got a HighDPI %swindow with physical resolution %d x %d and virtual resolution %g x %g\n",
|
||||
|
@ -432,7 +592,7 @@ try_again:
|
|||
} else {
|
||||
common->Printf( "Got a %swindow with resolution %g x %g\n", fsStr, glConfig.winWidth, glConfig.winHeight );
|
||||
}
|
||||
#else
|
||||
#else // SDL1.2 window creation
|
||||
SDL_WM_SetCaption(ENGINE_VERSION, ENGINE_VERSION);
|
||||
|
||||
SetSDLIcon(); // for SDL1.2 this must be done before creating the window
|
||||
|
@ -483,6 +643,13 @@ try_again:
|
|||
// then we know we are win32 and we have to include this
|
||||
// config to get the editors to work.
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
HWND hwnd = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
||||
HDC hdc = (HDC)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HDC_POINTER, NULL);
|
||||
if ( hwnd && hdc ) {
|
||||
win32.hWnd = hwnd;
|
||||
win32.hDC = hdc;
|
||||
#else // SDL2
|
||||
// Get the HWND for later use.
|
||||
SDL_SysWMinfo sdlinfo;
|
||||
SDL_version sdlver;
|
||||
|
@ -491,6 +658,7 @@ try_again:
|
|||
if (SDL_GetWindowWMInfo(window, &sdlinfo) && sdlinfo.subsystem == SDL_SYSWM_WINDOWS) {
|
||||
win32.hWnd = sdlinfo.info.win.window;
|
||||
win32.hDC = sdlinfo.info.win.hdc;
|
||||
#endif
|
||||
// NOTE: hInstance is set in main()
|
||||
win32.hGLRC = qwglGetCurrentContext();
|
||||
|
||||
|
@ -592,7 +760,9 @@ try_again:
|
|||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
const char* videoDriver = SDL_GetCurrentVideoDriver();
|
||||
if (idStr::Icmp(videoDriver, "wayland") == 0) {
|
||||
#if SDL_MAJOR_VERSION == 2 // don't enable this hack by default with SDL3
|
||||
glConfig.shouldFillWindowAlpha = true;
|
||||
#endif
|
||||
glConfig.isWayland = true;
|
||||
}
|
||||
#endif
|
||||
|
@ -600,7 +770,11 @@ try_again:
|
|||
glConfig.haveDebugContext = false;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int cflags = 0;
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_CONTEXT_FLAGS, &cflags ) ) {
|
||||
#else // SDL2
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_CONTEXT_FLAGS, &cflags ) == 0 ) {
|
||||
#endif
|
||||
glConfig.haveDebugContext = (cflags & SDL_GL_CONTEXT_DEBUG_FLAG) != 0;
|
||||
if ( glConfig.haveDebugContext )
|
||||
common->Printf( "Got a debug context!\n" );
|
||||
|
@ -648,12 +822,21 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
|
|||
}
|
||||
|
||||
if ( !parms.fullScreen ) { // we want windowed mode
|
||||
if ( curState.fullScreen && SDL_SetWindowFullscreen( window, 0 ) != 0 ) {
|
||||
if ( curState.fullScreen &&
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_SetWindowFullscreen( window, 0 ) == false
|
||||
#else
|
||||
SDL_SetWindowFullscreen( window, 0 ) != 0
|
||||
#endif
|
||||
) {
|
||||
common->Warning( "GLimp_SetScreenParms(): Couldn't switch to windowed mode, SDL error: %s\n", SDL_GetError() );
|
||||
return false;
|
||||
}
|
||||
SDL_RestoreWindow( window ); // make sure we're not maximized, then setting the size wouldn't work
|
||||
SDL_SetWindowSize( window, parms.width, parms.height );
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_SyncWindow( window );
|
||||
#endif
|
||||
} else { // we want some kind of fullscreen mode
|
||||
|
||||
// it's probably safest to first switch to windowed mode
|
||||
|
@ -661,6 +844,60 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
|
|||
SDL_SetWindowFullscreen( window, 0 );
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( wantFullscreenDesktop ) {
|
||||
SDL_SetWindowFullscreenMode( window, NULL ); // setting it to NULL enables fullscreen desktop mode
|
||||
SDL_SetWindowFullscreen( window, true );
|
||||
// TODO: check return values
|
||||
|
||||
if ( ! SDL_SyncWindow( window ) ) {
|
||||
common->Warning( "SDL_SyncWindow() failed: %s\n", SDL_GetError() );
|
||||
//TODO: probably not SDL_DestroyWindow( window );
|
||||
//window = NULL;
|
||||
return false;
|
||||
}
|
||||
} else { // want real fullscreen
|
||||
SDL_DisplayID displayID = SDL_GetDisplayForWindow( window );
|
||||
SDL_DisplayMode mode = {};
|
||||
if ( SDL_GetClosestFullscreenDisplayMode( displayID, parms.width, parms.height,
|
||||
parms.displayHz, true, &mode ) )
|
||||
{
|
||||
if ( ! SDL_SetWindowFullscreenMode( window, &mode ) ) {
|
||||
common->Warning( "Can't set window fullscreen mode: %s\n", SDL_GetError() );
|
||||
//TODO: probably not SDL_DestroyWindow( window );
|
||||
//window = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! SDL_SetWindowFullscreen( window, true ) ) {
|
||||
common->Warning( "Can't switch window to fullscreen mode: %s\n", SDL_GetError() );
|
||||
//TODO: probably not SDL_DestroyWindow( window );
|
||||
//window = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! SDL_SyncWindow( window ) ) {
|
||||
common->Warning( "SDL_SyncWindow() failed: %s\n", SDL_GetError() );
|
||||
//TODO: probably not SDL_DestroyWindow( window );
|
||||
//window = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( parms.displayHz != 0 ) {
|
||||
common->Warning( "Can't get display mode for %d x %d @ %dHz: %s\n", parms.width,
|
||||
parms.height, parms.displayHz, SDL_GetError() );
|
||||
} else {
|
||||
common->Warning( "Can't get display mode for %d x %d: %s\n", parms.width,
|
||||
parms.height, SDL_GetError() );
|
||||
}
|
||||
//TODO: probably not SDL_DestroyWindow( window );
|
||||
//window = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#else // SDL2
|
||||
if ( wantFullscreenDesktop ) {
|
||||
if ( SDL_SetWindowFullscreen( window, SDL_WINDOW_FULLSCREEN_DESKTOP ) != 0 ) {
|
||||
common->Warning( "GLimp_SetScreenParms(): Couldn't switch to fullscreen desktop mode, SDL error: %s\n", SDL_GetError() );
|
||||
|
@ -703,6 +940,7 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
#endif // SDL2
|
||||
}
|
||||
|
||||
glConfig.isFullscreen = (SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
|
@ -722,7 +960,32 @@ glimpParms_t GLimp_GetCurState()
|
|||
glimpParms_t ret = {};
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
My_SDL_WindowFlags winFlags = SDL_GetWindowFlags( window );
|
||||
ret.fullScreen = (winFlags & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
int curMultiSamples = 0;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &curMultiSamples ) && curMultiSamples > 0 ) {
|
||||
if ( ! SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &curMultiSamples ) ) {
|
||||
curMultiSamples = 0; // SDL_GL_GetAttribute() call failed, assume no MSAA
|
||||
}
|
||||
} else {
|
||||
curMultiSamples = 0; // SDL_GL_GetAttribute() call failed, assume no MSAA
|
||||
}
|
||||
|
||||
if (ret.fullScreen) {
|
||||
const SDL_DisplayMode* fullscreenMode = SDL_GetWindowFullscreenMode( window );
|
||||
if (fullscreenMode != NULL) {
|
||||
ret.width = fullscreenMode->w;
|
||||
ret.height = fullscreenMode->h;
|
||||
ret.displayHz = fullscreenMode->refresh_rate;
|
||||
} else {
|
||||
// SDL_WINDOW_FULLSCREEN is set, but SDL_GetWindowFullscreenMode() returns NULL
|
||||
// => fullscreen desktop mode
|
||||
ret.fullScreenDesktop = true;
|
||||
}
|
||||
}
|
||||
#else // SDL2
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &curMultiSamples ) == 0 && curMultiSamples > 0 ) {
|
||||
if ( SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &curMultiSamples ) != 0 ) {
|
||||
curMultiSamples = 0; // SDL_GL_GetAttribute() call failed, assume no MSAA
|
||||
|
@ -730,12 +993,8 @@ glimpParms_t GLimp_GetCurState()
|
|||
} else {
|
||||
curMultiSamples = 0; // SDL_GL_GetAttribute() call failed, assume no MSAA
|
||||
}
|
||||
ret.multiSamples = curMultiSamples;
|
||||
|
||||
Uint32 winFlags = SDL_GetWindowFlags( window );
|
||||
ret.fullScreen = (winFlags & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
ret.fullScreenDesktop = (winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
if ( ret.fullScreen && !ret.fullScreenDesktop ) { // I think SDL_GetWindowDisplayMode() is only for "real" fullscreen?
|
||||
SDL_DisplayMode real_mode = {};
|
||||
if ( SDL_GetWindowDisplayMode( window, &real_mode ) == 0 ) {
|
||||
|
@ -746,7 +1005,11 @@ glimpParms_t GLimp_GetCurState()
|
|||
common->Warning( "GLimp_GetCurState(): Can't get display mode: %s\n", SDL_GetError() );
|
||||
}
|
||||
}
|
||||
if ( ret.width == 0 && ret.height == 0 ) { // windowed mode or SDL_GetWindowDisplayMode() failed
|
||||
#endif
|
||||
|
||||
ret.multiSamples = curMultiSamples;
|
||||
|
||||
if ( ret.width == 0 && ret.height == 0 ) { // windowed mode, fullscreen-desktop mode or SDL_GetWindowDisplayMode() failed
|
||||
SDL_GetWindowSize( window, &ret.width, &ret.height );
|
||||
}
|
||||
|
||||
|
@ -797,11 +1060,14 @@ void GLimp_SwapBuffers() {
|
|||
#endif
|
||||
}
|
||||
|
||||
// SDL3 doesn't support hardware gamma
|
||||
#if ! SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
static bool gammaOrigError = false;
|
||||
static bool gammaOrigSet = false;
|
||||
static unsigned short gammaOrigRed[256];
|
||||
static unsigned short gammaOrigGreen[256];
|
||||
static unsigned short gammaOrigBlue[256];
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -809,6 +1075,12 @@ GLimp_SetGamma
|
|||
=================
|
||||
*/
|
||||
void GLimp_SetGamma(unsigned short red[256], unsigned short green[256], unsigned short blue[256]) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( ! r_gammaInShader.GetBool() ) {
|
||||
common->Warning( "This build of dhewm3 uses SDL3, which does not support hardware gamma." );
|
||||
common->Warning( "If you want to adjust gamma or brightness, enable r_gammaInShader" );
|
||||
}
|
||||
#else // SDL2 and SDL1.2
|
||||
if (!window) {
|
||||
common->Warning("GLimp_SetGamma called without window");
|
||||
return;
|
||||
|
@ -833,6 +1105,7 @@ void GLimp_SetGamma(unsigned short red[256], unsigned short green[256], unsigned
|
|||
if (SDL_SetGammaRamp(red, green, blue))
|
||||
#endif
|
||||
common->Warning("Couldn't set gamma ramp: %s", SDL_GetError());
|
||||
#endif // SDL2 and SDL1.2
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -843,6 +1116,7 @@ Restore original system gamma setting
|
|||
=================
|
||||
*/
|
||||
void GLimp_ResetGamma() {
|
||||
#if ! SDL_VERSION_ATLEAST(3, 0, 0) // only for SDL2 and SDL1.2
|
||||
if( gammaOrigError ) {
|
||||
common->Warning( "Can't reset hardware gamma because getting the Gamma Ramp at startup failed!\n" );
|
||||
common->Warning( "You might have to restart the game for gamma/brightness in shaders to work properly.\n" );
|
||||
|
@ -850,12 +1124,13 @@ void GLimp_ResetGamma() {
|
|||
}
|
||||
|
||||
if( gammaOrigSet ) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_SetWindowGammaRamp( window, gammaOrigRed, gammaOrigGreen, gammaOrigBlue );
|
||||
#else
|
||||
#else
|
||||
SDL_SetGammaRamp( gammaOrigRed, gammaOrigGreen, gammaOrigBlue );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif // ! SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
}
|
||||
|
||||
|
||||
|
@ -893,8 +1168,26 @@ void GLimp_GrabInput(int flags) {
|
|||
common->Warning("GLimp_GrabInput called without window");
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if (flags & GRAB_HIDECURSOR) {
|
||||
SDL_HideCursor();
|
||||
} else {
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
SDL_SetWindowRelativeMouseMode( window, (flags & GRAB_RELATIVEMOUSE) != 0 );
|
||||
if (flags & GRAB_GRABMOUSE) {
|
||||
SDL_SetWindowMouseGrab( window, true );
|
||||
SDL_SetWindowKeyboardGrab( window, in_grabKeyboard.GetBool() );
|
||||
} else {
|
||||
SDL_SetWindowMouseGrab( window, false );
|
||||
SDL_SetWindowKeyboardGrab( window, false );
|
||||
}
|
||||
if (flags & GRAB_ENABLETEXTINPUT) {
|
||||
SDL_StartTextInput( window );
|
||||
} else {
|
||||
SDL_StopTextInput( window );
|
||||
}
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_ShowCursor( (flags & GRAB_HIDECURSOR) ? SDL_DISABLE : SDL_ENABLE );
|
||||
SDL_SetRelativeMouseMode( (flags & GRAB_RELATIVEMOUSE) ? SDL_TRUE : SDL_FALSE );
|
||||
SDL_SetWindowGrab( window, (flags & GRAB_GRABMOUSE) ? SDL_TRUE : SDL_FALSE );
|
||||
|
@ -909,7 +1202,11 @@ void GLimp_GrabInput(int flags) {
|
|||
bool GLimp_SetSwapInterval( int swapInterval )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( ! SDL_GL_SetSwapInterval( swapInterval ) ) {
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if ( SDL_GL_SetSwapInterval( swapInterval ) < 0 ) {
|
||||
#endif
|
||||
common->Warning( "SDL_GL_SetSwapInterval( %d ) not supported", swapInterval );
|
||||
return false;
|
||||
}
|
||||
|
@ -922,7 +1219,10 @@ bool GLimp_SetSwapInterval( int swapInterval )
|
|||
|
||||
bool GLimp_SetWindowResizable( bool enableResizable )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_SetWindowResizable( window, enableResizable );
|
||||
return true;
|
||||
#elif SDL_VERSION_ATLEAST(2, 0, 5)
|
||||
SDL_SetWindowResizable( window, (SDL_bool)enableResizable );
|
||||
return true;
|
||||
#else
|
||||
|
@ -934,7 +1234,18 @@ bool GLimp_SetWindowResizable( bool enableResizable )
|
|||
void GLimp_UpdateWindowSize()
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
Uint32 winFlags = SDL_GetWindowFlags( window );
|
||||
My_SDL_WindowFlags winFlags = SDL_GetWindowFlags( window );
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_GetWindowSizeInPixels( window, &glConfig.vidWidth, &glConfig.vidHeight );
|
||||
|
||||
const SDL_DisplayMode* fullscreenMode = SDL_GetWindowFullscreenMode( window );
|
||||
if ( (winFlags & SDL_WINDOW_FULLSCREEN) != 0 && fullscreenMode != NULL) {
|
||||
glConfig.winWidth = fullscreenMode->w;
|
||||
glConfig.winHeight = fullscreenMode->h;
|
||||
}
|
||||
#else // SDL2
|
||||
SDL_GL_GetDrawableSize( window, &glConfig.vidWidth, &glConfig.vidHeight );
|
||||
if ( (winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN ) {
|
||||
// real fullscreen mode => must use SDL_GetWindowDisplayMode()
|
||||
// TODO: well, theoretically SDL_GetWindowSize() should work for fullscreen mode as well,
|
||||
|
@ -951,13 +1262,13 @@ void GLimp_UpdateWindowSize()
|
|||
} else {
|
||||
common->Warning( "GLimp_UpdateWindowSize(): SDL_GetWindowDisplayMode() failed: %s\n", SDL_GetError() );
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
#endif // SDL2
|
||||
else {
|
||||
int ww=0, wh=0;
|
||||
SDL_GetWindowSize( window, &ww, &wh );
|
||||
glConfig.winWidth = ww;
|
||||
glConfig.winHeight = wh;
|
||||
}
|
||||
SDL_GL_GetDrawableSize( window, &glConfig.vidWidth, &glConfig.vidHeight );
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <SDL_main.h>
|
||||
//#include <SDL_main.h> - not needed, dhewm3 doesn't currently use SDL's SDL_main
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "framework/Licensee.h"
|
||||
|
|
|
@ -32,9 +32,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include <fenv.h>
|
||||
#include <mach/thread_status.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include <SDL_main.h>
|
||||
|
||||
#include "sys/platform.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -45,6 +42,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "sys/posix/posix_public.h"
|
||||
|
||||
// usually the following would be from SDL_main.h,
|
||||
// but this way we should be able to avoid that header
|
||||
// for better compatibility between SDL1.2 to SDL3
|
||||
extern "C" int SDL_main( int argc, char *argv[] );
|
||||
|
||||
static char base_path[MAXPATHLEN];
|
||||
static char exe_path[MAXPATHLEN];
|
||||
static char save_path[MAXPATHLEN];
|
||||
|
@ -194,13 +196,15 @@ int SDL_main( int argc, char *argv[] ) {
|
|||
Sys_Error("Could not access application resources");
|
||||
|
||||
// DG: set exe_path so Posix_InitSignalHandlers() can call Posix_GetExePath()
|
||||
SDL_strlcpy(exe_path, [ [ [ NSBundle mainBundle ] bundlePath ] cStringUsingEncoding:NSUTF8StringEncoding ], sizeof(exe_path));
|
||||
strncpy(exe_path, [ [ [ NSBundle mainBundle ] bundlePath ] cStringUsingEncoding:NSUTF8StringEncoding ], sizeof(exe_path)-1);
|
||||
exe_path[sizeof(exe_path)-1] = '\0';
|
||||
// same for save_path for Posix_GetSavePath()
|
||||
D3_snprintfC99(save_path, sizeof(save_path), "%s/Library/Application Support/dhewm3", [NSHomeDirectory() cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
// and preinitializing basepath is easy enough so do that as well
|
||||
{
|
||||
char* snap;
|
||||
SDL_strlcpy(base_path, exe_path, sizeof(base_path));
|
||||
strncpy(base_path, exe_path, sizeof(base_path)-1);
|
||||
base_path[sizeof(base_path)-1] = '\0';
|
||||
snap = strrchr(base_path, '/');
|
||||
if (snap)
|
||||
*snap = '\0';
|
||||
|
|
|
@ -10,7 +10,15 @@
|
|||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
#ifdef D3_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
// as SDL.h doesn't implicitly include SDL_main.h anymore,
|
||||
// declare SDL_main() here. I think it's the only part of SDL_main.h we used,
|
||||
// we implement it in DOOMController.mm an call it here in applicationDidFinishLaunching
|
||||
extern "C" int SDL_main( int argc, char *argv[] );
|
||||
#else // SDL2 and SDL1.2
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
#include "SDLMain.h"
|
||||
#include <sys/param.h> /* for MAXPATHLEN */
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -49,7 +49,9 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "sys/posix/posix_public.h"
|
||||
|
||||
#include <SDL.h> // clipboard
|
||||
// SDL.h for clipboard:
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
|
||||
#define COMMAND_HISTORY 64
|
||||
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#include <SDL.h>
|
||||
#include "sys_sdl.h"
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// compat with SDL2
|
||||
#define SDL_TEXTINPUT SDL_EVENT_TEXT_INPUT
|
||||
#define SDL_CONTROLLERAXISMOTION SDL_EVENT_GAMEPAD_AXIS_MOTION
|
||||
#define SDL_CONTROLLERBUTTONDOWN SDL_EVENT_GAMEPAD_BUTTON_DOWN
|
||||
#define SDL_MOUSEBUTTONDOWN SDL_EVENT_MOUSE_BUTTON_DOWN
|
||||
#define SDL_MOUSEMOTION SDL_EVENT_MOUSE_MOTION
|
||||
#define SDL_MOUSEWHEEL SDL_EVENT_MOUSE_WHEEL
|
||||
#define SDL_KEYDOWN SDL_EVENT_KEY_DOWN
|
||||
#endif
|
||||
|
||||
|
||||
#include "sys_imgui.h"
|
||||
|
||||
|
@ -13,7 +25,20 @@ typedef char* (*MY_XGETDEFAULTFUN)(Display*, const char*, const char*);
|
|||
#endif
|
||||
|
||||
#include "../libs/imgui/backends/imgui_impl_opengl2.h"
|
||||
#include "../libs/imgui/backends/imgui_impl_sdl2.h"
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
#include "../libs/imgui/backends/imgui_impl_sdl3.h"
|
||||
#define ImGui_ImplSDLx_InitForOpenGL ImGui_ImplSDL3_InitForOpenGL
|
||||
#define ImGui_ImplSDLx_Shutdown ImGui_ImplSDL3_Shutdown
|
||||
#define ImGui_ImplSDLx_NewFrame ImGui_ImplSDL3_NewFrame
|
||||
#define ImGui_ImplSDLx_ProcessEvent ImGui_ImplSDL3_ProcessEvent
|
||||
#else
|
||||
#include "../libs/imgui/backends/imgui_impl_sdl2.h"
|
||||
#define ImGui_ImplSDLx_InitForOpenGL ImGui_ImplSDL2_InitForOpenGL
|
||||
#define ImGui_ImplSDLx_Shutdown ImGui_ImplSDL2_Shutdown
|
||||
#define ImGui_ImplSDLx_NewFrame ImGui_ImplSDL2_NewFrame
|
||||
#define ImGui_ImplSDLx_ProcessEvent ImGui_ImplSDL2_ProcessEvent
|
||||
#endif
|
||||
|
||||
#include "framework/Common.h"
|
||||
#include "framework/KeyInput.h"
|
||||
|
@ -145,7 +170,7 @@ void ShowWarningOverlay( const char* text )
|
|||
warningOverlayStartPos = ImGui::GetMousePos();
|
||||
}
|
||||
|
||||
|
||||
#if SDL_MAJOR_VERSION == 2 // not used with SDL3
|
||||
static float GetDefaultDPI()
|
||||
{
|
||||
SDL_Window* win = sdlWindow;
|
||||
|
@ -185,6 +210,7 @@ static float GetDefaultDPI()
|
|||
}
|
||||
return dpi;
|
||||
}
|
||||
#endif // SDL2-only
|
||||
|
||||
static float GetDefaultScale()
|
||||
{
|
||||
|
@ -192,8 +218,13 @@ static float GetDefaultScale()
|
|||
// in HighDPI mode, the font sizes are already scaled (to window coordinates), apparently
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
float ret = SDL_GetWindowDisplayScale( sdlWindow );
|
||||
#else
|
||||
// TODO: different reference DPI on mac? also, doesn't work that well on my laptop..
|
||||
float ret = GetDefaultDPI() / 96.0f;
|
||||
#endif
|
||||
ret = round(ret*2.0)*0.5; // round to .0 or .5
|
||||
return ret;
|
||||
}
|
||||
|
@ -250,7 +281,7 @@ bool Init(void* _sdlWindow, void* sdlGlContext)
|
|||
imgui_scale.SetModified(); // so NewFrame() will load the scaled font
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
if ( ! ImGui_ImplSDL2_InitForOpenGL( sdlWindow, sdlGlContext ) ) {
|
||||
if ( ! ImGui_ImplSDLx_InitForOpenGL( sdlWindow, sdlGlContext ) ) {
|
||||
ImGui::DestroyContext( imguiCtx );
|
||||
imguiCtx = NULL;
|
||||
common->Warning( "Failed to initialize ImGui SDL platform backend!\n" );
|
||||
|
@ -258,7 +289,7 @@ bool Init(void* _sdlWindow, void* sdlGlContext)
|
|||
}
|
||||
|
||||
if ( ! ImGui_ImplOpenGL2_Init() ) {
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui_ImplSDLx_Shutdown();
|
||||
ImGui::DestroyContext( imguiCtx );
|
||||
imguiCtx = NULL;
|
||||
common->Warning( "Failed to initialize ImGui OpenGL renderer backend!\n" );
|
||||
|
@ -302,7 +333,7 @@ void Shutdown()
|
|||
|
||||
// TODO: only if init was successful!
|
||||
ImGui_ImplOpenGL2_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui_ImplSDLx_Shutdown();
|
||||
ImGui::DestroyContext( imguiCtx );
|
||||
imgui_initialized = false;
|
||||
}
|
||||
|
@ -345,7 +376,7 @@ void NewFrame()
|
|||
else
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
|
||||
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui_ImplSDLx_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
haveNewFrame = true;
|
||||
|
||||
|
@ -379,7 +410,7 @@ bool ProcessEvent(const void* sdlEvent)
|
|||
// - 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.
|
||||
|
||||
bool imguiUsedEvent = ImGui_ImplSDL2_ProcessEvent( ev );
|
||||
bool imguiUsedEvent = ImGui_ImplSDLx_ProcessEvent( ev );
|
||||
if ( keybindModeEnabled ) {
|
||||
// in keybind mode, all input events are passed to Doom3 so it can translate them
|
||||
// to internal events and we can access and use them to create a new binding
|
||||
|
@ -424,7 +455,11 @@ bool ProcessEvent(const void* sdlEvent)
|
|||
return true;
|
||||
case SDL_KEYDOWN:
|
||||
//case SDL_KEYUP: NOTE: see above why key up events are passed to the engine
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if ( ev->key.key < SDLK_F1 || ev->key.key > SDLK_F12) {
|
||||
#else
|
||||
if ( ev->key.keysym.sym < SDLK_F1 || ev->key.keysym.sym > SDLK_F12) {
|
||||
#endif
|
||||
// F1 - F12 are passed to the engine so its shortcuts
|
||||
// (like quickload or screenshot) still work
|
||||
// Doom3's menu does the same
|
||||
|
|
14
neo/sys/sys_sdl.h
Normal file
14
neo/sys/sys_sdl.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// just a wrapper for #include <SDL.h> to support SDL1.2, SDL2 and SDL3
|
||||
|
||||
#ifndef NEO_SYS_SYS_SDL_H_
|
||||
#define NEO_SYS_SYS_SDL_H_
|
||||
|
||||
#ifdef D3_SDL3
|
||||
// HACK: I don't want SDL.h to drag in SDL_oldnames.h to avoid all the warnings about redefined definitions
|
||||
#define SDL_oldnames_h_
|
||||
#include <SDL3/SDL.h>
|
||||
#else // SDL1.2 or SDL2
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#endif /* NEO_SYS_SYS_SDL_H_ */
|
|
@ -26,10 +26,14 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <SDL_version.h>
|
||||
#include <SDL_mutex.h>
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_timer.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#if 0 // TODO: was there a reason not to include full SDL.h?
|
||||
#include <SDL_version.h>
|
||||
#include <SDL_mutex.h>
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_timer.h>
|
||||
#endif
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "framework/Common.h"
|
||||
|
@ -40,6 +44,15 @@ If you have questions concerning this license or the applicable additional terms
|
|||
// SDL1.2 doesn't have SDL_threadID but uses Uint32.
|
||||
// this typedef helps using the same code for SDL1.2 and SDL2
|
||||
typedef Uint32 SDL_threadID;
|
||||
#elif SDL_MAJOR_VERSION >= 3
|
||||
// backwards-compat with SDL2
|
||||
#define SDL_mutex SDL_Mutex
|
||||
#define SDL_cond SDL_Condition
|
||||
#define SDL_threadID SDL_ThreadID
|
||||
#define SDL_CreateCond SDL_CreateCondition
|
||||
#define SDL_DestroyCond SDL_DestroyCondition
|
||||
#define SDL_CondWait SDL_WaitCondition
|
||||
#define SDL_CondSignal SDL_SignalCondition
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103
|
||||
|
@ -159,8 +172,12 @@ Sys_EnterCriticalSection
|
|||
void Sys_EnterCriticalSection(int index) {
|
||||
assert(index >= 0 && index < MAX_CRITICAL_SECTIONS);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_LockMutex(mutex[index]); // in SDL3, this returns void and can't fail
|
||||
#else // SDL2 and SDL1.2
|
||||
if (SDL_LockMutex(mutex[index]) != 0)
|
||||
common->Error("ERROR: SDL_LockMutex failed\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -171,8 +188,12 @@ Sys_LeaveCriticalSection
|
|||
void Sys_LeaveCriticalSection(int index) {
|
||||
assert(index >= 0 && index < MAX_CRITICAL_SECTIONS);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_UnlockMutex(mutex[index]); // in SDL3, this returns void and can't fail
|
||||
#else // SDL2 and SDL1.2
|
||||
if (SDL_UnlockMutex(mutex[index]) != 0)
|
||||
common->Error("ERROR: SDL_UnlockMutex failed\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,8 +225,12 @@ void Sys_WaitForEvent(int index) {
|
|||
signaled[index] = false;
|
||||
} else {
|
||||
waiting[index] = true;
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_CondWait(cond[index], mutex[CRITICAL_SECTION_SYS]); // in SDL3, this returns void and can't fail
|
||||
#else // SDL2 and SDL1.2
|
||||
if (SDL_CondWait(cond[index], mutex[CRITICAL_SECTION_SYS]) != 0)
|
||||
common->Error("ERROR: SDL_CondWait failed\n");
|
||||
#endif
|
||||
waiting[index] = false;
|
||||
}
|
||||
|
||||
|
@ -223,8 +248,12 @@ void Sys_TriggerEvent(int index) {
|
|||
Sys_EnterCriticalSection(CRITICAL_SECTION_SYS);
|
||||
|
||||
if (waiting[index]) {
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_CondSignal(cond[index]); // in SDL3, this returns void and can't fail
|
||||
#else // SDL2 and SDL1.2
|
||||
if (SDL_CondSignal(cond[index]) != 0)
|
||||
common->Error("ERROR: SDL_CondSignal failed\n");
|
||||
#endif
|
||||
} else {
|
||||
// emulate windows behaviour: if no thread is waiting, leave the signal on so next wait keeps going
|
||||
signaled[index] = true;
|
||||
|
|
|
@ -160,154 +160,6 @@ static void cleanup(void)
|
|||
SDL_Quit();
|
||||
}
|
||||
|
||||
/* Remove the output files if there was no output written */
|
||||
static void cleanup_output(void) {
|
||||
FILE *file;
|
||||
int empty;
|
||||
|
||||
/* Flush the output in case anything is queued */
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
|
||||
/* Without redirection we're done */
|
||||
if (!stdioRedirectEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if the files have any output in them */
|
||||
if ( stdoutPath[0] ) {
|
||||
file = fopen(stdoutPath, TEXT("rb"));
|
||||
if ( file ) {
|
||||
empty = (fgetc(file) == EOF) ? 1 : 0;
|
||||
fclose(file);
|
||||
if ( empty ) {
|
||||
remove(stdoutPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( stderrPath[0] ) {
|
||||
file = fopen(stderrPath, TEXT("rb"));
|
||||
if ( file ) {
|
||||
empty = (fgetc(file) == EOF) ? 1 : 0;
|
||||
fclose(file);
|
||||
if ( empty ) {
|
||||
remove(stderrPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern int Win_GetHomeDir(char *dst, size_t size);
|
||||
|
||||
/* Redirect the output (stdout and stderr) to a file */
|
||||
static void redirect_output(void)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
wchar_t path[MAX_PATH];
|
||||
#error "adapt homedir code for wchar_t!"
|
||||
#else
|
||||
char path[MAX_PATH];
|
||||
struct _stat st;
|
||||
|
||||
/* DG: use "My Documents/My Games/dhewm3" to write stdout.txt and stderr.txt
|
||||
* instead of the binary, which might not be writable */
|
||||
Win_GetHomeDir(path, sizeof(path));
|
||||
|
||||
if (_stat(path, &st) == -1) {
|
||||
/* oops, "My Documents/My Games/dhewm3" doesn't exist - does My Games/ at least exist? */
|
||||
char myGamesPath[MAX_PATH];
|
||||
char* lastslash;
|
||||
memcpy(myGamesPath, path, MAX_PATH);
|
||||
lastslash = strrchr(myGamesPath, '/');
|
||||
if (lastslash != NULL) {
|
||||
*lastslash = '\0';
|
||||
}
|
||||
if (_stat(myGamesPath, &st) == -1) {
|
||||
/* if My Documents/My Games/ doesn't exist, create it */
|
||||
_mkdir(myGamesPath);
|
||||
}
|
||||
|
||||
_mkdir(path); /* create My Documents/My Games/dhewm3/ */
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
FILE *newfp;
|
||||
|
||||
#if 0 /* DG: don't do this anymore. */
|
||||
DWORD pathlen;
|
||||
pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path));
|
||||
while ( pathlen > 0 && path[pathlen] != '\\' ) {
|
||||
--pathlen;
|
||||
}
|
||||
path[pathlen] = '\0';
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
wcsncpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
|
||||
wcsncat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
|
||||
#else
|
||||
SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
|
||||
SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
|
||||
#endif
|
||||
|
||||
{ /* DG: rename old stdout log */
|
||||
#ifdef _WIN32_WCE
|
||||
wchar_t stdoutPathBK[MAX_PATH];
|
||||
wcsncpy( stdoutPathBK, path, SDL_arraysize(stdoutPath) );
|
||||
wcsncat( stdoutPathBK, DIR_SEPERATOR TEXT("dhewm3log-old.txt"), SDL_arraysize(stdoutPath) );
|
||||
_wrename( stdoutPath, stdoutpathBK );
|
||||
#else
|
||||
char stdoutPathBK[MAX_PATH];
|
||||
SDL_strlcpy( stdoutPathBK, path, SDL_arraysize(stdoutPath) );
|
||||
SDL_strlcat( stdoutPathBK, DIR_SEPERATOR TEXT("dhewm3log-old.txt"), SDL_arraysize(stdoutPath) );
|
||||
rename( stdoutPath, stdoutPathBK );
|
||||
#endif
|
||||
} /* DG end */
|
||||
|
||||
/* Redirect standard input and standard output */
|
||||
newfp = freopen(stdoutPath, TEXT("w"), stdout);
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
if ( newfp == NULL ) { /* This happens on NT */
|
||||
#if !defined(stdout)
|
||||
stdout = fopen(stdoutPath, TEXT("w"));
|
||||
#else
|
||||
newfp = fopen(stdoutPath, TEXT("w"));
|
||||
if ( newfp ) {
|
||||
*stdout = *newfp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
wcsncpy( stderrPath, path, SDL_arraysize(stdoutPath) );
|
||||
wcsncat( stderrPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
|
||||
#else
|
||||
SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) );
|
||||
SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) );
|
||||
#endif
|
||||
|
||||
newfp = freopen(stderrPath, TEXT("w"), stderr);
|
||||
#ifndef _WIN32_WCE
|
||||
if ( newfp == NULL ) { /* This happens on NT */
|
||||
#if !defined(stderr)
|
||||
stderr = fopen(stderrPath, TEXT("w"));
|
||||
#else
|
||||
newfp = fopen(stderrPath, TEXT("w"));
|
||||
if ( newfp ) {
|
||||
*stderr = *newfp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */
|
||||
setbuf(stderr, NULL); /* No buffering */
|
||||
stdioRedirectEnabled = 1;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
|
||||
/* The VC++ compiler needs main defined */
|
||||
#define console_main main
|
||||
|
@ -397,6 +249,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|||
FreeLibrary(handle);
|
||||
}
|
||||
|
||||
#if 0 // DG: output redirection is now done in dhewm3's main() aka SDL_main()
|
||||
/* Check for stdio redirect settings and do the redirection */
|
||||
if ((env_str = SDL_getenv("SDL_STDIO_REDIRECT"))) {
|
||||
if (SDL_atoi(env_str)) {
|
||||
|
@ -408,6 +261,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|||
redirect_output();
|
||||
}
|
||||
#endif
|
||||
#endif // 0
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
nLen = wcslen(szCmdLine)+128+1;
|
||||
|
|
|
@ -53,7 +53,15 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "tools/edit_public.h"
|
||||
|
||||
#include <SDL_main.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#ifdef D3_SDL3
|
||||
#define SDL_MAIN_HANDLED // dhewm3 implements WinMain() itself
|
||||
#include <SDL3/SDL_main.h>
|
||||
#else // SDL1.2 or SDL2
|
||||
#include <SDL_main.h>
|
||||
#endif
|
||||
|
||||
|
||||
idCVar Win32Vars_t::win_outputDebugString( "win_outputDebugString", "0", CVAR_SYSTEM | CVAR_BOOL, "" );
|
||||
idCVar Win32Vars_t::win_outputEditString( "win_outputEditString", "1", CVAR_SYSTEM | CVAR_BOOL, "" );
|
||||
|
@ -1001,14 +1009,154 @@ int Win_ChoosePixelFormat(HDC hdc)
|
|||
}
|
||||
#endif
|
||||
|
||||
// stdout/stderr redirection, originally from SDL_win32_main.c
|
||||
|
||||
/* The standard output files */
|
||||
#define STDOUT_FILE TEXT("dhewm3log.txt") /* DG: renamed this */
|
||||
#define STDERR_FILE TEXT("stderr.txt")
|
||||
|
||||
/* Set a variable to tell if the stdio redirect has been enabled. */
|
||||
static int stdioRedirectEnabled = 0;
|
||||
static char stdoutPath[MAX_PATH];
|
||||
static char stderrPath[MAX_PATH];
|
||||
#define DIR_SEPERATOR TEXT("/")
|
||||
|
||||
|
||||
/* Remove the output files if there was no output written */
|
||||
static void cleanup_output(void) {
|
||||
FILE *file;
|
||||
int empty;
|
||||
|
||||
/* Flush the output in case anything is queued */
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
|
||||
/* Without redirection we're done */
|
||||
if (!stdioRedirectEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if the files have any output in them */
|
||||
if ( stdoutPath[0] ) {
|
||||
file = fopen(stdoutPath, TEXT("rb"));
|
||||
if ( file ) {
|
||||
empty = (fgetc(file) == EOF) ? 1 : 0;
|
||||
fclose(file);
|
||||
if ( empty ) {
|
||||
remove(stdoutPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( stderrPath[0] ) {
|
||||
file = fopen(stderrPath, TEXT("rb"));
|
||||
if ( file ) {
|
||||
empty = (fgetc(file) == EOF) ? 1 : 0;
|
||||
fclose(file);
|
||||
if ( empty ) {
|
||||
remove(stderrPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Redirect the output (stdout and stderr) to a file */
|
||||
static void redirect_output(void)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
struct _stat st;
|
||||
|
||||
/* DG: use "My Documents/My Games/dhewm3" to write stdout.txt and stderr.txt
|
||||
* instead of the binary, which might not be writable */
|
||||
Win_GetHomeDir(path, sizeof(path));
|
||||
|
||||
if (_stat(path, &st) == -1) {
|
||||
/* oops, "My Documents/My Games/dhewm3" doesn't exist - does My Games/ at least exist? */
|
||||
char myGamesPath[MAX_PATH];
|
||||
char* lastslash;
|
||||
memcpy(myGamesPath, path, MAX_PATH);
|
||||
lastslash = strrchr(myGamesPath, '/');
|
||||
if (lastslash != NULL) {
|
||||
*lastslash = '\0';
|
||||
}
|
||||
if (_stat(myGamesPath, &st) == -1) {
|
||||
/* if My Documents/My Games/ doesn't exist, create it */
|
||||
_mkdir(myGamesPath);
|
||||
}
|
||||
|
||||
_mkdir(path); /* create My Documents/My Games/dhewm3/ */
|
||||
}
|
||||
|
||||
FILE *newfp;
|
||||
|
||||
#if 0 /* DG: don't do this anymore. */
|
||||
DWORD pathlen;
|
||||
pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path));
|
||||
while ( pathlen > 0 && path[pathlen] != '\\' ) {
|
||||
--pathlen;
|
||||
}
|
||||
path[pathlen] = '\0';
|
||||
#endif
|
||||
|
||||
SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
|
||||
SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
|
||||
|
||||
{ /* DG: rename old stdout log */
|
||||
char stdoutPathBK[MAX_PATH];
|
||||
SDL_strlcpy( stdoutPathBK, path, SDL_arraysize(stdoutPath) );
|
||||
SDL_strlcat( stdoutPathBK, DIR_SEPERATOR TEXT("dhewm3log-old.txt"), SDL_arraysize(stdoutPath) );
|
||||
rename( stdoutPath, stdoutPathBK );
|
||||
} /* DG end */
|
||||
|
||||
/* Redirect standard input and standard output */
|
||||
newfp = freopen(stdoutPath, TEXT("w"), stdout);
|
||||
|
||||
if ( newfp == NULL ) { /* This happens on NT */
|
||||
#if !defined(stdout)
|
||||
stdout = fopen(stdoutPath, TEXT("w"));
|
||||
#else
|
||||
newfp = fopen(stdoutPath, TEXT("w"));
|
||||
if ( newfp ) {
|
||||
*stdout = *newfp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) );
|
||||
SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) );
|
||||
|
||||
newfp = freopen(stderrPath, TEXT("w"), stderr);
|
||||
if ( newfp == NULL ) { /* This happens on NT */
|
||||
#if !defined(stderr)
|
||||
stderr = fopen(stderrPath, TEXT("w"));
|
||||
#else
|
||||
newfp = fopen(stderrPath, TEXT("w"));
|
||||
if ( newfp ) {
|
||||
*stderr = *newfp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */
|
||||
setbuf(stderr, NULL); /* No buffering */
|
||||
stdioRedirectEnabled = 1;
|
||||
}
|
||||
|
||||
// end of stdout/stderr redirection code from old SDL
|
||||
|
||||
/*
|
||||
==================
|
||||
WinMain
|
||||
The pseudo-main function called from real main (either in SDL_win32_main.c or WinMain() below)
|
||||
NOTE: Currently argv[] are ANSI strings, not UTF-8 strings as usual in SDL2 and SDL3!
|
||||
==================
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
// SDL_win32_main.c creates the dhewm3log.txt and redirects stdout into it
|
||||
// so here we can log its (approx.) creation time before anything else is logged:
|
||||
int SDL_main(int argc, char *argv[]) {
|
||||
// as the very first thing, redirect stdout to dhewm3log.txt (and stderr to stderr.txt)
|
||||
// so we can log
|
||||
redirect_output();
|
||||
atexit(cleanup_output);
|
||||
|
||||
// now that stdout is redirected to dhewm3log.txt,
|
||||
// log its (approx.) creation time before anything else is logged:
|
||||
{
|
||||
time_t tt = time(NULL);
|
||||
const struct tm* tms = localtime(&tt);
|
||||
|
@ -1017,8 +1165,6 @@ int main(int argc, char *argv[]) {
|
|||
printf("Opened this log at %s\n", timeStr);
|
||||
}
|
||||
|
||||
const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) );
|
||||
|
||||
InitializeCriticalSection( &printfCritSect );
|
||||
|
||||
#ifdef ID_DEDICATED
|
||||
|
@ -1065,8 +1211,6 @@ int main(int argc, char *argv[]) {
|
|||
SetThreadAffinityMask( GetCurrentThread(), 1 );
|
||||
#endif
|
||||
|
||||
// ::SetCursor( hcurSave ); // DG: I think SDL handles the cursor fine..
|
||||
|
||||
// Launch the script debugger
|
||||
if ( strstr( GetCommandLine(), "+debugger" ) ) {
|
||||
|
||||
|
@ -1204,3 +1348,80 @@ void idSysLocal::StartProcess( const char *exePath, bool doexit ) {
|
|||
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit\n" );
|
||||
}
|
||||
}
|
||||
|
||||
// the actual WinMain(), based on SDL2_main and SDL3's SDL_main_impl.h + SDL_RunApp()
|
||||
// but modified to pass ANSI strings to SDL_main() instead of UTF-8,
|
||||
// because dhewm3 doesn't use Unicode internally (except for Dear ImGui,
|
||||
// which doesn't use commandline arguments)
|
||||
// for SDL1.2, SDL_win32_main.c is still used instead
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
||||
/* Pop up an out of memory message, returns to Windows */
|
||||
static BOOL OutOfMemory(void)
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
||||
{
|
||||
(void)hInst;
|
||||
(void)hPrev;
|
||||
(void)szCmdLine;
|
||||
(void)sw;
|
||||
|
||||
LPWSTR *argvw;
|
||||
char **argv;
|
||||
int i, argc, result;
|
||||
|
||||
argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
if (!argvw) {
|
||||
return OutOfMemory();
|
||||
}
|
||||
|
||||
/* Note that we need to be careful about how we allocate/free memory here.
|
||||
* If the application calls SDL_SetMemoryFunctions(), we can't rely on
|
||||
* SDL_free() to use the same allocator after SDL_main() returns.
|
||||
*/
|
||||
|
||||
/* Parse it into argv and argc */
|
||||
argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
|
||||
if (!argv) {
|
||||
return OutOfMemory();
|
||||
}
|
||||
for (i = 0; i < argc; ++i) {
|
||||
// NOTE: SDL2+ uses CP_UTF8 instead of CP_ACP here (and in the other call below)
|
||||
// but Doom3 needs ANSI strings on Windows (so paths work with the Windows ANSI APIs)
|
||||
const int ansiSize = WideCharToMultiByte(CP_ACP, 0, argvw[i], -1, NULL, 0, NULL, NULL);
|
||||
if (!ansiSize) { // uhoh?
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ansiSize); // this size includes the null-terminator character.
|
||||
if (!argv[i]) {
|
||||
return OutOfMemory();
|
||||
}
|
||||
|
||||
if (WideCharToMultiByte(CP_ACP, 0, argvw[i], -1, argv[i], ansiSize, NULL, NULL) == 0) { // failed? uhoh!
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
argv[i] = NULL;
|
||||
LocalFree(argvw);
|
||||
|
||||
SDL_SetMainReady();
|
||||
|
||||
// Run the application main() code
|
||||
result = SDL_main(argc, argv);
|
||||
|
||||
// Free argv, to avoid memory leak
|
||||
for (i = 0; i < argc; ++i) {
|
||||
HeapFree(GetProcessHeap(), 0, argv[i]);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,14 @@ If you have questions concerning this license or the applicable additional terms
|
|||
const int MAX_MSGLEN = 8600;
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// compat with SDL2
|
||||
#define SDL_CreateCond SDL_CreateCondition
|
||||
#define SDL_DestroyCond SDL_DestroyCondition
|
||||
#define SDL_CondWait SDL_WaitCondition
|
||||
#define SDL_CondSignal SDL_SignalCondition
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::rvDebuggerServer
|
||||
|
|
|
@ -28,13 +28,20 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#ifndef DEBUGGERSERVER_H_
|
||||
#define DEBUGGERSERVER_H_
|
||||
|
||||
#include <SDL.h>
|
||||
#include "sys/sys_sdl.h"
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/Str.h"
|
||||
#include "DebuggerMessages.h"
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#include "framework/Game.h"
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
// backwards-compat with SDL <= 2
|
||||
#define SDL_mutex SDL_Mutex
|
||||
#define SDL_cond SDL_Condition
|
||||
#endif
|
||||
|
||||
class function_t;
|
||||
typedef struct prstack_s prstack_t;
|
||||
|
||||
|
|
Loading…
Reference in a new issue