diff --git a/.github/workflows/Linux_x86_64_SDL3_test.yml b/.github/workflows/Linux_x86_64_SDL3_test.yml index fd9d2bfd9..ee7048e4e 100644 --- a/.github/workflows/Linux_x86_64_SDL3_test.yml +++ b/.github/workflows/Linux_x86_64_SDL3_test.yml @@ -36,8 +36,8 @@ jobs: uses: actions/cache@v4 with: path: build - key: ${{ github.workflow }}-v2-${{ github.sha }} - restore-keys: ${{ github.workflow }}-v2- + key: ${{ github.workflow }}-v3-${{ github.sha }} + restore-keys: ${{ github.workflow }}-v3- # We specify `-DDEVILUTIONX_SYSTEM_BENCHMARK=OFF` to work around the following error: # lto1: fatal error: bytecode stream in file ‘/usr/lib/x86_64-linux-gnu/libbenchmark_main.a’ generated with LTO version 11.2 instead of the expected 11.3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 21a014c29..4cf2b8a9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,7 +112,12 @@ endif() # Graphics options if(NOT USE_SDL1) - set(DEVILUTIONX_DISPLAY_TEXTURE_FORMAT "SDL_PIXELFORMAT_RGB888" CACHE STRING "Texture format for DevilutionX textures when using the GPU renderer") +if(USE_SDL3) + set(_texture_format_default "SDL_PIXELFORMAT_XRGB8888") +else() + set(_texture_format_default "SDL_PIXELFORMAT_RGB888") +endif() + set(DEVILUTIONX_DISPLAY_TEXTURE_FORMAT "${_texture_format_default}" CACHE STRING "Texture format for DevilutionX textures when using the GPU renderer") mark_as_advanced(DEVILUTIONX_DISPLAY_TEXTURE_FORMAT) endif() diff --git a/Source/DiabloUI/button.cpp b/Source/DiabloUI/button.cpp index 8d4c8c813..07ddc6d98 100644 --- a/Source/DiabloUI/button.cpp +++ b/Source/DiabloUI/button.cpp @@ -2,7 +2,12 @@ #include +#ifdef USE_SDL3 +#include +#include +#else #include +#endif #include "DiabloUI/diabloui.h" #include "DiabloUI/ui_flags.hpp" @@ -60,13 +65,21 @@ bool HandleMouseEventButton(const SDL_Event &event, UiButton *button) if (event.button.button != SDL_BUTTON_LEFT) return false; switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_MOUSEBUTTONUP: +#endif if (button->IsPressed()) { button->Activate(); return true; } return false; +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_DOWN: +#else case SDL_MOUSEBUTTONDOWN: +#endif button->Press(); return true; default: diff --git a/Source/DiabloUI/credits.cpp b/Source/DiabloUI/credits.cpp index 4b873ec63..84aa2ea91 100644 --- a/Source/DiabloUI/credits.cpp +++ b/Source/DiabloUI/credits.cpp @@ -6,7 +6,14 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#else #include +#endif #include "DiabloUI/credits_lines.h" #include "DiabloUI/diabloui.h" @@ -102,7 +109,11 @@ void CreditsRenderer::Render() return; prev_offset_y_ = offsetY; +#ifdef USE_SDL3 + SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0); +#else SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000); +#endif const Point uiPosition = GetUIRectangle().position; if (ArtBackgroundWidescreen) RenderClxSprite(Surface(DiabloUiSurface()), (*ArtBackgroundWidescreen)[0], uiPosition - Displacement { 320, 0 }); @@ -152,10 +163,15 @@ bool TextDialog(const char *const *text, std::size_t textLines) do { creditsRenderer.Render(); UiFadeIn(); - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_KEYDOWN: case SDL_MOUSEBUTTONUP: +#endif endMenu = true; break; default: diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index a083811aa..cbcab0ca4 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -10,7 +10,16 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#include +#else #include +#endif + #include #include "DiabloUI/button.h" @@ -401,17 +410,34 @@ void UiOnBackgroundChange() // of single-player characters. // // Black out the screen immediately to make it appear more smooth. +#ifdef USE_SDL3 + SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0); +#else SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000); +#endif if (DiabloUiSurface() == PalSurface) BltFast(nullptr, nullptr); RenderPresent(); } -} // namespace - void UiFocusNavigation(SDL_Event *event) { switch (event->type) { +#ifdef USE_SDL3 + case SDL_EVENT_KEY_UP: + case SDL_EVENT_MOUSE_BUTTON_UP: + case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_MOUSE_WHEEL: + case SDL_EVENT_JOYSTICK_BUTTON_UP: + case SDL_EVENT_JOYSTICK_AXIS_MOTION: + case SDL_EVENT_JOYSTICK_BALL_MOTION: + case SDL_EVENT_JOYSTICK_HAT_MOTION: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_MOTION: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_WINDOW_EXPOSED: +#else case SDL_KEYUP: case SDL_MOUSEBUTTONUP: case SDL_MOUSEMOTION: @@ -430,8 +456,11 @@ void UiFocusNavigation(SDL_Event *event) case SDL_WINDOWEVENT: #endif case SDL_SYSWMEVENT: +#endif mainmenu_restart_repintro(); break; + default: + break; } bool menuActionHandled = false; @@ -440,7 +469,16 @@ void UiFocusNavigation(SDL_Event *event) if (menuActionHandled) return; -#if SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef USE_SDL3 + if (event->type == SDL_EVENT_MOUSE_WHEEL) { + if (event->wheel.integer_y > 0) { + UiFocusUp(); + } else if (event->wheel.integer_y < 0) { + UiFocusDown(); + } + return; + } +#elif SDL_VERSION_ATLEAST(2, 0, 0) if (event->type == SDL_MOUSEWHEEL) { if (event->wheel.y > 0) { UiFocusUp(); @@ -466,15 +504,29 @@ void UiFocusNavigation(SDL_Event *event) return; } - if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) { - if (UiItemMouseEvents(event, gUiItems)) - return; + if (IsAnyOf(event->type, +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP +#endif + ) + && UiItemMouseEvents(event, gUiItems)) { + return; } } +} // namespace + void UiHandleEvents(SDL_Event *event) { - if (event->type == SDL_MOUSEMOTION) { + if (event->type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_MOTION +#else + SDL_MOUSEMOTION +#endif + ) { #ifdef USE_SDL1 OutputToLogical(&event->motion.x, &event->motion.y); #endif @@ -482,8 +534,13 @@ void UiHandleEvents(SDL_Event *event) return; } - if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_RETURN) { - const Uint8 *state = SDLC_GetKeyState(); +#ifdef USE_SDL3 + if (event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_RETURN) +#else + if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_RETURN) +#endif + { + const auto *state = SDLC_GetKeyState(); if (state[SDLC_KEYSTATE_LALT] != 0 || state[SDLC_KEYSTATE_RALT] != 0) { GetOptions().Graphics.fullscreen.SetValue(!IsFullScreen()); SaveOptions(); @@ -493,12 +550,41 @@ void UiHandleEvents(SDL_Event *event) } } - if (event->type == SDL_QUIT) + if (event->type == +#ifdef USE_SDL3 + SDL_EVENT_QUIT +#else + SDL_QUIT +#endif + ) { diablo_quit(0); + } #ifndef USE_SDL1 HandleControllerAddedOrRemovedEvent(*event); +#ifdef USE_SDL3 + switch (event->type) { + case SDL_EVENT_WINDOW_SHOWN: + case SDL_EVENT_WINDOW_EXPOSED: + case SDL_EVENT_WINDOW_RESTORED: + gbActive = true; + break; + case SDL_EVENT_WINDOW_HIDDEN: + case SDL_EVENT_WINDOW_MINIMIZED: + gbActive = false; + break; + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + DoReinitializeHardwareCursor(); + break; + case SDL_EVENT_WINDOW_FOCUS_LOST: + if (*GetOptions().Gameplay.pauseOnFocusLoss) music_mute(); + break; + case SDL_EVENT_WINDOW_FOCUS_GAINED: + if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause(); + break; + } +#else if (event->type == SDL_WINDOWEVENT) { if (IsAnyOf(event->window.event, SDL_WINDOWEVENT_SHOWN, SDL_WINDOWEVENT_EXPOSED, SDL_WINDOWEVENT_RESTORED)) { gbActive = true; @@ -517,6 +603,7 @@ void UiHandleEvents(SDL_Event *event) diablo_focus_unpause(); } } +#endif #else if (event->type == SDL_ACTIVEEVENT && (event->active.state & SDL_APPINPUTFOCUS) != 0) { if (event->active.gain == 0) @@ -786,14 +873,19 @@ void DrawSelector(const SDL_Rect &rect) void UiClearScreen() { - if (!ArtBackground || gnScreenWidth > (*ArtBackground)[0].width() || gnScreenHeight > (*ArtBackground)[0].height()) + if (!ArtBackground || gnScreenWidth > (*ArtBackground)[0].width() || gnScreenHeight > (*ArtBackground)[0].height()) { +#ifdef USE_SDL3 + SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0); +#else SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000); +#endif + } } void UiPollAndRender(std::optional> eventHandler) { SDL_Event event; - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { if (eventHandler && (*eventHandler)(event)) continue; UiFocusNavigation(&event); @@ -942,7 +1034,13 @@ void Render(const UiEdit &uiEdit) bool HandleMouseEventArtTextButton(const SDL_Event &event, const UiArtTextButton *uiButton) { - if (event.type != SDL_MOUSEBUTTONUP || event.button.button != SDL_BUTTON_LEFT) { + if (event.type != +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONUP +#endif + || event.button.button != SDL_BUTTON_LEFT) { return false; } @@ -959,17 +1057,37 @@ bool HandleMouseEventList(const SDL_Event &event, UiList *uiList) if (event.button.button != SDL_BUTTON_LEFT) return false; - if (event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEBUTTONDOWN) + if (!IsAnyOf(event.type, +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP, SDL_EVENT_MOUSE_BUTTON_DOWN +#else + SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONDOWN +#endif + )) { return false; + } std::size_t index = uiList->indexAt(event.button.y); - if (event.type == SDL_MOUSEBUTTONDOWN) { + if (event.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_DOWN +#else + SDL_MOUSEBUTTONDOWN +#endif + ) { uiList->Press(index); return true; } - if (event.type == SDL_MOUSEBUTTONUP && !uiList->IsPressed(index)) + if (event.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONUP +#endif + && !uiList->IsPressed(index)) { return false; + } index += listOffset; @@ -998,7 +1116,13 @@ bool HandleMouseEventScrollBar(const SDL_Event &event, const UiScrollbar *uiSb) { if (event.button.button != SDL_BUTTON_LEFT) return false; - if (event.type == SDL_MOUSEBUTTONUP) { + if (event.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONUP +#endif + ) { if (scrollBarState.upArrowPressed && IsInsideRect(event, UpArrowRect(*uiSb))) { UiFocusUp(); return true; @@ -1007,7 +1131,14 @@ bool HandleMouseEventScrollBar(const SDL_Event &event, const UiScrollbar *uiSb) UiFocusDown(); return true; } - } else if (event.type == SDL_MOUSEBUTTONDOWN) { + } else if (event.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_DOWN +#else + SDL_MOUSEBUTTONDOWN +#endif + + ) { if (IsInsideRect(event, BarRect(*uiSb))) { // Scroll up or down based on thumb position. const SDL_Rect thumbRect = ThumbRect(*uiSb, SelectedItem, SelectedItemMax + 1); @@ -1116,7 +1247,13 @@ bool UiItemMouseEvents(SDL_Event *event, const std::vector &items) } } - if (event->type == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_LEFT) { + if (event->type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONUP +#endif + && event->button.button == SDL_BUTTON_LEFT) { scrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false; for (const auto &item : items) { if (item->IsType(UiType::Button)) { @@ -1149,7 +1286,13 @@ bool UiItemMouseEvents(SDL_Event *event, const std::vectortype == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_LEFT) { + if (event->type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONUP +#endif + && event->button.button == SDL_BUTTON_LEFT) { scrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false; for (const auto &item : items) { if (item->IsType(UiType::Button)) { diff --git a/Source/DiabloUI/diabloui.h b/Source/DiabloUI/diabloui.h index 8bac87a6b..61c5cd7a8 100644 --- a/Source/DiabloUI/diabloui.h +++ b/Source/DiabloUI/diabloui.h @@ -5,7 +5,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else #include +#endif + #include #include "DiabloUI/ui_item.h" diff --git a/Source/DiabloUI/dialogs.cpp b/Source/DiabloUI/dialogs.cpp index 711690182..10f915b3a 100644 --- a/Source/DiabloUI/dialogs.cpp +++ b/Source/DiabloUI/dialogs.cpp @@ -7,7 +7,16 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#include +#include +#else #include +#endif #include "DiabloUI/button.h" #include "DiabloUI/diabloui.h" @@ -68,7 +77,13 @@ bool Init(std::string_view caption, std::string_view text, bool error, bool rend { if (!renderBehind) { if (!UiLoadBlackBackground()) { - if (SDL_ShowCursor(SDL_ENABLE) <= -1) + if ( +#ifdef USE_SDL3 + SDL_ShowCursor() +#else + SDL_ShowCursor(SDL_ENABLE) <= -1 +#endif + ) LogError("{}", SDL_GetError()); } } @@ -123,10 +138,15 @@ void DialogLoop(const std::vector> &items, const std SDL_Event event; dialogEnd = false; do { - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: +#endif UiItemMouseEvents(&event, items); break; default: @@ -162,8 +182,15 @@ void UiOkDialog(std::string_view caption, std::string_view text, bool error, con if (!gbActive || inDialog) { if (!HeadlessMode) { - if (SDL_ShowCursor(SDL_ENABLE) <= -1) + if ( +#ifdef USE_SDL3 + SDL_ShowCursor() +#else + SDL_ShowCursor(SDL_ENABLE) <= -1 +#endif + ) { LogError("{}", SDL_GetError()); + } const std::string captionStr = std::string(caption); const std::string textStr = std::string(text); if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) <= -1) { @@ -174,21 +201,38 @@ void UiOkDialog(std::string_view caption, std::string_view text, bool error, con } if (IsHardwareCursor()) { - if (SDL_ShowCursor(SDL_ENABLE) <= -1) + if ( +#ifdef USE_SDL3 + SDL_ShowCursor() +#else + SDL_ShowCursor(SDL_ENABLE) <= -1 +#endif + ) { LogError("{}", SDL_GetError()); + } } if (!Init(caption, text, error, !renderBehind.empty())) { LogError("{}\n{}", caption, text); const std::string captionStr = std::string(caption); const std::string textStr = std::string(text); - if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) <= -1) { + if ( +#ifdef USE_SDL3 + !SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) +#else + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) <= -1 +#endif + ) { LogError("{}", SDL_GetError()); } } inDialog = true; +#ifdef USE_SDL3 + SDL_SetSurfaceClipRect(DiabloUiSurface(), nullptr); +#else SDL_SetClipRect(DiabloUiSurface(), nullptr); +#endif DialogLoop(vecOkDialog, renderBehind); Deinit(); inDialog = false; diff --git a/Source/DiabloUI/hero/selhero.cpp b/Source/DiabloUI/hero/selhero.cpp index 093caa11e..bb3287c41 100644 --- a/Source/DiabloUI/hero/selhero.cpp +++ b/Source/DiabloUI/hero/selhero.cpp @@ -10,7 +10,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif + #include #include "DiabloUI/diabloui.h" diff --git a/Source/DiabloUI/mainmenu.cpp b/Source/DiabloUI/mainmenu.cpp index 3405253f4..deff63fc8 100644 --- a/Source/DiabloUI/mainmenu.cpp +++ b/Source/DiabloUI/mainmenu.cpp @@ -4,7 +4,12 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else #include +#endif #include "DiabloUI/diabloui.h" #include "DiabloUI/ui_flags.hpp" diff --git a/Source/DiabloUI/multi/selconn.cpp b/Source/DiabloUI/multi/selconn.cpp index 65e8d4e50..020901aab 100644 --- a/Source/DiabloUI/multi/selconn.cpp +++ b/Source/DiabloUI/multi/selconn.cpp @@ -4,7 +4,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif + #include #include "DiabloUI/diabloui.h" diff --git a/Source/DiabloUI/multi/selgame.cpp b/Source/DiabloUI/multi/selgame.cpp index 4955923c4..52914f1c7 100644 --- a/Source/DiabloUI/multi/selgame.cpp +++ b/Source/DiabloUI/multi/selgame.cpp @@ -9,7 +9,14 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else #include +#endif + #include #include "DiabloUI/diabloui.h" diff --git a/Source/DiabloUI/progress.cpp b/Source/DiabloUI/progress.cpp index a613275be..0c129292c 100644 --- a/Source/DiabloUI/progress.cpp +++ b/Source/DiabloUI/progress.cpp @@ -2,7 +2,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else #include +#endif #include "DiabloUI/button.h" #include "DiabloUI/diabloui.h" @@ -71,7 +77,11 @@ Point GetPosition() void ProgressRenderBackground() { +#ifdef USE_SDL3 + SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0); +#else SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000); +#endif const Surface &out = Surface(DiabloUiSurface()); const Point position = GetPosition(); @@ -128,19 +138,36 @@ bool UiProgressDialog(int (*fnfunc)()) DrawMouse(); UiFadeIn(); - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: +#endif UiItemMouseEvents(&event, vecProgress); break; +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + switch (event.key.key) +#else + case SDL_KEYDOWN: + switch (event.key.keysym.sym) +#endif + { #ifndef USE_SDL1 - case SDLK_KP_ENTER: + case SDLK_KP_ENTER: #endif - case SDLK_ESCAPE: - case SDLK_RETURN: - case SDLK_SPACE: - endMenu = true; + case SDLK_ESCAPE: + case SDLK_RETURN: + case SDLK_SPACE: + endMenu = true; + break; + default: + break; + } break; default: for (const MenuAction menuAction : GetMenuActions(event)) { diff --git a/Source/DiabloUI/selok.cpp b/Source/DiabloUI/selok.cpp index f75d681e5..dd470be9e 100644 --- a/Source/DiabloUI/selok.cpp +++ b/Source/DiabloUI/selok.cpp @@ -5,7 +5,11 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif #include "DiabloUI/diabloui.h" #include "DiabloUI/ui_flags.hpp" diff --git a/Source/DiabloUI/title.cpp b/Source/DiabloUI/title.cpp index 02babab0f..94a543876 100644 --- a/Source/DiabloUI/title.cpp +++ b/Source/DiabloUI/title.cpp @@ -77,7 +77,7 @@ void UiTitleDialog() discord_manager::UpdateMenu(); - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { if (c_any_of(GetMenuActions(event), [](MenuAction menuAction) { return menuAction != MenuAction_NONE; })) { endMenu = true; break; diff --git a/Source/capture.cpp b/Source/capture.cpp index 30993e15d..5aac1a156 100644 --- a/Source/capture.cpp +++ b/Source/capture.cpp @@ -9,7 +9,14 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else #include +#endif + #include #define DEVILUTIONX_SCREENSHOT_FORMAT_PCX 0 @@ -34,7 +41,12 @@ namespace devilution { namespace { -SDL_RWops *CaptureFile(std::string *dstPath) +#ifdef USE_SDL3 +SDL_IOStream * +#else +SDL_RWops * +#endif +CaptureFile(std::string *dstPath) { const char *ext = #if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX @@ -55,7 +67,11 @@ SDL_RWops *CaptureFile(std::string *dstPath) i++; *dstPath = StrCat(paths::PrefPath(), filename, "-", i, ext); } +#ifdef USE_SDL3 + return SDL_IOFromFile(dstPath->c_str(), "wb"); +#else return SDL_RWFromFile(dstPath->c_str(), "wb"); +#endif } /** @@ -79,7 +95,7 @@ void CaptureScreen() std::string fileName; const uint32_t startTime = SDL_GetTicks(); - SDL_RWops *outStream = CaptureFile(&fileName); + auto *outStream = CaptureFile(&fileName); if (outStream == nullptr) { LogError("Failed to open {} for writing: {}", fileName, SDL_GetError()); SDL_ClearError(); diff --git a/Source/control.cpp b/Source/control.cpp index 31cbf88e4..288cdcb8e 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -15,6 +15,7 @@ #ifdef USE_SDL3 #include +#include #include #include #else @@ -1248,7 +1249,14 @@ void CheckMainPanelButton() SetPanelObjectPosition(UiPanels::Main, spellSelectButton); if (!SpellSelectFlag && spellSelectButton.contains(MousePosition)) { - if ((SDL_GetModState() & KMOD_SHIFT) != 0) { + if ((SDL_GetModState() & +#ifdef USE_SDL3 + SDL_KMOD_SHIFT +#else + KMOD_SHIFT +#endif + ) + != 0) { Player &myPlayer = *MyPlayer; myPlayer._pRSpell = SpellID::Invalid; myPlayer._pRSplType = SpellType::Invalid; @@ -1922,21 +1930,31 @@ void TypeChatMessage() .value = TalkMessage, .cursor = &ChatCursor, .maxLength = sizeof(TalkMessage) - 1 }); - SDL_Rect rect = MakeSdlRect(GetMainPanel().position.x + 200, GetMainPanel().position.y + 22, 0, 27); - SDL_SetTextInputRect(&rect); for (bool &talkButtonDown : TalkButtonsDown) { talkButtonDown = false; } sgbPlrTalkTbl = GetMainPanel().size.height + PanelPaddingHeight; RedrawEverything(); TalkSaveIndex = NextTalkSave; + + SDL_Rect rect = MakeSdlRect(GetMainPanel().position.x + 200, GetMainPanel().position.y + 22, 0, 27); +#ifdef USE_SDL3 + SDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0); + SDL_StartTextInput(ghMainWnd); +#else + SDL_SetTextInputRect(&rect); SDL_StartTextInput(); +#endif } void ResetChat() { ChatFlag = false; +#ifdef USE_SDL3 + SDL_StopTextInput(ghMainWnd); +#else SDL_StopTextInput(); +#endif ChatCursor = {}; ChatInputState = std::nullopt; sgbPlrTalkTbl = 0; @@ -2042,14 +2060,22 @@ void OpenGoldDrop(int8_t invIndex, int max) .min = 0, .max = max, }); +#ifdef USE_SDL3 + SDL_StartTextInput(ghMainWnd); +#else SDL_StartTextInput(); +#endif } void CloseGoldDrop() { if (!DropGoldFlag) return; +#ifdef USE_SDL3 + SDL_StopTextInput(ghMainWnd); +#else SDL_StopTextInput(); +#endif DropGoldFlag = false; GoldDropInputState = std::nullopt; GoldDropInvIndex = 0; diff --git a/Source/controls/axis_direction.cpp b/Source/controls/axis_direction.cpp index a2838ee09..fbd055be5 100644 --- a/Source/controls/axis_direction.cpp +++ b/Source/controls/axis_direction.cpp @@ -1,6 +1,10 @@ #include "axis_direction.h" +#ifdef USE_SDL3 +#include +#else #include +#endif namespace devilution { diff --git a/Source/controls/controller.cpp b/Source/controls/controller.cpp index 51c0ff69a..12a1cd298 100644 --- a/Source/controls/controller.cpp +++ b/Source/controls/controller.cpp @@ -36,11 +36,17 @@ StaticVector ToControllerButtonEvents(const SDL_Event { ControllerButtonEvent result { ControllerButton_NONE, false }; switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_JOYSTICK_BUTTON_UP: + case SDL_EVENT_KEY_UP: +#else #ifndef USE_SDL1 case SDL_CONTROLLERBUTTONUP: #endif case SDL_JOYBUTTONUP: case SDL_KEYUP: +#endif result.up = true; break; default: diff --git a/Source/controls/devices/game_controller.h b/Source/controls/devices/game_controller.h index 69d2761d8..955c6aedf 100644 --- a/Source/controls/devices/game_controller.h +++ b/Source/controls/devices/game_controller.h @@ -2,7 +2,13 @@ #include +#ifdef USE_SDL3 +#include +#include +#include +#else #include +#endif #include "controls/controller_buttons.h" #include "controls/game_controls.h" @@ -41,7 +47,12 @@ public: static GamepadLayout getLayout(const SDL_Event &event); private: - SDL_GameController *sdl_game_controller_ = NULL; +#ifdef USE_SDL3 + SDL_Gamepad *sdl_game_controller_ = nullptr; +#else + SDL_GameController *sdl_game_controller_ = nullptr; +#endif + SDL_JoystickID instance_id_ = -1; ControllerButton trigger_left_state_ = ControllerButton_NONE; diff --git a/Source/controls/devices/joystick.cpp b/Source/controls/devices/joystick.cpp index 18733d58f..c238d4fa2 100644 --- a/Source/controls/devices/joystick.cpp +++ b/Source/controls/devices/joystick.cpp @@ -320,14 +320,22 @@ bool Joystick::IsPressed(ControllerButton button) const const int joyButton = ToSdlJoyButton(button); if (joyButton == -1) return false; +#ifdef USE_SDL3 + const int numButtons = SDL_GetNumJoystickButtons(sdl_joystick_); + return joyButton < numButtons && SDL_GetJoystickButton(sdl_joystick_, joyButton); +#else const int numButtons = SDL_JoystickNumButtons(sdl_joystick_); return joyButton < numButtons && SDL_JoystickGetButton(sdl_joystick_, joyButton) != 0; +#endif } bool Joystick::ProcessAxisMotion(const SDL_Event &event) { - if (event.type != SDL_JOYAXISMOTION) - return false; +#ifdef USE_SDL3 + if (event.type != SDL_EVENT_JOYSTICK_AXIS_MOTION) return false; +#else + if (event.type != SDL_JOYAXISMOTION) return false; +#endif #if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY) switch (event.jaxis.axis) { diff --git a/Source/controls/input.h b/Source/controls/input.h index 1780cdfc2..1b37ee329 100644 --- a/Source/controls/input.h +++ b/Source/controls/input.h @@ -1,16 +1,24 @@ #pragma once +#ifdef USE_SDL3 +#include +#else #include +#endif #include "controls/controller.h" #include "controls/controller_motion.h" namespace devilution { -inline int PollEvent(SDL_Event *event) +inline bool PollEvent(SDL_Event *event) { - int result = SDL_PollEvent(event); - if (result != 0) { +#ifdef USE_SDL3 + const bool result = SDL_PollEvent(event); +#else + const bool result = SDL_PollEvent(event) >= 0; +#endif + if (result) { UnlockControllerState(*event); ProcessControllerMotion(*event); } diff --git a/Source/controls/keymapper.cpp b/Source/controls/keymapper.cpp index d5bd6e5c6..8a7b344cf 100644 --- a/Source/controls/keymapper.cpp +++ b/Source/controls/keymapper.cpp @@ -1,10 +1,16 @@ #include "controls/keymapper.hpp" +#include + +#ifdef USE_SDL3 +#include +#else #include #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif #include "control.h" #include "options.h" @@ -15,7 +21,12 @@ namespace { bool IsTextEntryKey(SDL_Keycode vkey) { - return IsAnyOf(vkey, SDLK_ESCAPE, SDLK_RETURN, SDLK_KP_ENTER, SDLK_BACKSPACE, SDLK_DOWN, SDLK_UP) || (vkey >= SDLK_SPACE && vkey <= SDLK_z); + return IsAnyOf(vkey, SDLK_ESCAPE, SDLK_RETURN, SDLK_KP_ENTER, SDLK_BACKSPACE, SDLK_DOWN, SDLK_UP) +#ifdef USE_SDL3 + || (vkey >= SDLK_SPACE && vkey <= SDLK_Z); +#else + || (vkey >= SDLK_SPACE && vkey <= SDLK_z); +#endif } bool IsNumberEntryKey(SDL_Keycode vkey) @@ -25,8 +36,14 @@ bool IsNumberEntryKey(SDL_Keycode vkey) SDL_Keycode ToAsciiUpper(SDL_Keycode key) { - if (key >= SDLK_a && key <= SDLK_z) { - return static_cast(static_cast(key) - ('a' - 'A')); + if ( +#ifdef USE_SDL3 + key >= SDLK_A && key <= SDLK_Z +#else + key >= SDLK_a && key <= SDLK_z +#endif + ) { + return static_cast(static_cast(key) - ('a' - 'A')); } return key; } diff --git a/Source/controls/keymapper.hpp b/Source/controls/keymapper.hpp index 048f6a4fb..63d864e80 100644 --- a/Source/controls/keymapper.hpp +++ b/Source/controls/keymapper.hpp @@ -2,11 +2,15 @@ #include +#ifdef USE_SDL3 +#include +#else #include #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif namespace devilution { diff --git a/Source/controls/menu_controls.cpp b/Source/controls/menu_controls.cpp index abe9351a8..40804ae92 100644 --- a/Source/controls/menu_controls.cpp +++ b/Source/controls/menu_controls.cpp @@ -1,5 +1,13 @@ #include "controls/menu_controls.h" +#ifdef USE_SDL3 +#include +#include +#include +#else +#include +#endif + #include "DiabloUI/diabloui.h" #include "controls/axis_direction.h" #include "controls/control_mode.hpp" @@ -78,7 +86,13 @@ std::vector GetMenuActions(const SDL_Event &event) return menuActions; } - if (event.type == SDL_MOUSEBUTTONDOWN) { + if (event.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_DOWN +#else + SDL_MOUSEBUTTONDOWN +#endif + ) { switch (event.button.button) { case SDL_BUTTON_X1: #if !SDL_VERSION_ATLEAST(2, 0, 0) @@ -89,8 +103,20 @@ std::vector GetMenuActions(const SDL_Event &event) } #if HAS_KBCTRL == 0 - if (event.type == SDL_KEYDOWN) { - SDL_Keycode sym = event.key.keysym.sym; + if ( + event.type == +#ifdef USE_SDL3 + SDL_EVENT_KEY_DOWN +#else + SDL_KEYDOWN +#endif + ) { + SDL_Keycode sym = +#ifdef USE_SDL3 + event.key.key; +#else + event.key.keysym.sym; +#endif remap_keyboard_key(&sym); switch (sym) { case SDLK_UP: @@ -98,16 +124,30 @@ std::vector GetMenuActions(const SDL_Event &event) case SDLK_DOWN: return { MenuAction_DOWN }; case SDLK_TAB: - if ((SDL_GetModState() & KMOD_SHIFT) != 0) + if ((SDL_GetModState() & +#ifdef USE_SDL3 + SDL_KMOD_SHIFT +#else + KMOD_SHIFT +#endif + ) + != 0) { return { MenuAction_UP }; - else - return { MenuAction_DOWN }; + } + return { MenuAction_DOWN }; case SDLK_PAGEUP: return { MenuAction_PAGE_UP }; case SDLK_PAGEDOWN: return { MenuAction_PAGE_DOWN }; case SDLK_RETURN: - if ((SDL_GetModState() & KMOD_ALT) == 0) { + if ((SDL_GetModState() & +#ifdef USE_SDL3 + SDL_KMOD_ALT +#else + KMOD_ALT +#endif + ) + == 0) { return { MenuAction_SELECT }; } break; diff --git a/Source/controls/menu_controls.h b/Source/controls/menu_controls.h index f5475cb26..ca95cb111 100644 --- a/Source/controls/menu_controls.h +++ b/Source/controls/menu_controls.h @@ -1,9 +1,14 @@ #pragma once -#include #include #include +#ifdef USE_SDL3 +#include +#else +#include +#endif + namespace devilution { enum MenuAction : uint8_t { diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 00725426b..f4348eb04 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -5,9 +5,17 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else +#include + #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif #include "automap.h" #include "control.h" @@ -1592,34 +1600,102 @@ bool IsStickMovementSignificant() ControlTypes GetInputTypeFromEvent(const SDL_Event &event) { - if (IsAnyOf(event.type, SDL_KEYDOWN, SDL_KEYUP)) + switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: +#else + case SDL_KEYDOWN: + case SDL_KEYUP: +#endif return ControlTypes::KeyboardAndMouse; #ifdef USE_SDL1 - if (IsAnyOf(event.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_MOUSEMOTION)) + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEMOTION: return ControlTypes::KeyboardAndMouse; #else - if (IsAnyOf(event.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP)) +// SDL 2/3-only events (touch / gamepad): +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: +#endif return event.button.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; - if (event.type == SDL_MOUSEMOTION) +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_MOTION: +#else + case SDL_MOUSEMOTION: +#endif return event.motion.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; - if (event.type == SDL_MOUSEWHEEL) +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_WHEEL: +#else + case SDL_MOUSEWHEEL: +#endif return event.wheel.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; - if (IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) +#ifdef USE_SDL3 + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_MOTION: +#else + case SDL_FINGERDOWN: + case SDL_FINGERUP: + case SDL_FINGERMOTION: +#endif return ControlTypes::VirtualGamepad; - if (event.type == SDL_CONTROLLERAXISMOTION - && (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT || event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT - || IsStickMovementSignificant())) - return ControlTypes::Gamepad; - if (event.type >= SDL_CONTROLLERBUTTONDOWN && event.type <= SDL_CONTROLLERDEVICEREMAPPED) - return ControlTypes::Gamepad; - if (IsAnyOf(event.type, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED)) - return ControlTypes::Gamepad; +#ifdef USE_SDL3 + case SDL_EVENT_GAMEPAD_AXIS_MOTION: +#else + case SDL_CONTROLLERAXISMOTION: +#endif + if ( +#ifdef USE_SDL3 + IsAnyOf(event.gaxis.axis, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) +#else + IsAnyOf(event.caxis.axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) +#endif + || IsStickMovementSignificant()) { + return ControlTypes::Gamepad; + } + break; +#endif // !USE_SDL1 +#ifdef USE_SDL3 + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_JOYSTICK_BALL_MOTION: + case SDL_EVENT_JOYSTICK_HAT_MOTION: + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: + case SDL_EVENT_JOYSTICK_BUTTON_UP: +#else +#ifndef USE_SDL1 + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERDEVICEADDED: +#endif + case SDL_JOYBALLMOTION: + case SDL_JOYHATMOTION: + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: #endif - if (event.type == SDL_JOYAXISMOTION && IsStickMovementSignificant()) - return ControlTypes::Gamepad; - if (event.type >= SDL_JOYBALLMOTION && event.type <= SDL_JOYBUTTONUP) return ControlTypes::Gamepad; - +#ifdef USE_SDL3 + case SDL_EVENT_JOYSTICK_AXIS_MOTION: + case SDL_EVENT_JOYSTICK_ADDED: +#else + case SDL_JOYAXISMOTION: +#ifndef USE_SDL1 + case SDL_JOYDEVICEADDED: +#endif +#endif + if (IsStickMovementSignificant()) return ControlTypes::Gamepad; + break; + default: + break; + } return ControlTypes::None; } @@ -1631,9 +1707,16 @@ bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonE return false; #if !defined(USE_SDL1) && !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY) - if (IsAnyOf(event.type, SDL_JOYAXISMOTION, SDL_JOYHATMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP)) { - if (!GameController::All().empty()) - return true; + if (IsAnyOf(event.type, +#ifdef USE_SDL3 + SDL_EVENT_JOYSTICK_AXIS_MOTION, SDL_EVENT_JOYSTICK_HAT_MOTION, + SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_EVENT_JOYSTICK_BUTTON_UP +#else + SDL_JOYAXISMOTION, SDL_JOYHATMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP +#endif + ) + && !GameController::All().empty()) { + return true; } #endif @@ -1662,8 +1745,7 @@ std::string_view ControlTypeToString(ControlTypes controlType) void LogControlDeviceAndModeChange(ControlTypes newControlDevice, ControlTypes newControlMode) { - if (SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION) > SDL_LOG_PRIORITY_VERBOSE) - return; + if (!IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_VERBOSE)) return; if (newControlDevice == ControlDevice && newControlMode == ControlMode) return; constexpr auto DebugChange = [](ControlTypes before, ControlTypes after) -> std::string { @@ -1692,8 +1774,7 @@ std::string_view GamepadTypeToString(GamepadLayout gamepadLayout) void LogGamepadChange(GamepadLayout newGamepad) { - if (SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION) > SDL_LOG_PRIORITY_VERBOSE) - return; + if (!IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_VERBOSE)) return; constexpr auto DebugChange = [](GamepadLayout before, GamepadLayout after) -> std::string { if (before == after) return std::string { GamepadTypeToString(before) }; diff --git a/Source/controls/plrctrls.h b/Source/controls/plrctrls.h index c02689c44..4b79c8fde 100644 --- a/Source/controls/plrctrls.h +++ b/Source/controls/plrctrls.h @@ -4,7 +4,11 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif #include "controls/controller.h" #include "controls/game_controls.h" diff --git a/Source/controls/remap_keyboard.h b/Source/controls/remap_keyboard.h index f569a16bf..697e610ef 100644 --- a/Source/controls/remap_keyboard.h +++ b/Source/controls/remap_keyboard.h @@ -2,11 +2,14 @@ #include +#ifdef USE_SDL3 +#include +#else #include - #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif namespace devilution { diff --git a/Source/controls/touch/event_handlers.cpp b/Source/controls/touch/event_handlers.cpp index 9cad136c5..ea0ae2b3e 100644 --- a/Source/controls/touch/event_handlers.cpp +++ b/Source/controls/touch/event_handlers.cpp @@ -1,5 +1,12 @@ #include "controls/touch/event_handlers.h" +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include "control.h" #include "controls/plrctrls.h" #include "cursor.h" @@ -36,6 +43,42 @@ Point ScaleToScreenCoordinates(float x, float y) }; } +constexpr bool IsFingerDown(const SDL_Event &event) +{ +#ifdef USE_SDL3 + return event.type == SDL_EVENT_FINGER_DOWN; +#else + return event.type == SDL_FINGERDOWN; +#endif +} + +constexpr bool IsFingerUp(const SDL_Event &event) +{ +#ifdef USE_SDL3 + return event.type == SDL_EVENT_FINGER_UP; +#else + return event.type == SDL_FINGERUP; +#endif +} + +constexpr bool IsFingerMotion(const SDL_Event &event) +{ +#ifdef USE_SDL3 + return event.type == SDL_EVENT_FINGER_MOTION; +#else + return event.type == SDL_FINGERMOTION; +#endif +} + +constexpr SDL_FingerID FingerId(const SDL_TouchFingerEvent &event) +{ +#ifdef USE_SDL3 + return event.fingerID; +#else + return event.fingerId; +#endif +} + void SimulateMouseMovement(const SDL_Event &event) { const Point position = ScaleToScreenCoordinates(event.tfinger.x, event.tfinger.y); @@ -62,18 +105,18 @@ bool HandleGameMenuInteraction(const SDL_Event &event) { if (!gmenu_is_active()) return false; - if (event.type == SDL_FINGERDOWN && gmenu_left_mouse(true)) + if (IsFingerDown(event) && gmenu_left_mouse(true)) return true; - if (event.type == SDL_FINGERMOTION && gmenu_on_mouse_move()) + if (IsFingerMotion(event) && gmenu_on_mouse_move()) return true; - return event.type == SDL_FINGERUP && gmenu_left_mouse(false); + return IsFingerUp(event) && gmenu_left_mouse(false); } bool HandleStoreInteraction(const SDL_Event &event) { if (!IsPlayerInStore()) return false; - if (event.type == SDL_FINGERDOWN) + if (IsFingerDown(event)) CheckStoreBtn(); return true; } @@ -83,7 +126,7 @@ void HandleSpellBookInteraction(const SDL_Event &event) if (!SpellbookFlag) return; - if (event.type == SDL_FINGERUP) + if (IsFingerUp(event)) CheckSBook(); } @@ -91,7 +134,7 @@ bool HandleSpeedBookInteraction(const SDL_Event &event) { if (!SpellSelectFlag) return false; - if (event.type == SDL_FINGERUP) + if (IsFingerUp(event)) SetSpell(); return true; } @@ -103,7 +146,7 @@ void HandleBottomPanelInteraction(const SDL_Event &event) ResetMainPanelButtons(); - if (event.type != SDL_FINGERUP) { + if (!IsFingerUp(event)) { SpellSelectFlag = true; CheckMainPanelButton(); SpellSelectFlag = false; @@ -119,9 +162,9 @@ void HandleCharacterPanelInteraction(const SDL_Event &event) if (!CharFlag) return; - if (event.type == SDL_FINGERDOWN) + if (IsFingerDown(event)) CheckChrBtns(); - else if (event.type == SDL_FINGERUP && CharPanelButtonActive) + else if (IsFingerUp(event) && CharPanelButtonActive) ReleaseChrBtns(false); } @@ -130,7 +173,7 @@ void HandleStashPanelInteraction(const SDL_Event &event) if (!IsStashOpen || !MyPlayer->HoldItem.isEmpty()) return; - if (event.type != SDL_FINGERUP) { + if (!IsFingerUp(event)) { CheckStashButtonPress(MousePosition); } else { CheckStashButtonRelease(MousePosition); @@ -158,7 +201,7 @@ void HandleTouchEvent(const SDL_Event &event) return; } - if (!IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) { + if (!IsFingerDown(event) && !IsFingerUp(event) && !IsFingerMotion(event)) { return; } @@ -189,7 +232,7 @@ void DeactivateTouchEventHandlers() bool VirtualGamepadEventHandler::Handle(const SDL_Event &event) { if (!IsDeactivateEvent(event)) { - if (!VirtualGamepadState.isActive || !IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) { + if (!VirtualGamepadState.isActive || (!IsFingerDown(event) && !IsFingerUp(event) && !IsFingerMotion(event))) { VirtualGamepadState.primaryActionButton.didStateChange = false; VirtualGamepadState.secondaryActionButton.didStateChange = false; VirtualGamepadState.spellActionButton.didStateChange = false; @@ -244,19 +287,10 @@ bool VirtualDirectionPadEventHandler::Handle(const SDL_Event &event) return false; } - switch (event.type) { - case SDL_FINGERDOWN: - return HandleFingerDown(event.tfinger); - - case SDL_FINGERUP: - return HandleFingerUp(event.tfinger); - - case SDL_FINGERMOTION: - return HandleFingerMotion(event.tfinger); - - default: - return false; - } + if (IsFingerDown(event)) return HandleFingerDown(event.tfinger); + if (IsFingerUp(event)) return HandleFingerUp(event.tfinger); + if (IsFingerMotion(event)) return HandleFingerMotion(event.tfinger); + return false; } bool VirtualDirectionPadEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event) @@ -272,14 +306,14 @@ bool VirtualDirectionPadEventHandler::HandleFingerDown(const SDL_TouchFingerEven return false; virtualDirectionPad->UpdatePosition(touchCoordinates); - activeFinger = event.fingerId; + activeFinger = FingerId(event); isActive = true; return true; } bool VirtualDirectionPadEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event) { - if (!isActive || event.fingerId != activeFinger) + if (!isActive || FingerId(event) != activeFinger) return false; const Point position = virtualDirectionPad->area.position; @@ -290,7 +324,7 @@ bool VirtualDirectionPadEventHandler::HandleFingerUp(const SDL_TouchFingerEvent bool VirtualDirectionPadEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event) { - if (!isActive || event.fingerId != activeFinger) + if (!isActive || FingerId(event) != activeFinger) return false; const float x = event.x; @@ -316,19 +350,10 @@ bool VirtualButtonEventHandler::Handle(const SDL_Event &event) virtualButton->didStateChange = false; - switch (event.type) { - case SDL_FINGERDOWN: - return HandleFingerDown(event.tfinger); - - case SDL_FINGERUP: - return HandleFingerUp(event.tfinger); - - case SDL_FINGERMOTION: - return HandleFingerMotion(event.tfinger); - - default: - return false; - } + if (IsFingerDown(event)) return HandleFingerDown(event.tfinger); + if (IsFingerUp(event)) return HandleFingerUp(event.tfinger); + if (IsFingerMotion(event)) return HandleFingerMotion(event.tfinger); + return false; } bool VirtualButtonEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event) @@ -349,14 +374,14 @@ bool VirtualButtonEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &eve virtualButton->isHeld = true; virtualButton->didStateChange = true; - activeFinger = event.fingerId; + activeFinger = FingerId(event); isActive = true; return true; } bool VirtualButtonEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event) { - if (!isActive || event.fingerId != activeFinger) + if (!isActive || FingerId(event) != activeFinger) return false; if (!toggles) { @@ -371,7 +396,7 @@ bool VirtualButtonEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event bool VirtualButtonEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event) { - if (!isActive || event.fingerId != activeFinger) + if (!isActive || FingerId(event) != activeFinger) return false; if (toggles) diff --git a/Source/controls/touch/event_handlers.h b/Source/controls/touch/event_handlers.h index 5e9e8b073..20de5dbe6 100644 --- a/Source/controls/touch/event_handlers.h +++ b/Source/controls/touch/event_handlers.h @@ -1,6 +1,10 @@ #pragma once +#ifdef USE_SDL3 +#include +#else #include +#endif #include "controls/touch/gamepad.h" diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index 0b851b893..3c766068e 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -1,5 +1,11 @@ #include "controls/touch/renderers.h" +#ifdef USE_SDL +#include +#else +#include +#endif + #include "control.h" #include "cursor.h" #include "diablo.h" @@ -127,14 +133,19 @@ void LoadPotionArt(ButtonTexture *potionArt) SDL_PIXELFORMAT_INDEX8); auto palette = SDLWrap::AllocPalette(); - if (SDLC_SetSurfaceAndPaletteColors(surface.get(), palette.get(), logical_palette.data(), 0, 256) < 0) + if (!SDLC_SetSurfaceAndPaletteColors(surface.get(), palette.get(), logical_palette.data(), 0, 256)) ErrSdl(); const Uint32 bgColor = SDL_MapRGB(surface->format, logical_palette[1].r, logical_palette[1].g, logical_palette[1].b); +#ifdef USE_SDL3 + if (!SDL_FillSurfaceRect(surface.get(), nullptr, bgColor)) ErrSdl(); + if (!SDL_SetSurfaceColorKey(surface.get(), true, bgColor)) ErrSdl(); +#else if (SDL_FillRect(surface.get(), nullptr, bgColor) < 0) ErrSdl(); if (SDL_SetColorKey(surface.get(), SDL_TRUE, bgColor) < 0) ErrSdl(); +#endif Point position { 0, 0 }; for (const item_cursor_graphic graphic : potionGraphics) { @@ -145,7 +156,13 @@ void LoadPotionArt(ButtonTexture *potionArt) potionArt->numFrames = sizeof(potionGraphics); - potionArt->surface.reset(SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0)); + potionArt->surface.reset( +#ifdef USE_SDL3 + SDL_ConvertSurface(surface.get(), SDL_PIXELFORMAT_ARGB8888) +#else + SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0) +#endif + ); } bool InteractsWithCharButton(Point point) @@ -191,8 +208,11 @@ void RenderVirtualGamepad(SDL_Renderer *renderer) if (art.texture == nullptr) return; - if (SDL_RenderCopy(renderer, art.texture.get(), src, dst) <= -1) - ErrSdl(); +#ifdef USE_SDL3 + if (!SDL_RenderTexture(renderer, art.texture.get(), src, dst)) ErrSdl(); +#else + if (SDL_RenderCopy(renderer, art.texture.get(), src, dst) <= -1) ErrSdl(); +#endif }; Renderer.Render(renderFunction); diff --git a/Source/controls/touch/renderers.h b/Source/controls/touch/renderers.h index 7ceab432f..1d62b3208 100644 --- a/Source/controls/touch/renderers.h +++ b/Source/controls/touch/renderers.h @@ -3,7 +3,11 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif #include "controls/plrctrls.h" #include "controls/touch/gamepad.h" diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 56af0c9c5..0d5567619 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -11,6 +11,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include #include "DiabloUI/diabloui.h" @@ -501,17 +508,31 @@ void CreateHalfSizeItemSprites() } const Surface itemSurface = ownedItemSurface.subregion(0, 0, itemSprite.width(), itemSprite.height()); const SDL_Rect itemSurfaceRect = MakeSdlRect(0, 0, itemSurface.w(), itemSurface.h()); + +#ifdef USE_SDL3 + SDL_SetSurfaceClipRect(itemSurface.surface, &itemSurfaceRect); + SDL_FillSurfaceRect(itemSurface.surface, nullptr, 1); +#else SDL_SetClipRect(itemSurface.surface, &itemSurfaceRect); SDL_FillRect(itemSurface.surface, nullptr, 1); +#endif ClxDraw(itemSurface, { 0, itemSurface.h() }, itemSprite); const Surface halfSurface = ownedHalfSurface.subregion(0, 0, itemSurface.w() / 2, itemSurface.h() / 2); const SDL_Rect halfSurfaceRect = MakeSdlRect(0, 0, halfSurface.w(), halfSurface.h()); +#ifdef USE_SDL3 + SDL_SetSurfaceClipRect(halfSurface.surface, &halfSurfaceRect); +#else SDL_SetClipRect(halfSurface.surface, &halfSurfaceRect); +#endif BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1); HalfSizeItemSprites[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1)); +#ifdef USE_SDL3 + SDL_FillSurfaceRect(itemSurface.surface, nullptr, 1); +#else SDL_FillRect(itemSurface.surface, nullptr, 1); +#endif ClxDrawTRN(itemSurface, { 0, itemSurface.h() }, itemSprite, redTrn); BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1); HalfSizeItemSpritesRed[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1)); diff --git a/Source/diablo_msg.cpp b/Source/diablo_msg.cpp index 68f768f42..3137712e1 100644 --- a/Source/diablo_msg.cpp +++ b/Source/diablo_msg.cpp @@ -8,6 +8,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else +#include +#endif + #include "diablo_msg.hpp" #include "DiabloUI/ui_flags.hpp" diff --git a/Source/engine/demomode.cpp b/Source/engine/demomode.cpp index 1d1d60367..ad4abedc7 100644 --- a/Source/engine/demomode.cpp +++ b/Source/engine/demomode.cpp @@ -5,9 +5,17 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else +#include + #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif #include "controls/control_mode.hpp" #include "controls/plrctrls.h" @@ -247,23 +255,44 @@ bool CreateSdlEvent(const DemoMsg &dmsg, SDL_Event &event, uint16_t &modState) const uint8_t type = dmsg.type; switch (type) { case DemoMsg::MouseMotionEvent: +#ifdef USE_SDL3 + event.type = SDL_EVENT_MOUSE_MOTION; + event.motion.state = 0; + event.motion.xrel = 0.F; + event.motion.yrel = 0.F; +#else event.type = SDL_MOUSEMOTION; +#endif event.motion.which = 0; event.motion.x = dmsg.motion.x; event.motion.y = dmsg.motion.y; return true; case DemoMsg::MouseButtonDownEvent: case DemoMsg::MouseButtonUpEvent: +#ifdef USE_SDL3 + event.type = type == DemoMsg::MouseButtonDownEvent ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; + event.button.down = type == DemoMsg::MouseButtonDownEvent; + event.button.clicks = 1; +#else event.type = type == DemoMsg::MouseButtonDownEvent ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP; + event.button.state = type == DemoMsg::MouseButtonDownEvent ? SDL_PRESSED : SDL_RELEASED; +#endif event.button.which = 0; event.button.button = dmsg.button.button; - event.button.state = type == DemoMsg::MouseButtonDownEvent ? SDL_PRESSED : SDL_RELEASED; event.button.x = dmsg.button.x; event.button.y = dmsg.button.y; modState = dmsg.button.mod; return true; case DemoMsg::MouseWheelEvent: +#ifdef USE_SDL3 + event.type = SDL_EVENT_MOUSE_WHEEL; + event.wheel.integer_x = dmsg.wheel.x; + event.wheel.integer_y = dmsg.wheel.y; + event.wheel.mouse_x = 0; + event.wheel.mouse_y = 0; +#else event.type = SDL_MOUSEWHEEL; +#endif event.wheel.which = 0; event.wheel.x = dmsg.wheel.x; event.wheel.y = dmsg.wheel.y; @@ -271,11 +300,19 @@ bool CreateSdlEvent(const DemoMsg &dmsg, SDL_Event &event, uint16_t &modState) return true; case DemoMsg::KeyDownEvent: case DemoMsg::KeyUpEvent: +#ifdef USE_SDL3 + event.type = type == DemoMsg::KeyDownEvent ? SDL_EVENT_KEY_DOWN : SDL_EVENT_KEY_UP; + event.key.down = type == DemoMsg::KeyDownEvent; + event.key.scancode = SDL_GetScancodeFromKey(dmsg.key.sym, nullptr); + event.key.key = dmsg.key.sym; + event.key.mod = dmsg.key.mod; +#else event.type = type == DemoMsg::KeyDownEvent ? SDL_KEYDOWN : SDL_KEYUP; event.key.state = type == DemoMsg::KeyDownEvent ? SDL_PRESSED : SDL_RELEASED; event.key.keysym.scancode = SDL_GetScancodeFromKey(dmsg.key.sym); event.key.keysym.sym = dmsg.key.sym; event.key.keysym.mod = dmsg.key.mod; +#endif return true; default: if (type >= DemoMsg::MinCustomEvent) { @@ -688,27 +725,51 @@ bool FetchMessage(SDL_Event *event, uint16_t *modState) return false; SDL_Event e; - if (SDL_PollEvent(&e) != 0) { - if (e.type == SDL_QUIT) { + if ( +#ifdef USE_SDL3 + SDL_PollEvent(&e) +#else + SDL_PollEvent(&e) != 0 +#endif + ) { + if (e.type == +#ifdef USE_SDL3 + SDL_EVENT_QUIT +#else + SDL_QUIT +#endif + ) { *event = e; return true; } - if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { - CloseDemoFile(); - CurrentDemoMessage = std::nullopt; - DemoNumber = -1; - Timedemo = false; - last_tick = SDL_GetTicks(); - } - if (e.type == SDL_KEYDOWN && IsAnyOf(e.key.keysym.sym, SDLK_KP_PLUS, SDLK_PLUS) && sgGameInitInfo.nTickRate < 255) { - sgGameInitInfo.nTickRate++; - GetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); - gnTickDelay = 1000 / sgGameInitInfo.nTickRate; - } - if (e.type == SDL_KEYDOWN && IsAnyOf(e.key.keysym.sym, SDLK_KP_MINUS, SDLK_MINUS) && sgGameInitInfo.nTickRate > 1) { - sgGameInitInfo.nTickRate--; - GetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); - gnTickDelay = 1000 / sgGameInitInfo.nTickRate; + if (e.type == +#ifdef USE_SDL3 + SDL_EVENT_KEY_DOWN +#else + SDL_KEYDOWN +#endif + ) { + const SDL_Keycode key = +#ifdef USE_SDL3 + e.key.key; +#else + e.key.keysym.sym; +#endif + if (key == SDLK_ESCAPE) { + CloseDemoFile(); + CurrentDemoMessage = std::nullopt; + DemoNumber = -1; + Timedemo = false; + last_tick = SDL_GetTicks(); + } else if (IsAnyOf(key, SDLK_KP_PLUS, SDLK_PLUS) && sgGameInitInfo.nTickRate < 255) { + sgGameInitInfo.nTickRate++; + GetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); + gnTickDelay = 1000 / sgGameInitInfo.nTickRate; + } else if (IsAnyOf(key, SDLK_KP_MINUS, SDLK_MINUS) && sgGameInitInfo.nTickRate > 1) { + sgGameInitInfo.nTickRate--; + GetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); + gnTickDelay = 1000 / sgGameInitInfo.nTickRate; + } } } @@ -743,13 +804,22 @@ void RecordMessage(const SDL_Event &event, uint16_t modState) if (CurrentEventHandler == DisableInputEventHandler) return; switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_MOTION: +#else case SDL_MOUSEMOTION: +#endif WriteDemoMsgHeader(DemoMsg::MouseMotionEvent); WriteLE16(DemoRecording, event.motion.x); WriteLE16(DemoRecording, event.motion.y); break; +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: +#endif #ifdef USE_SDL1 if (event.button.button == SDL_BUTTON_WHEELUP || event.button.button == SDL_BUTTON_WHEELDOWN) { WriteDemoMsgHeader(DemoMsg::MouseWheelEvent); @@ -758,7 +828,14 @@ void RecordMessage(const SDL_Event &event, uint16_t modState) WriteLE16(DemoRecording, modState); } else { #endif - WriteDemoMsgHeader(event.type == SDL_MOUSEBUTTONDOWN ? DemoMsg::MouseButtonDownEvent : DemoMsg::MouseButtonUpEvent); + WriteDemoMsgHeader( +#ifdef USE_SDL3 + event.button.down +#else + event.type == SDL_MOUSEBUTTONDOWN +#endif + ? DemoMsg::MouseButtonDownEvent + : DemoMsg::MouseButtonUpEvent); WriteByte(DemoRecording, event.button.button); WriteLE16(DemoRecording, event.button.x); WriteLE16(DemoRecording, event.button.y); @@ -768,8 +845,24 @@ void RecordMessage(const SDL_Event &event, uint16_t modState) #endif break; #ifndef USE_SDL1 +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_WHEEL: +#else case SDL_MOUSEWHEEL: +#endif WriteDemoMsgHeader(DemoMsg::MouseWheelEvent); + +#ifdef USE_SDL3 + if (event.wheel.integer_x < std::numeric_limits::min() + || event.wheel.integer_x > std::numeric_limits::max() + || event.wheel.integer_y < std::numeric_limits::min() + || event.wheel.integer_y > std::numeric_limits::max()) { + app_fatal(StrCat("Mouse wheel event integer_x/y out of int16_t range. x=", + event.wheel.integer_x, " y=", event.wheel.integer_y)); + } + WriteLE16(DemoRecording, event.wheel.integer_x); + WriteLE16(DemoRecording, event.wheel.integer_y); +#else if (event.wheel.x < std::numeric_limits::min() || event.wheel.x > std::numeric_limits::max() || event.wheel.y < std::numeric_limits::min() @@ -779,23 +872,39 @@ void RecordMessage(const SDL_Event &event, uint16_t modState) } WriteLE16(DemoRecording, event.wheel.x); WriteLE16(DemoRecording, event.wheel.y); +#endif WriteLE16(DemoRecording, modState); break; #endif +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + WriteDemoMsgHeader(event.key.down ? DemoMsg::KeyDownEvent : DemoMsg::KeyUpEvent); + WriteLE32(DemoRecording, static_cast(event.key.key)); + WriteLE16(DemoRecording, static_cast(event.key.mod)); + break; +#else case SDL_KEYDOWN: case SDL_KEYUP: WriteDemoMsgHeader(event.type == SDL_KEYDOWN ? DemoMsg::KeyDownEvent : DemoMsg::KeyUpEvent); WriteLE32(DemoRecording, static_cast(event.key.keysym.sym)); WriteLE16(DemoRecording, static_cast(event.key.keysym.mod)); break; +#endif #ifndef USE_SDL1 +#ifndef USE_SDL3 case SDL_WINDOWEVENT: if (event.window.type == SDL_WINDOWEVENT_CLOSE) { WriteDemoMsgHeader(DemoMsg::QuitEvent); } break; #endif +#endif +#ifdef USE_SDL3 + case SDL_EVENT_QUIT: +#else case SDL_QUIT: +#endif WriteDemoMsgHeader(DemoMsg::QuitEvent); break; default: @@ -843,17 +952,17 @@ void NotifyGameLoopEnd() if (IsRunning() && !HeadlessMode) { const float seconds = (SDL_GetTicks() - StartTime) / 1000.0F; - SDL_Log("%d frames, %.2f seconds: %.1f fps", LogicTick, seconds, LogicTick / seconds); + Log("{} frames, {:.2f} seconds: {:.1f} fps", LogicTick, seconds, LogicTick / seconds); gbRunGameResult = false; gbRunGame = false; HeroCompareResult compareResult = pfile_compare_hero_demo(DemoNumber, false); switch (compareResult.status) { case HeroCompareResult::ReferenceNotFound: - SDL_Log("Timedemo: No final comparison because reference is not present."); + Log("Timedemo: No final comparison because reference is not present."); break; case HeroCompareResult::Same: - SDL_Log("Timedemo: Same outcome as initial run. :)"); + Log("Timedemo: Same outcome as initial run. :)"); break; case HeroCompareResult::Difference: Log("Timedemo: Different outcome than initial run. ;(\n{}", compareResult.message); diff --git a/Source/engine/demomode.h b/Source/engine/demomode.h index 59629c9d1..9f9d38ec7 100644 --- a/Source/engine/demomode.h +++ b/Source/engine/demomode.h @@ -7,7 +7,11 @@ #include +#ifdef USE_SDL3 +#include +#else #include +#endif namespace devilution { diff --git a/Source/engine/dx.cpp b/Source/engine/dx.cpp index 7781d35b2..5fc1357d1 100644 --- a/Source/engine/dx.cpp +++ b/Source/engine/dx.cpp @@ -5,9 +5,17 @@ */ #include "engine/dx.h" -#include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#else +#include +#endif + #include "controls/control_mode.hpp" #include "controls/plrctrls.h" #include "engine/render/primitive_render.hpp" @@ -144,7 +152,9 @@ void CreateBackBuffer() PalSurface = PinnedPalSurface.get(); } -#ifndef USE_SDL1 +#if defined(USE_SDL3) + if (!SDL_SetSurfacePalette(PalSurface, Palette.get())) ErrSdl(); +#elif !defined(USE_SDL1) // In SDL2, `PalSurface` points to the global `palette`. if (SDL_SetSurfacePalette(PalSurface, Palette.get()) < 0) ErrSdl(); @@ -168,7 +178,9 @@ void Blit(SDL_Surface *src, SDL_Rect *srcRect, SDL_Rect *dstRect) return; SDL_Surface *dst = GetOutputSurface(); -#ifndef USE_SDL1 +#if defined(USE_SDL3) + if (!SDL_BlitSurface(src, srcRect, dst, dstRect)) ErrSdl(); +#elif !defined(USE_SDL1) if (SDL_BlitSurface(src, srcRect, dst, dstRect) < 0) ErrSdl(); #else @@ -229,21 +241,32 @@ void RenderPresent() #ifndef USE_SDL1 if (renderer != nullptr) { - if (SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch) <= -1) { // pitch is 2560 - ErrSdl(); - } +#ifdef USE_SDL3 + if (!SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch)) ErrSdl(); +#else + if (SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch) <= -1) ErrSdl(); +#endif - // Clear buffer to avoid artifacts in case the window was resized - if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) <= -1) { // TODO only do this if window was resized - ErrSdl(); - } + // Clear buffer to avoid artifacts in case the window was resized + // TODO only do this if window was resized +#ifdef USE_SDL3 + if (!SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)) ErrSdl(); +#else + if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) <= -1) ErrSdl(); +#endif + +#ifdef USE_SDL3 + if (!SDL_RenderClear(renderer)) ErrSdl(); +#else + if (SDL_RenderClear(renderer) <= -1) ErrSdl(); +#endif + +#ifdef USE_SDL3 + if (!SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr)) ErrSdl(); +#else + if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) ErrSdl(); +#endif - if (SDL_RenderClear(renderer) <= -1) { - ErrSdl(); - } - if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) { - ErrSdl(); - } if (ControlMode == ControlTypes::VirtualGamepad) { RenderVirtualGamepad(renderer); } @@ -256,9 +279,13 @@ void RenderPresent() if (ControlMode == ControlTypes::VirtualGamepad) { RenderVirtualGamepad(surface); } - if (SDL_UpdateWindowSurface(ghMainWnd) <= -1) { - ErrSdl(); - } + +#ifdef USE_SDL3 + if (!SDL_UpdateWindowSurface(ghMainWnd)) ErrSdl(); +#else + if (SDL_UpdateWindowSurface(ghMainWnd) <= -1) ErrSdl(); +#endif + if (RenderDirectlyToOutputSurface) PalSurface = GetOutputSurface(); LimitFrameRate(); diff --git a/Source/engine/dx.h b/Source/engine/dx.h index ef7203604..ba14d57c8 100644 --- a/Source/engine/dx.h +++ b/Source/engine/dx.h @@ -5,7 +5,12 @@ */ #pragma once +#ifdef USE_SDL3 +#include +#include +#else #include +#endif #include "engine/surface.hpp" diff --git a/Source/engine/events.cpp b/Source/engine/events.cpp index d4492bac9..2153c6e1d 100644 --- a/Source/engine/events.cpp +++ b/Source/engine/events.cpp @@ -2,6 +2,16 @@ #include +#ifdef USE_SDL3 +#include +#else +#include + +#ifdef USE_SDL1 +#include "utils/sdl2_to_1_2_backports.h" +#endif +#endif + #include "controls/input.h" #include "controls/padmapper.hpp" #include "engine/demomode.h" @@ -46,9 +56,7 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) #endif SDL_Event e; - if (PollEvent(&e) == 0) { - return false; - } + if (!PollEvent(&e)) return false; event->type = static_cast(0); *modState = SDL_GetModState(); @@ -59,25 +67,54 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) HandleTouchEvent(e); #endif - if (e.type == SDL_QUIT || IsCustomEvent(e.type)) { + if (e.type == +#ifdef USE_SDL3 + SDL_EVENT_QUIT +#else + SDL_QUIT +#endif + || IsCustomEvent(e.type)) { *event = e; return true; } - if (IsAnyOf(e.type, SDL_KEYUP, SDL_KEYDOWN) && e.key.keysym.sym == SDLK_UNKNOWN) { - // Erroneous events generated by RG350 kernel. - return true; - } + // Erroneous events generated by RG350 kernel. +#ifdef USE_SDL3 + if (IsAnyOf(e.type, SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP) && e.key.key == SDLK_UNKNOWN) return true; +#else + if (IsAnyOf(e.type, SDL_KEYUP, SDL_KEYDOWN) && e.key.keysym.sym == SDLK_UNKNOWN) return true; +#endif #if !defined(USE_SDL1) && !defined(__vita__) if (!movie_playing) { // SDL generates mouse events from touch-based inputs to provide basic // touchscreeen support for apps that don't explicitly handle touch events - if (IsAnyOf(e.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP) && e.button.which == SDL_TOUCH_MOUSEID) + if (IsAnyOf(e.type, +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP +#else + SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP +#endif + ) + && e.button.which == SDL_TOUCH_MOUSEID) { return true; - if (e.type == SDL_MOUSEMOTION && e.motion.which == SDL_TOUCH_MOUSEID) + } + if (e.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_MOTION +#else + SDL_MOUSEMOTION +#endif + && e.motion.which == SDL_TOUCH_MOUSEID) { return true; - if (e.type == SDL_MOUSEWHEEL && e.wheel.which == SDL_TOUCH_MOUSEID) + } + if (e.type == +#ifdef USE_SDL3 + SDL_EVENT_MOUSE_WHEEL +#else + SDL_MOUSEWHEEL +#endif + && e.wheel.which == SDL_TOUCH_MOUSEID) return true; } #endif @@ -94,6 +131,47 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) return true; switch (e.type) { +#ifdef USE_SDL3 + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_TEXT_EDITING: + case SDL_EVENT_TEXT_INPUT: + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + case SDL_EVENT_WINDOW_SHOWN: + case SDL_EVENT_WINDOW_MINIMIZED: + case SDL_EVENT_WINDOW_MAXIMIZED: + case SDL_EVENT_WINDOW_RESTORED: + case SDL_EVENT_WINDOW_HDR_STATE_CHANGED: + case SDL_EVENT_WINDOW_FOCUS_GAINED: + case SDL_EVENT_WINDOW_FOCUS_LOST: + case SDL_EVENT_MOUSE_WHEEL: + case SDL_EVENT_JOYSTICK_AXIS_MOTION: + case SDL_EVENT_JOYSTICK_HAT_MOTION: + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: + case SDL_EVENT_JOYSTICK_BUTTON_UP: + case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + *event = e; + break; + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + if (e.key.key == SDLK_UNKNOWN) { + return FalseAvail(e.key.down ? "SDL_EVENT_KEY_DOWN" : "SDL_EVENT_KEY_UP", e.key.key); + } + *event = e; + break; + case SDL_EVENT_AUDIO_DEVICE_ADDED: + return FalseAvail("SDL_EVENT_AUDIO_DEVICE_ADDED", e.adevice.which); + case SDL_EVENT_AUDIO_DEVICE_REMOVED: + return FalseAvail("SDL_EVENT_AUDIO_DEVICE_REMOVED", e.adevice.which); + case SDL_EVENT_KEYMAP_CHANGED: + return FalseAvail("SDL_EVENT_KEYMAP_CHANGED", 0); +#else #if SDL_VERSION_ATLEAST(2, 0, 0) case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERBUTTONDOWN: @@ -131,6 +209,7 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) case SDL_KEYMAPCHANGED: return FalseAvail("SDL_KEYMAPCHANGED", 0); #endif +#endif #endif default: return FalseAvail("unknown", e.type); diff --git a/Source/engine/events.hpp b/Source/engine/events.hpp index e7d65ab5f..47eb3230a 100644 --- a/Source/engine/events.hpp +++ b/Source/engine/events.hpp @@ -2,13 +2,17 @@ #include +#ifdef USE_SDL3 +#include +#else #include -#include "engine/point.hpp" - #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #endif +#endif + +#include "engine/point.hpp" namespace devilution { diff --git a/Source/engine/palette.cpp b/Source/engine/palette.cpp index 670c45179..98f3fb5a4 100644 --- a/Source/engine/palette.cpp +++ b/Source/engine/palette.cpp @@ -161,7 +161,7 @@ void SystemPaletteUpdated(int first, int ncolor) return; assert(Palette); - if (SDLC_SetSurfaceAndPaletteColors(PalSurface, Palette.get(), system_palette.data() + first, first, ncolor) < 0) { + if (!SDLC_SetSurfaceAndPaletteColors(PalSurface, Palette.get(), system_palette.data() + first, first, ncolor)) { ErrSdl(); } } diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index 662d49b58..e8ee18aaf 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -9,6 +9,14 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else +#include +#endif + #include #include "DiabloUI/ui_flags.hpp" @@ -530,8 +538,16 @@ void DrawCell(const Surface &out, const Lightmap lightmap, Point tilePosition, P bool transparency = TileHasAny(tilePosition, TileProperties::Transparent) && TransList[dTransVal[tilePosition.x][tilePosition.y]]; #ifdef _DEBUG - if ((SDL_GetModState() & KMOD_ALT) != 0) + if ((SDL_GetModState() & +#ifdef USE_SDL3 + SDL_KMOD_ALT +#else + KMOD_ALT +#endif + ) + != 0) { transparency = false; + } #endif const auto getFirstTileMaskLeft = [=](TileType tile) -> MaskType { @@ -876,7 +892,14 @@ void DrawDungeon(const Surface &out, const Lightmap &lightmap, Point tilePositio bool transparency = TransList[bMap]; #ifdef _DEBUG // Turn transparency off here for debugging - transparency = transparency && (SDL_GetModState() & KMOD_ALT) == 0; + transparency = transparency && (SDL_GetModState() & +#ifdef USE_SDL3 + SDL_KMOD_ALT +#else + KMOD_ALT +#endif + ) + == 0; #endif if (perPixelLighting) { // Create a special lightmap buffer to bleed light up walls @@ -1629,7 +1652,11 @@ void ClearScreenBuffer() return; assert(PalSurface != nullptr); +#ifdef USE_SDL3 + SDL_FillSurfaceRect(PalSurface, nullptr, 0); +#else SDL_FillRect(PalSurface, nullptr, 0); +#endif } #ifdef _DEBUG diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index 0863055c8..d9549784b 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -9,7 +9,17 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#else +#include +#endif + #include "DiabloUI/ui_flags.hpp" +#include "appfat.h" #include "control.h" #include "controls/axis_direction.h" #include "controls/controller_motion.h" @@ -125,7 +135,11 @@ void GmenuDrawMenuItem(const Surface &out, TMenuItem *pItem, int y) const uint16_t steps = std::max(pItem->sliderSteps(), 2); const uint16_t pos = SliderFillMin + step * (SliderFillMax - SliderFillMin) / steps; SDL_Rect rect = MakeSdlRect(SliderValueLeft + uiPositionX, y + SliderValuePaddingTop, pos, SliderValueHeight); +#ifdef USE_SDL3 + SDL_FillSurfaceRect(out.surface, &rect, 205); +#else SDL_FillRect(out.surface, &rect, 205); +#endif ClxDraw(out, { SliderValueLeft + pos - SliderMarkerWidth / 2 + uiPositionX, y + SliderValuePaddingTop + SliderValueHeight - 1 }, (*option_cel)[0]); } diff --git a/Source/gmenu.h b/Source/gmenu.h index 563496c2d..0e8ff88df 100644 --- a/Source/gmenu.h +++ b/Source/gmenu.h @@ -7,6 +7,12 @@ #include +#ifdef USE_SDL3 +#include +#else +#include +#endif + #include "engine/surface.hpp" namespace devilution { diff --git a/Source/hwcursor.cpp b/Source/hwcursor.cpp index 98f8997d9..625e4d433 100644 --- a/Source/hwcursor.cpp +++ b/Source/hwcursor.cpp @@ -3,11 +3,21 @@ #include #include -#if SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef USE_SDL3 +#include +#include +#include +#include +#include +#else +#include + +#ifndef USE_SDL1 #include #include #include #endif +#endif #include "DiabloUI/diabloui.h" @@ -35,9 +45,16 @@ enum class HotpointPosition : uint8_t { Size ScaledSize(Size size) { if (renderer != nullptr) { - float scaleX; - float scaleY; + float scaleX = 1.0F; + float scaleY = 1.0F; +#ifdef USE_SDL3 + if (!SDL_GetRenderScale(renderer, &scaleX, &scaleY)) { + LogError("SDL_GetRenderScale: {}", SDL_GetError()); + SDL_ClearError(); + } +#else SDL_RenderGetScale(renderer, &scaleX, &scaleY); +#endif size.width = static_cast(size.width * scaleX); size.height = static_cast(size.height * scaleY); } @@ -83,7 +100,13 @@ bool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpoin newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(surface, hotpoint.x, hotpoint.y) }; } else { // SDL does not support BlitScaled from 8-bit to RGBA. - const SDLSurfaceUniquePtr converted { SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0) }; + const SDLSurfaceUniquePtr converted { +#ifdef USE_SDL3 + SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888) +#else + SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0) +#endif + }; const SDLSurfaceUniquePtr scaledSurface = SDLWrap::CreateRGBSurfaceWithFormat(0, scaledSize.width, scaledSize.height, 32, SDL_PIXELFORMAT_ARGB8888); if (ShouldUseBilinearScaling()) { @@ -97,7 +120,11 @@ bool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpoin Log("hwcursor: SetHardwareCursorFromSurface {}x{} scaled to {}x{} using nearest neighbour scaling", size.width, size.height, scaledSize.width, scaledSize.height); #endif +#ifdef USE_SDL3 + SDL_BlitSurfaceScaled(converted.get(), nullptr, scaledSurface.get(), nullptr, SDL_SCALEMODE_NEAREST); +#else SDL_BlitScaled(converted.get(), nullptr, scaledSurface.get(), nullptr); +#endif } const Point hotpoint = GetHotpointPosition(*scaledSurface, hotpointPosition); newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(scaledSurface.get(), hotpoint.x, hotpoint.y) }; @@ -107,7 +134,15 @@ bool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpoin SDL_ClearError(); return false; } +#ifdef USE_SDL3 + if (!SDL_SetCursor(newCursor.get())) { + LogError("SDL_SetCursor: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } +#else SDL_SetCursor(newCursor.get()); +#endif CurrentCursor = std::move(newCursor); return true; } @@ -115,8 +150,29 @@ bool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpoin bool SetHardwareCursorFromClxSprite(ClxSprite sprite, HotpointPosition hotpointPosition) { const OwnedSurface surface { sprite.width(), sprite.height() }; - SDL_SetSurfacePalette(surface.surface, Palette.get()); - SDL_SetColorKey(surface.surface, SDL_TRUE, 0); +#ifdef USE_SDL3 + if (!SDL_SetSurfacePalette(surface.surface, Palette.get())) { + LogError("SDL_SetSurfacePalette: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } + if (!SDL_SetSurfaceColorKey(surface.surface, true, 0)) { + LogError("SDL_SetSurfaceColorKey: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } +#else + if (SDL_SetSurfacePalette(surface.surface, Palette.get()) != 0) { + LogError("SDL_SetSurfacePalette: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } + if (SDL_SetColorKey(surface.surface, SDL_TRUE, 0) != 0) { + LogError("SDL_SetColorKey: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } +#endif RenderClxSprite(surface, sprite, { 0, 0 }); return SetHardwareCursorFromSurface(surface.surface, hotpointPosition); } @@ -142,8 +198,29 @@ bool SetHardwareCursorFromSprite(int pcurs) // Transparent color must not be used in the sprite itself. // Colors 1-127 are outside of the UI palette so are safe to use. constexpr std::uint8_t TransparentColor = 1; - SDL_FillRect(out.surface, nullptr, TransparentColor); - SDL_SetColorKey(out.surface, 1, TransparentColor); +#ifdef USE_SDL3 + if (!SDL_FillSurfaceRect(out.surface, nullptr, TransparentColor)) { + LogError("SDL_FillSurfaceRect: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } + if (!SDL_SetSurfaceColorKey(out.surface, true, TransparentColor)) { + LogError("SDL_SetSurfaceColorKey: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } +#else + if (SDL_FillRect(out.surface, nullptr, TransparentColor) != 0) { + LogError("SDL_FillRect: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } + if (SDL_SetColorKey(out.surface, 1, TransparentColor) != 0) { + LogError("SDL_SetColorKey: {}", SDL_GetError()); + SDL_ClearError(); + return false; + } +#endif DrawSoftwareCursor(out, { outlineWidth, size.height - outlineWidth - 1 }, pcurs); const bool result = SetHardwareCursorFromSurface( diff --git a/Source/hwcursor.hpp b/Source/hwcursor.hpp index 2c23b5b59..df946aacd 100644 --- a/Source/hwcursor.hpp +++ b/Source/hwcursor.hpp @@ -7,7 +7,12 @@ #include +#ifdef USE_SDL3 +#include +#include +#else #include +#endif #include "options.h" #include "utils/log.hpp" @@ -139,7 +144,9 @@ inline void DoReinitializeHardwareCursor() inline bool IsHardwareCursorVisible() { -#if SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef USE_SDL3 + return SDL_CursorVisible(); +#elif SDL_VERSION_ATLEAST(2, 0, 0) return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE; #else return false; @@ -157,7 +164,13 @@ inline void SetHardwareCursorVisible(bool visible) #if LOG_HWCURSOR Log("hwcursor: SetHardwareCursorVisible {}", visible); #endif - if (SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE) < 0) { + if ( +#ifdef USE_SDL3 + visible ? SDL_ShowCursor() : SDL_HideCursor() +#else + SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE) < 0 +#endif + ) { LogError("{}", SDL_GetError()); SDL_ClearError(); } diff --git a/Source/init.cpp b/Source/init.cpp index 93456c0f8..d2acda710 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -9,7 +9,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else #include +#endif + #include #include "DiabloUI/diabloui.h" @@ -138,38 +144,77 @@ void init_create_window() void MainWndProc(const SDL_Event &event) { #ifndef USE_SDL1 - if (event.type != SDL_WINDOWEVENT) - return; - switch (event.window.event) { +#ifdef USE_SDL3 + switch (event.type) +#else + if (event.type != SDL_WINDOWEVENT) return; + switch (event.window.event) +#endif + { +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_HIDDEN: + case SDL_EVENT_WINDOW_MINIMIZED: +#else case SDL_WINDOWEVENT_HIDDEN: case SDL_WINDOWEVENT_MINIMIZED: +#endif gbActive = false; break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_SHOWN: + case SDL_EVENT_WINDOW_EXPOSED: + case SDL_EVENT_WINDOW_RESTORED: +#else case SDL_WINDOWEVENT_SHOWN: case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_RESTORED: +#endif gbActive = true; RedrawEverything(); break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: +#else case SDL_WINDOWEVENT_SIZE_CHANGED: +#endif ReinitializeHardwareCursor(); break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_MOUSE_LEAVE: +#else case SDL_WINDOWEVENT_LEAVE: +#endif sgbMouseDown = CLICK_NONE; LastPlayerAction = PlayerActionType::None; RedrawEverything(); break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: +#else case SDL_WINDOWEVENT_CLOSE: +#endif diablo_quit(0); break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_FOCUS_LOST: +#else case SDL_WINDOWEVENT_FOCUS_LOST: +#endif if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_pause(); break; +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_FOCUS_GAINED: +#else case SDL_WINDOWEVENT_FOCUS_GAINED: +#endif if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause(); break; +#ifdef USE_SDL3 + default: + break; +#else case SDL_WINDOWEVENT_MOVED: case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_MAXIMIZED: @@ -179,6 +224,7 @@ void MainWndProc(const SDL_Event &event) default: LogVerbose("Unhandled SDL_WINDOWEVENT event: {:d}", event.window.event); break; +#endif } #else if (event.type != SDL_ACTIVEEVENT) diff --git a/Source/init.hpp b/Source/init.hpp index b6c7a5222..53492e413 100644 --- a/Source/init.hpp +++ b/Source/init.hpp @@ -9,7 +9,11 @@ // https://github.com/bebbo/amiga-gcc/issues/413 #include +#ifdef USE_SDL3 +#include +#else #include +#endif #ifdef UNPACKED_MPQS #include diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 3d65b1af3..37518ebc3 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -9,7 +9,12 @@ #include #ifdef USE_SDL3 +#include #include +#include +#include +#include +#include #include #else #include @@ -66,7 +71,11 @@ const int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } }; OptionalOwnedClxSpriteList ArtCutsceneWidescreen; +#ifdef USE_SDL3 +SdlEventType CustomEventType = SDL_EVENT_USER; +#else SdlEventType CustomEventType = SDL_USEREVENT; +#endif Cutscenes GetCutSceneFromLevelType(dungeon_type type) { @@ -220,7 +229,11 @@ void DrawCutsceneBackground() { const Rectangle &uiRectangle = GetUIRectangle(); const Surface &out = GlobalBackBuffer(); +#ifdef USE_SDL3 + SDL_FillSurfaceRect(out.surface, nullptr, 0); +#else SDL_FillRect(out.surface, nullptr, 0x000000); +#endif if (ArtCutsceneWidescreen) { const ClxSprite sprite = (*ArtCutsceneWidescreen)[0]; RenderClxSprite(out, sprite, { uiRectangle.position.x - (sprite.width() - uiRectangle.size.width) / 2, uiRectangle.position.y }); @@ -238,7 +251,11 @@ void DrawCutsceneForeground() out.region.y + BarPos[progress_id][1] + uiRectangle.position.y, sgdwProgress, ProgressHeight); +#ifdef USE_SDL3 + SDL_FillSurfaceRect(out.surface, &rect, BarColor[progress_id]); +#else SDL_FillRect(out.surface, &rect, BarColor[progress_id]); +#endif if (DiabloUiSurface() == PalSurface) BltFast(&rect, &rect); @@ -293,9 +310,15 @@ bool HandleProgressBarUpdate() SDL_Event event; // We use the real `PollEvent` here instead of `FetchMessage` // to process real events rather than the recorded ones in demo mode. - while (PollEvent(&event) != 0) { + while (PollEvent(&event)) { CheckShouldSkipRendering(); - if (event.type != SDL_QUIT) { + if (event.type != +#ifdef USE_SDL3 + SDL_EVENT_QUIT +#else + SDL_QUIT +#endif + ) { HandleMessage(event, SDL_GetModState()); } if (ProgressEventHandlerState.done) return false; @@ -465,7 +488,13 @@ void DoLoad(interface_mode uMsg) SDL_Event event; CustomEventToSdlEvent(event, WM_ERROR); event.user.data1 = new std::string(std::move(loadResult).error()); - if (SDL_PushEvent(&event) < 0) { + if ( +#ifdef USE_SDL3 + !SDL_PushEvent(&event) +#else + SDL_PushEvent(&event) < 0 +#endif + ) { LogError("Failed to send WM_ERROR {}", SDL_GetError()); SDL_ClearError(); } @@ -477,7 +506,13 @@ void DoLoad(interface_mode uMsg) SDL_Event event; CustomEventToSdlEvent(event, WM_DONE); - if (SDL_PushEvent(&event) < 0) { + if ( +#ifdef USE_SDL3 + !SDL_PushEvent(&event) +#else + SDL_PushEvent(&event) < 0 +#endif + ) { LogError("Failed to send WM_DONE {}", SDL_GetError()); SDL_ClearError(); } @@ -592,7 +627,13 @@ void interface_msg_pump() SDL_Event event; uint16_t modState; while (FetchMessage(&event, &modState)) { - if (event.type != SDL_QUIT) { + if (event.type != +#ifdef USE_SDL3 + SDL_EVENT_QUIT +#else + SDL_QUIT +#endif + ) { HandleMessage(event, modState); } } @@ -609,7 +650,13 @@ void IncProgress(uint32_t steps) if (!HeadlessMode && sgdwProgress != prevProgress) { SDL_Event event; CustomEventToSdlEvent(event, WM_PROGRESS); - if (SDL_PushEvent(&event) < 0) { + if ( +#ifdef USE_SDL3 + !SDL_PushEvent(&event) +#else + SDL_PushEvent(&event) < 0 +#endif + ) { LogError("Failed to send WM_PROGRESS {}", SDL_GetError()); SDL_ClearError(); } diff --git a/Source/inv.cpp b/Source/inv.cpp index cbcb8f54b..b0071d39c 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -9,6 +9,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include #include "DiabloUI/ui_flags.hpp" @@ -34,6 +41,7 @@ #include "qol/stash.h" #include "stores.h" #include "towners.h" +#include "utils/display.h" #include "utils/format_int.hpp" #include "utils/is_of.hpp" #include "utils/language.h" @@ -1088,7 +1096,11 @@ void StartGoldDrop() const Point start = GetPanelPosition(UiPanels::Inventory, { 67, 128 }); SDL_Rect rect = MakeSdlRect(start.x, start.y, 180, 20); +#ifdef USE_SDL3 + SDL_SetTextInputArea(ghMainWnd, &rect, 0); +#else SDL_SetTextInputRect(&rect); +#endif OpenGoldDrop(invIndex, max); } diff --git a/Source/items.cpp b/Source/items.cpp index a81f767a3..96f046ed4 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -19,7 +19,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif + #include #include "DiabloUI/ui_flags.hpp" diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 71c2a5c1f..29ac162dd 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/Source/menu.cpp b/Source/menu.cpp index 6a7241a42..98f5a8a4d 100644 --- a/Source/menu.cpp +++ b/Source/menu.cpp @@ -6,6 +6,13 @@ #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include "DiabloUI/diabloui.h" #include "DiabloUI/settingsmenu.h" #include "engine/assets.hpp" @@ -137,7 +144,11 @@ bool mainmenu_select_hero_dialog(GameData *gameData) void mainmenu_wait_for_button_sound() { +#ifdef USE_SDL3 + SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0); +#else SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000); +#endif UiFadeIn(); SDL_Delay(350); // delay to let button pressed sound finish playing } diff --git a/Source/movie.cpp b/Source/movie.cpp index cb70458fe..c662095e8 100644 --- a/Source/movie.cpp +++ b/Source/movie.cpp @@ -6,6 +6,13 @@ #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include "controls/control_mode.hpp" #include "controls/plrctrls.h" #include "diablo.h" @@ -53,12 +60,30 @@ void play_movie(const char *pszMovie, bool userCanClose) } } switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#else case SDL_KEYDOWN: case SDL_MOUSEBUTTONUP: - if (userCanClose || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) +#endif + if (userCanClose || ( +#ifdef USE_SDL3 + event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE +#else + event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE +#endif + )) movie_playing = false; break; -#ifndef USE_SDL1 +#ifdef USE_SDL3 + case SDL_EVENT_WINDOW_FOCUS_LOST: + if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_pause(); + break; + case SDL_EVENT_WINDOW_FOCUS_GAINED: + if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause(); + break; +#elif !defined(USE_SDL1) case SDL_WINDOWEVENT: if (*GetOptions().Gameplay.pauseOnFocusLoss) { if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) @@ -77,7 +102,11 @@ void play_movie(const char *pszMovie, bool userCanClose) } break; #endif +#ifdef USE_SDL3 + case SDL_EVENT_QUIT: +#else case SDL_QUIT: +#endif SVidPlayEnd(); diablo_quit(0); } diff --git a/Source/msg.cpp b/Source/msg.cpp index 14e49252c..1ebbe08f8 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -11,6 +11,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else +#include +#endif + #include #include diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 079e3c4b9..c563923f5 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -8,7 +8,11 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif #include "diablo.h" #include "engine/animationinfo.h" diff --git a/Source/panels/console.cpp b/Source/panels/console.cpp index 3ec118ce1..272012d80 100644 --- a/Source/panels/console.cpp +++ b/Source/panels/console.cpp @@ -9,6 +9,9 @@ #ifdef USE_SDL3 #include +#include +#include +#include #else #include @@ -31,6 +34,7 @@ #include "lua/autocomplete.hpp" #include "lua/repl.hpp" #include "utils/algorithm/container.hpp" +#include "utils/display.h" #include "utils/sdl_geometry.h" #include "utils/str_cat.hpp" #include "utils/str_split.hpp" @@ -452,7 +456,13 @@ bool ConsoleHandleEvent(const SDL_Event &event) { if (!IsConsoleVisible) { // Make console open on the top-left keyboard key even if it is not a backtick. - if (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_GRAVE) { + if ( +#ifdef USE_SDL3 + event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_GRAVE +#else + event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_GRAVE +#endif + ) { OpenConsole(); return true; } @@ -463,10 +473,23 @@ bool ConsoleHandleEvent(const SDL_Event &event) return true; } const auto modState = SDL_GetModState(); - const bool isShift = (modState & KMOD_SHIFT) != 0; + const bool isShift = (modState & +#ifdef USE_SDL3 + SDL_KMOD_SHIFT +#else + KMOD_SHIFT +#endif + ) + != 0; switch (event.type) { +#ifdef USE_SDL3 + case SDL_EVENT_KEY_DOWN: + switch (event.key.key) +#else case SDL_KEYDOWN: - switch (event.key.keysym.sym) { + switch (event.key.keysym.sym) +#endif + { case SDLK_ESCAPE: if (!AutocompleteSuggestions.empty()) { AutocompleteSuggestions.clear(); @@ -517,14 +540,26 @@ bool ConsoleHandleEvent(const SDL_Event &event) case SDLK_PAGEDOWN: --PendingScrollPages; return true; +#ifdef USE_SDL3 + case SDLK_L: +#else case SDLK_l: +#endif ClearConsole(); return true; default: return false; } break; -#if SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef USE_SDL3 + case SDL_EVENT_MOUSE_WHEEL: + if (event.wheel.integer_y > 0) { + ScrollOffset += ScrollStep; + } else if (event.wheel.integer_y < 0) { + ScrollOffset -= ScrollStep; + } + return true; +#elif SDL_VERSION_ATLEAST(2, 0, 0) case SDL_MOUSEWHEEL: if (event.wheel.y > 0) { ScrollOffset += ScrollStep; @@ -585,8 +620,13 @@ void DrawConsole(const Surface &out) if (FirstRender) { SDL_Rect sdlInputRect = MakeSdlRect(InputRect); +#ifdef USE_SDL3 + SDL_SetTextInputArea(ghMainWnd, &sdlInputRect, ConsoleInputState.cursorPosition()); + SDL_StartTextInput(ghMainWnd); +#else SDL_SetTextInputRect(&sdlInputRect); SDL_StartTextInput(); +#endif FirstRender = false; if (ConsoleLines.empty()) { InitConsole(); diff --git a/Source/pfile.cpp b/Source/pfile.cpp index b6c7ff01f..f8012f27c 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -12,6 +12,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include "codec.h" #include "engine/load_file.hpp" #include "engine/render/primitive_render.hpp" @@ -281,20 +288,37 @@ void CreateDetailDiffs(std::string_view prefix, std::string_view memoryMapFile, // Note: Detail diffs are currently only supported in unit tests const std::string memoryMapFileAssetName = StrCat(paths::BasePath(), "/test/fixtures/memory_map/", memoryMapFile, ".txt"); +#ifdef USE_SDL3 + SDL_IOStream *handle = SDL_IOFromFile(memoryMapFileAssetName.c_str(), "r"); +#else SDL_RWops *handle = SDL_RWFromFile(memoryMapFileAssetName.c_str(), "r"); +#endif if (handle == nullptr) { app_fatal(StrCat("MemoryMapFile ", memoryMapFile, " is missing")); return; } - const size_t readBytes = static_cast(SDL_RWsize(handle)); + const size_t readBytes = static_cast( +#ifdef USE_SDL3 + SDL_GetIOSize(handle) +#else + SDL_RWsize(handle) +#endif + ); const std::unique_ptr memoryMapFileData { new std::byte[readBytes] }; -#if SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef USE_SDL3 + SDL_ReadIO(handle, memoryMapFileData.get(), readBytes); +#elif SDL_VERSION_ATLEAST(2, 0, 0) SDL_RWread(handle, memoryMapFileData.get(), readBytes, 1); #else SDL_RWread(handle, memoryMapFileData.get(), static_cast(readBytes), 1); #endif + +#ifdef USE_SDL3 + SDL_CloseIO(handle); +#else SDL_RWclose(handle); +#endif const std::string_view buffer(reinterpret_cast(memoryMapFileData.get()), readBytes); diff --git a/Source/player.cpp b/Source/player.cpp index fec8fa23f..23688db7c 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -7,6 +7,13 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#else +#include +#endif + #include #include "control.h" diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index 782c16227..9d45ac84e 100644 --- a/Source/plrmsg.cpp +++ b/Source/plrmsg.cpp @@ -9,6 +9,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else +#include +#endif + #include #include "control.h" @@ -27,7 +33,7 @@ namespace { struct PlayerMessage { /** Time message was received */ - Uint32 time; + uint32_t time; /** The default text color */ UiFlags style; /** The text message to display on screen */ diff --git a/Source/plrmsg.h b/Source/plrmsg.h index 7d3c0b67f..4c038ee2a 100644 --- a/Source/plrmsg.h +++ b/Source/plrmsg.h @@ -9,8 +9,6 @@ #include #include -#include - #include "DiabloUI/ui_flags.hpp" #include "engine/surface.hpp" #include "player.h" diff --git a/Source/restrict.cpp b/Source/restrict.cpp index 654bdb0ab..180cb0703 100644 --- a/Source/restrict.cpp +++ b/Source/restrict.cpp @@ -4,23 +4,37 @@ * Implementation of functionality for checking if the game will be able run on the system. */ +#include + #include "appfat.h" #include "utils/file_util.h" #include "utils/paths.h" +#ifdef USE_SDL3 +#include +#else #include +#endif namespace devilution { void ReadOnlyTest() { const std::string path = paths::PrefPath() + "Diablo1ReadOnlyTest.foo"; +#ifdef USE_SDL3 + SDL_IOStream *file = SDL_IOFromFile(path.c_str(), "w"); +#else SDL_RWops *file = SDL_RWFromFile(path.c_str(), "w"); +#endif if (file == nullptr) { DirErrorDlg(paths::PrefPath()); } +#ifdef USE_SDL3 + SDL_CloseIO(file); +#else SDL_RWclose(file); +#endif RemoveFile(path.c_str()); } diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 44e3587a1..f1aaae8b4 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -5,6 +5,16 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#include +#else +#include +#endif + #include #ifndef NOSOUND @@ -39,7 +49,7 @@ constexpr uint64_t TimeMsToSmk(uint64_t ms) { return ms * SmackerTimeUnit; } constexpr uint64_t TimeSmkToMs(uint64_t time) { return time / SmackerTimeUnit; }; uint64_t GetTicksSmk() { -#if SDL_VERSION_ATLEAST(2, 0, 18) +#if SDL_VERSION_ATLEAST(2, 0, 18) && !defined(USE_SDL3) return TimeMsToSmk(SDL_GetTicks64()); #else return TimeMsToSmk(SDL_GetTicks()); @@ -180,7 +190,15 @@ void UpdatePalette() if (SDL_SetSurfacePalette(SVidSurface.get(), SVidPalette.get()) <= -1) { ErrSdl(); } - if (GetOutputSurface()->format->BitsPerPixel == 8) { + + const SDL_Surface *surface = GetOutputSurface(); + if ( +#ifdef USE_SDL3 + SDL_BITSPERPIXEL(surface->format) +#else + surface->format->BitsPerPixel +#endif + == 8) { if (SDL_SetSurfacePalette(GetOutputSurface(), SVidPalette.get()) <= -1) { ErrSdl(); } @@ -192,7 +210,13 @@ bool BlitFrame() { #ifndef USE_SDL1 if (renderer != nullptr) { - if (SDL_BlitSurface(SVidSurface.get(), nullptr, GetOutputSurface(), nullptr) <= -1) { + if ( +#ifdef USE_SDL3 + SDL_BlitSurface(SVidSurface.get(), nullptr, GetOutputSurface(), nullptr) +#else + SDL_BlitSurface(SVidSurface.get(), nullptr, GetOutputSurface(), nullptr) <= -1 +#endif + ) { Log("{}", SDL_GetError()); return false; } @@ -203,7 +227,12 @@ bool BlitFrame() #ifdef USE_SDL1 const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputSurface->format); #else + +#ifdef USE_SDL3 + const SDL_PixelFormat wndFormat = SDL_GetWindowPixelFormat(ghMainWnd); +#else const Uint32 wndFormat = SDL_GetWindowPixelFormat(ghMainWnd); +#endif const bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(wndFormat); #endif SDL_Rect outputRect; @@ -224,7 +253,13 @@ bool BlitFrame() if (isIndexedOutputFormat || outputSurface->w == static_cast(SVidWidth) || outputSurface->h == static_cast(SVidHeight)) { - if (SDL_BlitSurface(SVidSurface.get(), nullptr, outputSurface, &outputRect) <= -1) { + if ( +#ifdef USE_SDL3 + SDL_BlitSurface(SVidSurface.get(), nullptr, outputSurface, &outputRect) +#else + SDL_BlitSurface(SVidSurface.get(), nullptr, outputSurface, &outputRect) <= -1 +#endif + ) { ErrSdl(); } } else { @@ -235,7 +270,13 @@ bool BlitFrame() #else SDLSurfaceUniquePtr converted = SDLWrap::ConvertSurfaceFormat(SVidSurface.get(), wndFormat, 0); #endif - if (SDL_BlitScaled(converted.get(), nullptr, outputSurface, &outputRect) <= -1) { + if ( +#ifdef USE_SDL3 + SDL_BlitSurfaceScaled(converted.get(), nullptr, outputSurface, &outputRect, SDL_SCALEMODE_LINEAR) +#else + SDL_BlitScaled(converted.get(), nullptr, outputSurface, &outputRect) <= -1 +#endif + ) { Log("{}", SDL_GetError()); return false; } @@ -264,7 +305,7 @@ bool SVidPlayBegin(const char *filename, int flags) // 0x800000 // Edge detection // 0x200800 // Clear FB - SDL_RWops *videoStream = OpenAssetAsSdlRwOps(filename); + auto *videoStream = OpenAssetAsSdlRwOps(filename); SVidHandle = Smacker_Open(videoStream); if (!SVidHandle.isValid) { return false; @@ -312,7 +353,14 @@ bool SVidPlayBegin(const char *filename, int flags) const int renderWidth = static_cast(SVidWidth); const int renderHeight = static_cast(SVidHeight); texture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, renderWidth, renderHeight); - if (SDL_RenderSetLogicalSize(renderer, renderWidth, renderHeight) <= -1) { + if ( +#ifdef USE_SDL3 + !SDL_SetRenderLogicalPresentation(renderer, renderWidth, renderHeight, + *GetOptions().Graphics.integerScaling ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_STRETCH) +#else + SDL_RenderSetLogicalSize(renderer, renderWidth, renderHeight) <= -1 +#endif + ) { ErrSdl(); } } @@ -330,7 +378,11 @@ bool SVidPlayBegin(const char *filename, int flags) #endif // Set the background to black. +#ifdef USE_SDL3 + SDL_FillSurfaceRect(GetOutputSurface(), nullptr, 0x000000); +#else SDL_FillRect(GetOutputSurface(), nullptr, 0x000000); +#endif // The buffer for the frame. It is not the same as the SDL surface because the SDL surface also has pitch padding. SVidFrameBuffer = std::unique_ptr { new uint8_t[static_cast(SVidWidth * SVidHeight)] }; @@ -415,7 +467,14 @@ void SVidPlayEnd() #ifndef USE_SDL1 if (renderer != nullptr) { texture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight); - if (renderer != nullptr && SDL_RenderSetLogicalSize(renderer, gnScreenWidth, gnScreenHeight) <= -1) { + if ( +#ifdef USE_SDL3 + !SDL_SetRenderLogicalPresentation(renderer, gnScreenWidth, gnScreenHeight, + *GetOptions().Graphics.integerScaling ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_STRETCH) +#else + SDL_RenderSetLogicalSize(renderer, gnScreenWidth, gnScreenHeight) <= -1 +#endif + ) { ErrSdl(); } } diff --git a/Source/tmsg.cpp b/Source/tmsg.cpp index 1ee1cf137..4307ccf94 100644 --- a/Source/tmsg.cpp +++ b/Source/tmsg.cpp @@ -3,9 +3,14 @@ * * Implementation of functionality transmitting chat messages. */ +#include #include -#include +#ifdef USE_SDL3 +#include +#else +#include +#endif #include "diablo.h" #include "tmsg.h" diff --git a/Source/track.cpp b/Source/track.cpp index 5e106a720..5804ed136 100644 --- a/Source/track.cpp +++ b/Source/track.cpp @@ -5,8 +5,6 @@ */ #include "track.h" -#include - #include "controls/control_mode.hpp" #include "controls/game_controls.h" #include "controls/plrctrls.h" diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 0150ee9c5..6e72e7a84 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -5,6 +5,22 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#include +#include +#else +#include +#ifdef USE_SDL1 +#include "utils/sdl2_to_1_2_backports.h" +#else +#include "utils/sdl2_backports.h" +#endif +#endif + #ifdef __vita__ #include #endif @@ -136,11 +152,16 @@ const auto OptionChangeHandlerFullscreen = (GetOptions().Graphics.fullscreen.Set void OptionGrabInputChanged() { -#ifdef USE_SDL1 - SDL_WM_GrabInput(*GetOptions().Gameplay.grabInput ? SDL_GRAB_ON : SDL_GRAB_OFF); -#else - if (ghMainWnd != nullptr) +#ifdef USE_SDL3 + if (ghMainWnd != nullptr) { + SDL_SetWindowMouseGrab(ghMainWnd, *GetOptions().Gameplay.grabInput); + } +#elif !defined(USE_SDL1) + if (ghMainWnd != nullptr) { SDL_SetWindowGrab(ghMainWnd, *GetOptions().Gameplay.grabInput ? SDL_TRUE : SDL_FALSE); + } +#else + SDL_WM_GrabInput(*GetOptions().Gameplay.grabInput ? SDL_GRAB_ON : SDL_GRAB_OFF); #endif } const auto OptionChangeHandlerGrabInput = (GetOptions().Gameplay.grabInput.SetValueChangedCallback(OptionGrabInputChanged), true); @@ -267,11 +288,23 @@ const auto OptionChangeHandlerVSync = (GetOptions().Graphics.frameRateControl.Se struct DisplayModeComparator { Size size; +#ifdef USE_SDL3 + SDL_PixelFormat pixelFormat; +#else SDL_PixelFormatEnum pixelFormat; +#endif // Is `a` better than `b`? +#ifdef USE_SDL3 + [[nodiscard]] bool operator()(const SDL_DisplayMode *aPtr, const SDL_DisplayMode *bPtr) +#else [[nodiscard]] bool operator()(const SDL_DisplayMode &a, const SDL_DisplayMode &b) +#endif { +#ifdef USE_SDL3 + const SDL_DisplayMode &a = *aPtr; + const SDL_DisplayMode &b = *bPtr; +#endif const int dwa = a.w - size.width; const int dha = a.h - size.height; const int dwb = b.w - size.width; @@ -302,11 +335,29 @@ struct DisplayModeComparator { } // namespace #if SDL_VERSION_ATLEAST(2, 0, 0) -SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat) +SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, +#ifdef USE_SDL3 + SDL_PixelFormat preferredPixelFormat +#else + SDL_PixelFormatEnum preferredPixelFormat +#endif +) { - SDL_DisplayMode nearestDisplayMode; - if (SDL_GetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) - ErrSdl(); + SDL_DisplayMode *nearestDisplayMode = nullptr; +#ifdef USE_SDL3 + const SDL_DisplayMode *fullscreenMode = SDL_GetWindowFullscreenMode(ghMainWnd); + if (fullscreenMode == nullptr) ErrSdl(); + const SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd); + if (displayId == 0) ErrSdl(); + int modeCount; + SDLUniquePtr modes { SDL_GetFullscreenDisplayModes(displayId, &modeCount) }; + if (modes == nullptr) ErrSdl(); + nearestDisplayMode = *std::min_element( + modes.get(), modes.get() + modeCount, DisplayModeComparator { preferredSize, preferredPixelFormat }); +#else + SDL_DisplayMode ownedNearestDisplayMode; + if (SDL_GetWindowDisplayMode(ghMainWnd, &ownedNearestDisplayMode) != 0) ErrSdl(); + nearestDisplayMode = &ownedNearestDisplayMode; const int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd); const int modeCount = SDL_GetNumDisplayModes(displayIndex); @@ -321,17 +372,18 @@ SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum pr modes.push_back(displayMode); } if (!modes.empty()) { - nearestDisplayMode = *std::min_element( + nearestDisplayMode = &*std::min_element( modes.begin(), modes.end(), DisplayModeComparator { preferredSize, preferredPixelFormat }); } +#endif LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz", preferredSize.width, preferredSize.height, - nearestDisplayMode.w, nearestDisplayMode.h, - SDL_BITSPERPIXEL(nearestDisplayMode.format), - nearestDisplayMode.refresh_rate); + nearestDisplayMode->w, nearestDisplayMode->h, + SDL_BITSPERPIXEL(nearestDisplayMode->format), + nearestDisplayMode->refresh_rate); - return nearestDisplayMode; + return *nearestDisplayMode; } #endif @@ -353,7 +405,11 @@ float GetDpiScalingFactor() int renderWidth; int renderHeight; +#ifdef USE_SDL3 + SDL_GetCurrentRenderOutputSize(renderer, &renderWidth, &renderHeight); +#else SDL_GetRendererOutputSize(renderer, &renderWidth, &renderHeight); +#endif int windowWidth; int windowHeight; @@ -399,10 +455,12 @@ void SetVideoModeToPrimary(bool fullscreen, int width, int height) bool IsFullScreen() { -#ifdef USE_SDL1 - return (SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) != 0; -#else +#ifdef USE_SDL3 + return (SDL_GetWindowFlags(ghMainWnd) & SDL_WINDOW_FULLSCREEN) != 0; +#elif !defined(USE_SDL1) return (SDL_GetWindowFlags(ghMainWnd) & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0; +#else + return (SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) != 0; #endif } @@ -424,7 +482,10 @@ bool SpawnWindow(const char *lpWindowName) } #endif -#if SDL_VERSION_ATLEAST(2, 0, 4) +#ifdef USE_SDL3 + SDL_SetHint(SDL_HINT_RETURN_KEY_HIDES_IME, "1"); +#endif +#if SDL_VERSION_ATLEAST(2, 0, 4) && !defined(USE_SDL3) SDL_SetHint(SDL_HINT_IME_INTERNAL_EDITING, "1"); #endif #if SDL_VERSION_ATLEAST(2, 0, 6) && defined(__vita__) @@ -433,10 +494,12 @@ bool SpawnWindow(const char *lpWindowName) #if SDL_VERSION_ATLEAST(2, 0, 10) SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); #endif -#if SDL_VERSION_ATLEAST(2, 0, 2) +#ifdef USE_SDL3 + SDL_SetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION, "0"); +#elif SDL_VERSION_ATLEAST(2, 0, 2) SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); #endif -#if SDL_VERSION_ATLEAST(2, 0, 12) +#if SDL_VERSION_ATLEAST(2, 0, 12) && !defined(USE_SDL3) SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); #endif @@ -445,7 +508,11 @@ bool SpawnWindow(const char *lpWindowName) initFlags |= SDL_INIT_AUDIO; #endif #ifndef USE_SDL1 +#ifdef USE_SDL3 + initFlags |= SDL_INIT_GAMEPAD; +#else initFlags |= SDL_INIT_GAMECONTROLLER; +#endif SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); #endif @@ -456,7 +523,11 @@ bool SpawnWindow(const char *lpWindowName) #ifndef USE_SDL1 if (GetOptions().Controller.szMapping[0] != '\0') { +#ifdef USE_SDL3 + SDL_AddGamepadMapping(GetOptions().Controller.szMapping); +#else SDL_GameControllerAddMapping(GetOptions().Controller.szMapping); +#endif } #endif @@ -478,31 +549,52 @@ bool SpawnWindow(const char *lpWindowName) if (*GetOptions().Gameplay.grabInput) SDL_WM_GrabInput(SDL_GRAB_ON); atexit(SDL_VideoQuit); // Without this video mode is not restored after fullscreen. +#else +#ifdef USE_SDL3 + int flags = SDL_WINDOW_HIGH_PIXEL_DENSITY; #else int flags = SDL_WINDOW_ALLOW_HIGHDPI; +#endif if (*GetOptions().Graphics.upscale) { if (*GetOptions().Graphics.fullscreen) { +#ifdef USE_SDL3 + flags |= SDL_WINDOW_FULLSCREEN; +#else flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif } flags |= SDL_WINDOW_RESIZABLE; } else if (*GetOptions().Graphics.fullscreen) { flags |= SDL_WINDOW_FULLSCREEN; } +#ifdef USE_SDL3 + ghMainWnd = SDL_CreateWindow(lpWindowName, windowSize.width, windowSize.height, flags); +#else ghMainWnd = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowSize.width, windowSize.height, flags); +#endif #if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT); - if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) { - ErrSdl(); - } +#if USE_SDL3 + if (SDL_SetWindowFullscreenMode(ghMainWnd, &nearestDisplayMode) != 0) ErrSdl(); +#else + if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) ErrSdl(); +#endif #endif - // Note: https://github.com/libsdl-org/SDL/issues/962 - // This is a solution to a problem related to SDL mouse grab. - // See https://github.com/diasurgical/devilutionX/issues/4251 - if (ghMainWnd != nullptr) +// Note: https://github.com/libsdl-org/SDL/issues/962 +// This is a solution to a problem related to SDL mouse grab. +// See https://github.com/diasurgical/devilutionX/issues/4251 +#ifdef USE_SDL3 + if (ghMainWnd != nullptr) { + SDL_SetWindowMouseGrab(ghMainWnd, *GetOptions().Gameplay.grabInput); + } +#else + if (ghMainWnd != nullptr) { SDL_SetWindowGrab(ghMainWnd, *GetOptions().Gameplay.grabInput ? SDL_TRUE : SDL_FALSE); + } +#endif #endif if (ghMainWnd == nullptr) { @@ -511,11 +603,21 @@ bool SpawnWindow(const char *lpWindowName) int refreshRate = 60; #ifndef USE_SDL1 +#ifdef USE_SDL3 + const SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd); + if (displayId == 0) ErrSdl(); + const SDL_DisplayMode *displayMode = SDL_GetCurrentDisplayMode(displayId); + if (displayMode == nullptr) ErrSdl(); + if (displayMode->refresh_rate != 0.F) { + refreshRate = static_cast(displayMode->refresh_rate); + } +#else SDL_DisplayMode mode; SDL_GetDisplayMode(0, 0, &mode); if (mode.refresh_rate != 0) { refreshRate = mode.refresh_rate; } +#endif #endif refreshDelay = 1000000 / refreshRate; @@ -539,9 +641,16 @@ void ReinitializeTexture() return; auto quality = StrCat(static_cast(*GetOptions().Graphics.scaleQuality)); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality.c_str()); +#ifdef USE_SDL3 texture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight); + if (quality == "nearest") { + SDL_SetTextureScaleMode(texture.get(), SDL_SCALEMODE_NEAREST); + } +#else + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality.c_str()); + texture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight); +#endif } void ReinitializeIntegerScale() @@ -550,10 +659,21 @@ void ReinitializeIntegerScale() ResizeWindow(); return; } + if (renderer == nullptr) return; - if (renderer != nullptr && SDL_RenderSetIntegerScale(renderer, *GetOptions().Graphics.integerScaling ? SDL_TRUE : SDL_FALSE) < 0) { +#ifdef USE_SDL3 + int w, h; + SDL_RendererLogicalPresentation mode; + if (!SDL_GetRenderLogicalPresentation(renderer, &w, &h, &mode)) ErrSdl(); + const SDL_RendererLogicalPresentation newMode = *GetOptions().Graphics.integerScaling + ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE + : SDL_LOGICAL_PRESENTATION_LETTERBOX; + if (mode != newMode) SDL_SetRenderLogicalPresentation(renderer, w, h, newMode); +#else + if (SDL_RenderSetIntegerScale(renderer, *GetOptions().Graphics.integerScaling ? SDL_TRUE : SDL_FALSE) < 0) { ErrSdl(); } +#endif } #endif @@ -573,18 +693,32 @@ void ReinitializeRenderer() if (*GetOptions().Graphics.upscale) { // We don't recreate the renderer, because this can result in a freezing (not refreshing) rendering if (renderer == nullptr) { +#ifdef USE_SDL3 + renderer = SDL_CreateRenderer(ghMainWnd, nullptr); +#else renderer = SDL_CreateRenderer(ghMainWnd, -1, 0); +#endif if (renderer == nullptr) { ErrSdl(); } } -#if SDL_VERSION_ATLEAST(2, 0, 18) +#ifdef USE_SDL3 + SDL_SetRenderVSync(renderer, *GetOptions().Graphics.frameRateControl == FrameRateControl::VerticalSync ? 1 : 0); +#elif SDL_VERSION_ATLEAST(2, 0, 18) SDL_RenderSetVSync(renderer, *GetOptions().Graphics.frameRateControl == FrameRateControl::VerticalSync ? 1 : 0); #endif ReinitializeTexture(); +#ifdef USE_SDL3 + if (!SDL_SetRenderLogicalPresentation(renderer, gnScreenWidth, gnScreenHeight, + *GetOptions().Graphics.integerScaling + ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE + : SDL_LOGICAL_PRESENTATION_LETTERBOX)) { + ErrSdl(); + } +#else if (SDL_RenderSetIntegerScale(renderer, *GetOptions().Graphics.integerScaling ? SDL_TRUE : SDL_FALSE) < 0) { ErrSdl(); } @@ -592,11 +726,16 @@ void ReinitializeRenderer() if (SDL_RenderSetLogicalSize(renderer, gnScreenWidth, gnScreenHeight) <= -1) { ErrSdl(); } +#endif +#ifdef USE_SDL3 + RendererTextureSurface = SDLSurfaceUniquePtr { SDL_CreateSurface(gnScreenWidth, gnScreenHeight, texture->format) }; + if (RendererTextureSurface == nullptr) ErrSdl(); +#else Uint32 format; - if (SDL_QueryTexture(texture.get(), &format, nullptr, nullptr, nullptr) < 0) - ErrSdl(); + if (SDL_QueryTexture(texture.get(), &format, nullptr, nullptr, nullptr) < 0) ErrSdl(); RendererTextureSurface = SDLWrap::CreateRGBSurfaceWithFormat(0, gnScreenWidth, gnScreenHeight, SDL_BITSPERPIXEL(format), format); +#endif } else { Size windowSize = {}; SDL_GetWindowSize(ghMainWnd, &windowSize.width, &windowSize.height); @@ -623,14 +762,20 @@ void SetFullscreenMode() if (*GetOptions().Graphics.fullscreen && !*GetOptions().Graphics.upscale) { const Size windowSize = GetPreferredWindowSize(); const SDL_DisplayMode displayMode = GetNearestDisplayMode(windowSize); - if (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) { - ErrSdl(); - } +#ifdef USE_SDL3 + if (!SDL_SetWindowFullscreenMode(ghMainWnd, &displayMode)) ErrSdl(); +#else + if (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) ErrSdl(); +#endif } Uint32 flags = 0; if (*GetOptions().Graphics.fullscreen) { +#if USE_SDL3 + flags = SDL_WINDOW_FULLSCREEN; +#else flags = *GetOptions().Graphics.upscale ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN; +#endif } if (SDL_SetWindowFullscreen(ghMainWnd, flags) != 0) { ErrSdl(); @@ -666,14 +811,21 @@ void ResizeWindow() const bool trueFullscreen = *GetOptions().Graphics.fullscreen && !*GetOptions().Graphics.upscale; if (trueFullscreen) { const SDL_DisplayMode displayMode = GetNearestDisplayMode(windowSize); - if (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) - ErrSdl(); +#ifdef USE_SDL3 + if (!SDL_SetWindowFullscreenMode(ghMainWnd, &displayMode)) ErrSdl(); +#else + if (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) ErrSdl(); +#endif } // Handle switching between "fake fullscreen" and "true fullscreen" when upscale is toggled const bool upscaleChanged = *GetOptions().Graphics.upscale != (renderer != nullptr); if (upscaleChanged && *GetOptions().Graphics.fullscreen) { +#ifdef USE_SDL3 + const Uint32 flags = SDL_WINDOW_FULLSCREEN; +#else const Uint32 flags = *GetOptions().Graphics.upscale ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN; +#endif if (SDL_SetWindowFullscreen(ghMainWnd, flags) != 0) ErrSdl(); if (!*GetOptions().Graphics.fullscreen) @@ -687,7 +839,11 @@ void ResizeWindow() ReinitializeRenderer(); #ifndef USE_SDL1 +#ifdef USE_SDL3 + SDL_SetWindowResizable(ghMainWnd, renderer != nullptr); +#else SDL_SetWindowResizable(ghMainWnd, renderer != nullptr ? SDL_TRUE : SDL_FALSE); +#endif InitializeVirtualGamepad(); #endif diff --git a/Source/utils/display.h b/Source/utils/display.h index f0e70b423..68b6a6a07 100644 --- a/Source/utils/display.h +++ b/Source/utils/display.h @@ -3,12 +3,19 @@ #include #include +#ifdef USE_SDL3 +#include +#include +#include +#include +#else #include #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" #else #include "utils/sdl2_backports.h" #endif +#endif #include "utils/attributes.h" #include "utils/sdl_ptrs.h" @@ -62,14 +69,22 @@ void OutputToLogical(T *x, T *y) return; float scaleX; - SDL_RenderGetScale(renderer, &scaleX, NULL); +#ifdef USE_SDL3 + SDL_GetRenderScale(renderer, &scaleX, nullptr); +#else + SDL_RenderGetScale(renderer, &scaleX, nullptr); +#endif float scaleDpi = GetDpiScalingFactor(); float scale = scaleX / scaleDpi; *x = static_cast(*x / scale); *y = static_cast(*y / scale); SDL_Rect view; +#ifdef USE_SDL3 + SDL_GetRenderViewport(renderer, &view); +#else SDL_RenderGetViewport(renderer, &view); +#endif *x -= view.x; *y -= view.y; #else @@ -90,12 +105,20 @@ void LogicalToOutput(T *x, T *y) if (!renderer) return; SDL_Rect view; +#ifdef USE_SDL3 + SDL_GetRenderViewport(renderer, &view); +#else SDL_RenderGetViewport(renderer, &view); +#endif *x += view.x; *y += view.y; float scaleX; - SDL_RenderGetScale(renderer, &scaleX, NULL); +#ifdef USE_SDL3 + SDL_GetRenderScale(renderer, &scaleX, nullptr); +#else + SDL_RenderGetScale(renderer, &scaleX, nullptr); +#endif float scaleDpi = GetDpiScalingFactor(); float scale = scaleX / scaleDpi; *x = static_cast(*x * scale); @@ -110,7 +133,13 @@ void LogicalToOutput(T *x, T *y) } #if SDL_VERSION_ATLEAST(2, 0, 0) -SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN); +SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, +#ifdef USE_SDL3 + SDL_PixelFormat preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN +#else + SDL_PixelFormatEnum preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN +#endif +); #endif } // namespace devilution diff --git a/Source/utils/png.h b/Source/utils/png.h index d898c7f73..36edafeba 100644 --- a/Source/utils/png.h +++ b/Source/utils/png.h @@ -1,9 +1,15 @@ #pragma once +#ifdef USE_SDL3 +#include +#include +#else #include +#endif #include "engine/assets.hpp" +#ifndef USE_SDL3 #ifdef __cplusplus extern "C" { #endif @@ -26,9 +32,11 @@ inline SDL_Surface *IMG_LoadPNG(const char *file) #ifdef __cplusplus } #endif +#endif namespace devilution { +#ifndef USE_SDL3 inline int InitPNG() { return IMG_Init(IMG_INIT_PNG); @@ -38,12 +46,18 @@ inline void QuitPNG() { IMG_Quit(); } +#endif inline SDL_Surface *LoadPNG(const char *file) { - SDL_RWops *rwops = OpenAssetAsSdlRwOps(file); + auto *rwops = OpenAssetAsSdlRwOps(file); +#ifdef USE_SDL3 + SDL_Surface *surface = IMG_LoadPNG_IO(rwops); + SDL_CloseIO(rwops); +#else SDL_Surface *surface = IMG_LoadPNG_RW(rwops); SDL_RWclose(rwops); +#endif return surface; } diff --git a/Source/utils/sdl_bilinear_scale.cpp b/Source/utils/sdl_bilinear_scale.cpp index 9164d7097..ff72166fb 100644 --- a/Source/utils/sdl_bilinear_scale.cpp +++ b/Source/utils/sdl_bilinear_scale.cpp @@ -1,8 +1,19 @@ #include "utils/sdl_bilinear_scale.hpp" +#include #include #include +#ifdef USE_SDL3 +#include +#include +#include +#else +#include +#endif + +#include "appfat.h" + // Performs bilinear scaling using fixed-width integer math. namespace devilution { @@ -148,16 +159,25 @@ void BilinearScale32(SDL_Surface *src, SDL_Surface *dst) } } -void BilinearDownscaleByHalf8(const SDL_Surface *src, const Uint8 paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex) +void BilinearDownscaleByHalf8(SDL_Surface *src, const uint8_t paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex) { + SDL_Rect srcClipRect, dstClipRect; +#ifdef USE_SDL3 + if (!SDL_GetSurfaceClipRect(src, &srcClipRect)) app_fatal(SDL_GetError()); + if (!SDL_GetSurfaceClipRect(dst, &dstClipRect)) app_fatal(SDL_GetError()); +#else + srcClipRect = src->clip_rect; + dstClipRect = dst->clip_rect; +#endif + const auto *const srcPixelsBegin = static_cast(src->pixels) - + static_cast(src->clip_rect.y * src->pitch + src->clip_rect.x); + + static_cast((srcClipRect.y * src->pitch) + srcClipRect.x); auto *const dstPixelsBegin = static_cast(dst->pixels) - + static_cast(dst->clip_rect.y * dst->pitch + dst->clip_rect.x); - for (unsigned y = 0, h = static_cast(dst->clip_rect.h); y < h; ++y) { + + static_cast((dstClipRect.y * dst->pitch) + dstClipRect.x); + for (unsigned y = 0, h = static_cast(dstClipRect.h); y < h; ++y) { const uint8_t *srcPixels = srcPixelsBegin + static_cast(2 * y * src->pitch); uint8_t *dstPixels = dstPixelsBegin + static_cast(y * dst->pitch); - for (unsigned x = 0, w = static_cast(dst->clip_rect.w); x < w; ++x) { + for (unsigned x = 0, w = static_cast(dstClipRect.w); x < w; ++x) { uint8_t quad[] = { srcPixels[0], srcPixels[1], diff --git a/Source/utils/sdl_bilinear_scale.hpp b/Source/utils/sdl_bilinear_scale.hpp index b35670363..04675e835 100644 --- a/Source/utils/sdl_bilinear_scale.hpp +++ b/Source/utils/sdl_bilinear_scale.hpp @@ -2,12 +2,10 @@ #include -#include - -#if SDL_VERSION_ATLEAST(2, 0, 0) -#include +#ifdef USE_SDL3 +#include #else -#include +#include #endif namespace devilution { @@ -22,6 +20,6 @@ void BilinearScale32(SDL_Surface *src, SDL_Surface *dst); * @brief Streamlined bilinear downscaling using blended transparency table. * Requires `src` and `dst` to have the same pixel format (INDEX8). */ -void BilinearDownscaleByHalf8(const SDL_Surface *src, const Uint8 paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex); +void BilinearDownscaleByHalf8(SDL_Surface *src, const uint8_t paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex); } // namespace devilution diff --git a/Source/utils/sdl_compat.h b/Source/utils/sdl_compat.h index 84ee9c0b4..bb42a5260 100644 --- a/Source/utils/sdl_compat.h +++ b/Source/utils/sdl_compat.h @@ -1,6 +1,13 @@ // Compatibility wrappers for SDL 1 & 2. #pragma once + +#ifdef USE_SDL3 +#include +#include +#include +#else #include +#endif #ifndef USE_SDL1 #define SDLC_KEYSTATE_LEFTCTRL SDL_SCANCODE_LCTRL @@ -26,49 +33,28 @@ #define SDLC_KEYSTATE_RIGHT SDLK_RIGHT #endif -inline const Uint8 *SDLC_GetKeyState() -{ -#ifndef USE_SDL1 - return SDL_GetKeyboardState(NULL); -#else - return SDL_GetKeyState(NULL); -#endif -} - -inline int SDLC_SetColorKey(SDL_Surface *surface, Uint32 key) -{ -#ifdef USE_SDL1 - return SDL_SetColorKey(surface, SDL_SRCCOLORKEY, key); +#ifdef USE_SDL3 +inline const bool *SDLC_GetKeyState() #else - return SDL_SetColorKey(surface, SDL_TRUE, key); +inline const Uint8 *SDLC_GetKeyState() #endif -} - -// Copies the colors into the surface's palette. -inline int SDLC_SetSurfaceColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors) { -#ifdef USE_SDL1 - return SDL_SetPalette(surface, SDL_LOGPAL, colors, firstcolor, ncolors) - 1; +#ifndef USE_SDL1 + return SDL_GetKeyboardState(nullptr); #else - return SDL_SetPaletteColors(surface->format->palette, colors, firstcolor, ncolors); + return SDL_GetKeyState(nullptr); #endif } -// Copies the colors into the surface's palette. -inline int SDLC_SetSurfaceColors(SDL_Surface *surface, SDL_Palette *palette) -{ - return SDLC_SetSurfaceColors(surface, palette->colors, 0, palette->ncolors); -} - // Sets the palette's colors and: -// SDL2: Points the surface's palette to the given palette if necessary. +// SDL3 and SDL2: Points the surface's palette to the given palette if necessary. // SDL1: Sets the surface's colors. -inline int SDLC_SetSurfaceAndPaletteColors(SDL_Surface *surface, SDL_Palette *palette, SDL_Color *colors, int firstcolor, int ncolors) +inline bool SDLC_SetSurfaceAndPaletteColors(SDL_Surface *surface, SDL_Palette *palette, SDL_Color *colors, int firstcolor, int ncolors) { -#ifdef USE_SDL1 +#if defined(USE_SDL1) if (ncolors > (palette->ncolors - firstcolor)) { SDL_SetError("ncolors > (palette->ncolors - firstcolor)"); - return -1; + return false; } if (colors != (palette->colors + firstcolor)) SDL_memcpy(palette->colors + firstcolor, colors, ncolors * sizeof(*colors)); @@ -77,16 +63,22 @@ inline int SDLC_SetSurfaceAndPaletteColors(SDL_Surface *surface, SDL_Palette *pa // When the video surface is 8bit, we need to set the output palette as well. SDL_Surface *videoSurface = SDL_GetVideoSurface(); SDL_SetColors(videoSurface, colors, firstcolor, ncolors); - if (videoSurface == surface) return 0; + if (videoSurface == surface) return true; #endif // In SDL1, the surface always has its own distinct palette, so we need to // update it as well. - return SDL_SetPalette(surface, SDL_LOGPAL, colors, firstcolor, ncolors) - 1; -#else // !USE_SDL1 + return SDL_SetPalette(surface, SDL_LOGPAL, colors, firstcolor, ncolors) == 0; +#elif defined(USE_SDL3) + if (!SDL_SetPaletteColors(palette, colors, firstcolor, ncolors)) return false; + if (SDL_GetSurfacePalette(surface) != palette) { + if (!SDL_SetSurfacePalette(surface, palette)) return false; + } + return true; +#else if (SDL_SetPaletteColors(palette, colors, firstcolor, ncolors) < 0) - return -1; + return false; if (surface->format->palette != palette) return SDL_SetSurfacePalette(surface, palette); - return 0; + return true; #endif } diff --git a/Source/utils/sdl_mutex.h b/Source/utils/sdl_mutex.h index 4284de78b..4bf4fca81 100644 --- a/Source/utils/sdl_mutex.h +++ b/Source/utils/sdl_mutex.h @@ -2,8 +2,13 @@ #include +#ifdef USE_SDL3 +#include +#include +#else #include #include +#endif #include "appfat.h" @@ -51,35 +56,49 @@ public: void lock() noexcept // NOLINT(readability-identifier-naming) { +#ifdef USE_SDL3 + SDL_LockMutex(mutex_); +#else int err = SDL_LockMutex(mutex_); - if (err == -1) - ErrSdl(); + if (err == -1) ErrSdl(); +#endif } #if SDL_VERSION_ATLEAST(2, 0, 0) - bool try_lock() noexcept // NOLINT(readability-identifier-naming) + [[nodiscard]] bool try_lock() noexcept // NOLINT(readability-identifier-naming) { - int err = SDL_TryLockMutex(mutex_); - if (err == -1) - ErrSdl(); - return err == 0; + const bool ok = +#ifdef USE_SDL3 + SDL_TryLockMutex(mutex_); +#else + SDL_TryLockMutex(mutex_) == 0; +#endif + return ok; } #endif void unlock() noexcept // NOLINT(readability-identifier-naming) { +#ifdef USE_SDL3 + SDL_UnlockMutex(mutex_); +#else int err = SDL_UnlockMutex(mutex_); - if (err == -1) - ErrSdl(); + if (err == -1) ErrSdl(); +#endif } - SDL_mutex *get() - { - return mutex_; - } +#ifdef USE_SDL3 + SDL_Mutex *get() { return mutex_; } +#else + SDL_mutex *get() { return mutex_; } +#endif private: +#ifdef USE_SDL3 + SDL_Mutex *mutex_; +#else SDL_mutex *mutex_; +#endif }; #endif diff --git a/test/palette_blending_benchmark.cpp b/test/palette_blending_benchmark.cpp index 0f0f8a521..a570155d7 100644 --- a/test/palette_blending_benchmark.cpp +++ b/test/palette_blending_benchmark.cpp @@ -3,7 +3,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif + #include #include "utils/palette_kd_tree.hpp" diff --git a/test/palette_blending_test.cpp b/test/palette_blending_test.cpp index 09bf3e43d..ac0cae7b9 100644 --- a/test/palette_blending_test.cpp +++ b/test/palette_blending_test.cpp @@ -4,7 +4,12 @@ #include #include +#ifdef USE_SDL3 +#include +#else #include +#endif + #include #include