Browse Source

SDL3: Some more migration

pull/8214/head
Gleb Mazovetskiy 5 months ago
parent
commit
a99cc9b40a
  1. 7
      3rdParty/libsmackerdec/CMakeLists.txt
  2. 93
      Source/DiabloUI/text_input.cpp
  3. 4
      Source/DiabloUI/text_input.hpp
  4. 3
      Source/codec.cpp
  5. 12
      Source/control.cpp
  6. 9
      Source/control.h
  7. 23
      Source/controls/controller.cpp
  8. 4
      Source/controls/controller.h
  9. 23
      Source/controls/controller_motion.cpp
  10. 8
      Source/controls/controller_motion.h
  11. 261
      Source/controls/devices/game_controller.cpp
  12. 10
      Source/controls/devices/game_controller.h
  13. 77
      Source/controls/devices/joystick.cpp
  14. 8
      Source/controls/devices/joystick.h
  15. 27
      Source/controls/devices/kbcontroller.cpp
  16. 7
      Source/controls/devices/kbcontroller.h
  17. 21
      Source/controls/game_controls.cpp
  18. 9
      Source/controls/game_controls.h
  19. 5
      Source/engine/render/dun_render.hpp
  20. 25
      Source/levels/gendung.cpp
  21. 15
      Source/objects.cpp
  22. 7
      Source/panels/console.cpp
  23. 4
      Source/panels/console.hpp
  24. 3
      Source/quests.cpp

7
3rdParty/libsmackerdec/CMakeLists.txt vendored

@ -2,8 +2,8 @@ include(functions/FetchContent_ExcludeFromAll_backport)
include(FetchContent) include(FetchContent)
FetchContent_Declare_ExcludeFromAll(libsmackerdec FetchContent_Declare_ExcludeFromAll(libsmackerdec
URL https://github.com/diasurgical/libsmackerdec/archive/91e732bb6953489077430572f43fc802bf2c75b2.tar.gz URL https://github.com/diasurgical/libsmackerdec/archive/0aaaf8c94a097b009d844db0d44dd7cd0ff81922.tar.gz
URL_HASH MD5=c3b1ecbe702266e149b158178a03e2b3 URL_HASH SHA256=c3a7fbc91531eee8989b1d281415adc0209d84ffc0437c6b0b4f677ae7fd3b41
) )
FetchContent_MakeAvailable_ExcludeFromAll(libsmackerdec) FetchContent_MakeAvailable_ExcludeFromAll(libsmackerdec)
@ -17,6 +17,9 @@ target_include_directories(libsmackerdec PUBLIC ${libsmackerdec_SOURCE_DIR}/incl
if(USE_SDL1) if(USE_SDL1)
target_link_libraries(libsmackerdec PUBLIC ${SDL_LIBRARY}) target_link_libraries(libsmackerdec PUBLIC ${SDL_LIBRARY})
elseif(USE_SDL3)
target_link_libraries(libsmackerdec PUBLIC SDL3::SDL3)
target_compile_definitions(libsmackerdec PUBLIC USE_SDL3)
elseif(TARGET SDL2::SDL2 AND NOT (DEVILUTIONX_STATIC_SDL2 AND TARGET SDL2::SDL2-static)) elseif(TARGET SDL2::SDL2 AND NOT (DEVILUTIONX_STATIC_SDL2 AND TARGET SDL2::SDL2-static))
target_link_libraries(libsmackerdec PUBLIC SDL2::SDL2) target_link_libraries(libsmackerdec PUBLIC SDL2::SDL2)
elseif(TARGET SDL2::SDL2-static) elseif(TARGET SDL2::SDL2-static)

93
Source/DiabloUI/text_input.cpp

@ -4,12 +4,20 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <SDL.h>
#include <function_ref.hpp> #include <function_ref.hpp>
#ifdef USE_SDL3
#include <SDL3/SDL_clipboard.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keyboard.h>
#include <SDL3/SDL_keycode.h>
#else
#include <SDL.h>
#ifdef USE_SDL1 #ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h" #include "utils/sdl2_to_1_2_backports.h"
#endif #endif
#endif
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/parse_int.hpp" #include "utils/parse_int.hpp"
@ -25,44 +33,94 @@ bool HandleInputEvent(const SDL_Event &event, TextInputState &state,
[[maybe_unused]] tl::function_ref<bool(std::string_view)> assignFn) [[maybe_unused]] tl::function_ref<bool(std::string_view)> assignFn)
{ {
const auto modState = SDL_GetModState(); const auto modState = SDL_GetModState();
#ifdef USE_SDL3
const bool isCtrl = (modState & SDL_KMOD_CTRL) != 0;
const bool isAlt = (modState & SDL_KMOD_ALT) != 0;
const bool isShift = (modState & SDL_KMOD_SHIFT) != 0;
#else
const bool isCtrl = (modState & KMOD_CTRL) != 0; const bool isCtrl = (modState & KMOD_CTRL) != 0;
const bool isAlt = (modState & KMOD_ALT) != 0; const bool isAlt = (modState & KMOD_ALT) != 0;
const bool isShift = (modState & KMOD_SHIFT) != 0; const bool isShift = (modState & KMOD_SHIFT) != 0;
#endif
switch (event.type) { switch (event.type) {
case SDL_KEYDOWN: { #ifdef USE_SDL3
switch (event.key.keysym.sym) { case SDL_EVENT_KEY_DOWN:
#else
case SDL_KEYDOWN:
#endif
{
#ifdef USE_SDL3
switch (event.key.key)
#else
switch (event.key.keysym.sym)
#endif
{
#ifndef USE_SDL1 #ifndef USE_SDL1
#ifdef USE_SDL3
case SDLK_A:
#else
case SDLK_a: case SDLK_a:
#endif
if (isCtrl) { if (isCtrl) {
state.setCursorToStart(); state.setCursorToStart();
state.setSelectCursorToEnd(); state.setSelectCursorToEnd();
} }
return true; return true;
#ifdef USE_SDL3
case SDLK_C:
#else
case SDLK_c: case SDLK_c:
#endif
if (isCtrl) { if (isCtrl) {
const std::string selectedText { state.selectedText() }; const std::string selectedText { state.selectedText() };
if (SDL_SetClipboardText(selectedText.c_str()) < 0) { #ifdef USE_SDL3
Log("{}", SDL_GetError()); if (SDL_SetClipboardText(selectedText.c_str()))
#else
if (SDL_SetClipboardText(selectedText.c_str()) < 0)
#endif
{
LogError("Failed to set clipboard text: {}", SDL_GetError());
SDL_ClearError();
} }
} }
return true; return true;
#ifdef USE_SDL3
case SDLK_X:
#else
case SDLK_x: case SDLK_x:
#endif
if (isCtrl) { if (isCtrl) {
const std::string selectedText { state.selectedText() }; const std::string selectedText { state.selectedText() };
if (SDL_SetClipboardText(selectedText.c_str()) < 0) { #ifdef USE_SDL3
Log("{}", SDL_GetError()); if (SDL_SetClipboardText(selectedText.c_str()))
#else
if (SDL_SetClipboardText(selectedText.c_str()) < 0)
#endif
{
LogError("Failed to set clipboard text: {}", SDL_GetError());
SDL_ClearError();
} else { } else {
state.eraseSelection(); state.eraseSelection();
} }
} }
return true; return true;
#ifdef USE_SDL3
case SDLK_V:
#else
case SDLK_v: case SDLK_v:
#endif
if (isCtrl) { if (isCtrl) {
if (SDL_HasClipboardText() == SDL_TRUE) { #if USE_SDL3
if (SDL_HasClipboardText())
#else
if (SDL_HasClipboardText() == SDL_TRUE)
#endif
{
const std::unique_ptr<char, SDLFreeDeleter<char>> clipboard { SDL_GetClipboardText() }; const std::unique_ptr<char, SDLFreeDeleter<char>> clipboard { SDL_GetClipboardText() };
if (clipboard == nullptr || *clipboard == '\0') { if (clipboard == nullptr) {
Log("{}", SDL_GetError()); LogError("Failed to get clipboard text: {}", SDL_GetError());
} else { SDL_ClearError();
} else if (*clipboard != '\0') {
typeFn(clipboard.get()); typeFn(clipboard.get());
} }
} }
@ -100,18 +158,31 @@ bool HandleInputEvent(const SDL_Event &event, TextInputState &state,
#else #else
// Mark events that will also trigger SDL_TEXTINPUT as handled. // Mark events that will also trigger SDL_TEXTINPUT as handled.
return !isCtrl && !isAlt return !isCtrl && !isAlt
#ifdef USE_SDL3
&& event.key.key >= SDLK_SPACE && event.key.key <= SDLK_Z;
#else
&& event.key.keysym.sym >= SDLK_SPACE && event.key.keysym.sym <= SDLK_z; && event.key.keysym.sym >= SDLK_SPACE && event.key.keysym.sym <= SDLK_z;
#endif
#endif #endif
} break; } break;
#ifndef USE_SDL1 #ifndef USE_SDL1
#ifdef USE_SDL3
case SDL_EVENT_TEXT_INPUT:
#else
case SDL_TEXTINPUT: case SDL_TEXTINPUT:
#endif
#ifdef __vita__ #ifdef __vita__
assignFn(event.text.text); assignFn(event.text.text);
#else #else
typeFn(event.text.text); typeFn(event.text.text);
#endif #endif
return true; return true;
#ifdef USE_SDL3
case SDL_EVENT_TEXT_EDITING:
case SDL_EVENT_TEXT_EDITING_CANDIDATES:
#else
case SDL_TEXTEDITING: case SDL_TEXTEDITING:
#endif
return true; return true;
#endif #endif
default: default:

4
Source/DiabloUI/text_input.hpp

@ -6,7 +6,11 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#endif
#include "utils/utf8.hpp" #include "utils/utf8.hpp"

3
Source/codec.cpp

@ -6,6 +6,7 @@
#include "appfat.h" #include "appfat.h"
#include "sha.h" #include "sha.h"
#include "utils/endian_read.hpp" #include "utils/endian_read.hpp"
#include "utils/endian_swap.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
namespace devilution { namespace devilution {
@ -77,7 +78,7 @@ void SetCodecSignature(std::byte *dst, CodecSignature sig)
void ByteSwapBlock(uint32_t *data) void ByteSwapBlock(uint32_t *data)
{ {
for (size_t i = 0; i < BlockSize; ++i) for (size_t i = 0; i < BlockSize; ++i)
data[i] = SDL_SwapLE32(data[i]); data[i] = Swap32LE(data[i]);
} }
void XorBlock(const uint32_t *shaResult, uint32_t *out) void XorBlock(const uint32_t *shaResult, uint32_t *out)

12
Source/control.cpp

@ -13,6 +13,18 @@
#include <optional> #include <optional>
#include <string> #include <string>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keycode.h>
#include <SDL3/SDL_rect.h>
#else
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#endif
#include <fmt/format.h> #include <fmt/format.h>
#include "DiabloUI/text_input.hpp" #include "DiabloUI/text_input.hpp"

9
Source/control.h

@ -11,12 +11,19 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keycode.h>
#include <SDL3/SDL_rect.h>
#else
#include <SDL.h> #include <SDL.h>
#include <expected.hpp>
#ifdef USE_SDL1 #ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h" #include "utils/sdl2_to_1_2_backports.h"
#endif #endif
#endif
#include <expected.hpp>
#include "DiabloUI/text_input.hpp" #include "DiabloUI/text_input.hpp"
#include "DiabloUI/ui_flags.hpp" #include "DiabloUI/ui_flags.hpp"

23
Source/controls/controller.cpp

@ -2,6 +2,12 @@
#include <cmath> #include <cmath>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h>
#endif
#ifndef USE_SDL1 #ifndef USE_SDL1
#include "controls/devices/game_controller.h" #include "controls/devices/game_controller.h"
#endif #endif
@ -91,16 +97,33 @@ bool HandleControllerAddedOrRemovedEvent(const SDL_Event &event)
{ {
#ifndef USE_SDL1 #ifndef USE_SDL1
switch (event.type) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_ADDED:
GameController::Add(event.gdevice.which);
break;
case SDL_EVENT_GAMEPAD_REMOVED:
GameController::Remove(event.gdevice.which);
break;
#else
case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEADDED:
GameController::Add(event.cdevice.which); GameController::Add(event.cdevice.which);
break; break;
case SDL_CONTROLLERDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMOVED:
GameController::Remove(event.cdevice.which); GameController::Remove(event.cdevice.which);
break; break;
#endif
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_ADDED:
#else
case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEADDED:
#endif
Joystick::Add(event.jdevice.which); Joystick::Add(event.jdevice.which);
break; break;
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_REMOVED:
#else
case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEREMOVED:
#endif
Joystick::Remove(event.jdevice.which); Joystick::Remove(event.jdevice.which);
break; break;
default: default:

4
Source/controls/controller.h

@ -1,6 +1,10 @@
#pragma once #pragma once
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#endif
#include "controller_buttons.h" #include "controller_buttons.h"
#include "utils/static_vector.hpp" #include "utils/static_vector.hpp"

23
Source/controls/controller_motion.cpp

@ -2,6 +2,12 @@
#include <cmath> #include <cmath>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h>
#endif
#include "control.h" #include "control.h"
#include "controls/control_mode.hpp" #include "controls/control_mode.hpp"
#include "controls/controller.h" #include "controls/controller.h"
@ -144,6 +150,15 @@ void ScaleJoysticks()
bool IsControllerMotion(const SDL_Event &event) bool IsControllerMotion(const SDL_Event &event)
{ {
#ifndef USE_SDL1 #ifndef USE_SDL1
#ifdef USE_SDL3
if (event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
return IsAnyOf(event.gaxis.axis,
SDL_GAMEPAD_AXIS_LEFTX,
SDL_GAMEPAD_AXIS_LEFTY,
SDL_GAMEPAD_AXIS_RIGHTX,
SDL_GAMEPAD_AXIS_RIGHTY);
}
#else
if (event.type == SDL_CONTROLLERAXISMOTION) { if (event.type == SDL_CONTROLLERAXISMOTION) {
return IsAnyOf(event.caxis.axis, return IsAnyOf(event.caxis.axis,
SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTX,
@ -152,9 +167,15 @@ bool IsControllerMotion(const SDL_Event &event)
SDL_CONTROLLER_AXIS_RIGHTY); SDL_CONTROLLER_AXIS_RIGHTY);
} }
#endif #endif
#endif
#if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY) #if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY)
if (event.type == SDL_JOYAXISMOTION) { #ifdef USE_SDL3
if (event.type == SDL_EVENT_JOYSTICK_AXIS_MOTION)
#else
if (event.type == SDL_JOYAXISMOTION)
#endif
{
switch (event.jaxis.axis) { switch (event.jaxis.axis) {
#ifdef JOY_AXIS_LEFTX #ifdef JOY_AXIS_LEFTX
case JOY_AXIS_LEFTX: case JOY_AXIS_LEFTX:

8
Source/controls/controller_motion.h

@ -2,10 +2,14 @@
// Processes and stores mouse and joystick motion. // Processes and stores mouse and joystick motion.
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#endif
#include "./axis_direction.h" #include "controls/axis_direction.h"
#include "./controller.h" #include "controls/controller.h"
namespace devilution { namespace devilution {

261
Source/controls/devices/game_controller.cpp

@ -1,11 +1,21 @@
#include "controls/devices/game_controller.h" #include "controls/devices/game_controller.h"
#include <cstddef> #include <cstddef>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_gamepad.h>
#else
#include <SDL.h>
#include "utils/sdl2_backports.h"
#endif
#include "controls/controller_motion.h" #include "controls/controller_motion.h"
#include "controls/devices/joystick.h" #include "controls/devices/joystick.h"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/sdl2_backports.h"
#include "utils/sdl_ptrs.h" #include "utils/sdl_ptrs.h"
#include "utils/stubs.h" #include "utils/stubs.h"
@ -22,60 +32,142 @@ void GameController::UnlockTriggerState()
ControllerButton GameController::ToControllerButton(const SDL_Event &event) ControllerButton GameController::ToControllerButton(const SDL_Event &event)
{ {
switch (event.type) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
#else
case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERAXISMOTION:
switch (event.caxis.axis) { #endif
{
const auto &axis =
#ifdef USE_SDL3
event.gaxis;
#else
event.caxis;
#endif
switch (axis.axis) {
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
#else
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
if (event.caxis.value < 8192 && trigger_left_is_down_) { // 25% pressed #endif
if (axis.value < 8192 && trigger_left_is_down_) { // 25% pressed
trigger_left_is_down_ = false; trigger_left_is_down_ = false;
trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT; trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;
} }
if (event.caxis.value > 16384 && !trigger_left_is_down_) { // 50% pressed if (axis.value > 16384 && !trigger_left_is_down_) { // 50% pressed
trigger_left_is_down_ = true; trigger_left_is_down_ = true;
trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT; trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;
} }
return trigger_left_state_; return trigger_left_state_;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
#else
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
if (event.caxis.value < 8192 && trigger_right_is_down_) { // 25% pressed #endif
if (axis.value < 8192 && trigger_right_is_down_) { // 25% pressed
trigger_right_is_down_ = false; trigger_right_is_down_ = false;
trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT; trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;
} }
if (event.caxis.value > 16384 && !trigger_right_is_down_) { // 50% pressed if (axis.value > 16384 && !trigger_right_is_down_) { // 50% pressed
trigger_right_is_down_ = true; trigger_right_is_down_ = true;
trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT; trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;
} }
return trigger_right_state_; return trigger_right_state_;
} }
break; } break;
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
switch (event.gbutton.button)
#else
case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERBUTTONUP:
switch (event.cbutton.button) { switch (event.cbutton.button)
#endif
{
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_SOUTH:
#else
case SDL_CONTROLLER_BUTTON_A: case SDL_CONTROLLER_BUTTON_A:
#endif
return ControllerButton_BUTTON_A; return ControllerButton_BUTTON_A;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_EAST:
#else
case SDL_CONTROLLER_BUTTON_B: case SDL_CONTROLLER_BUTTON_B:
#endif
return ControllerButton_BUTTON_B; return ControllerButton_BUTTON_B;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_WEST:
#else
case SDL_CONTROLLER_BUTTON_X: case SDL_CONTROLLER_BUTTON_X:
#endif
return ControllerButton_BUTTON_X; return ControllerButton_BUTTON_X;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_NORTH:
#else
case SDL_CONTROLLER_BUTTON_Y: case SDL_CONTROLLER_BUTTON_Y:
#endif
return ControllerButton_BUTTON_Y; return ControllerButton_BUTTON_Y;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
#else
case SDL_CONTROLLER_BUTTON_LEFTSTICK: case SDL_CONTROLLER_BUTTON_LEFTSTICK:
#endif
return ControllerButton_BUTTON_LEFTSTICK; return ControllerButton_BUTTON_LEFTSTICK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
#else
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
#endif
return ControllerButton_BUTTON_RIGHTSTICK; return ControllerButton_BUTTON_RIGHTSTICK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
#else
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
#endif
return ControllerButton_BUTTON_LEFTSHOULDER; return ControllerButton_BUTTON_LEFTSHOULDER;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
#else
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
#endif
return ControllerButton_BUTTON_RIGHTSHOULDER; return ControllerButton_BUTTON_RIGHTSHOULDER;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_START:
#else
case SDL_CONTROLLER_BUTTON_START: case SDL_CONTROLLER_BUTTON_START:
#endif
return ControllerButton_BUTTON_START; return ControllerButton_BUTTON_START;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_BACK:
#else
case SDL_CONTROLLER_BUTTON_BACK: case SDL_CONTROLLER_BUTTON_BACK:
#endif
return ControllerButton_BUTTON_BACK; return ControllerButton_BUTTON_BACK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_UP:
#else
case SDL_CONTROLLER_BUTTON_DPAD_UP: case SDL_CONTROLLER_BUTTON_DPAD_UP:
#endif
return ControllerButton_BUTTON_DPAD_UP; return ControllerButton_BUTTON_DPAD_UP;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
#else
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
#endif
return ControllerButton_BUTTON_DPAD_DOWN; return ControllerButton_BUTTON_DPAD_DOWN;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
#else
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
#endif
return ControllerButton_BUTTON_DPAD_LEFT; return ControllerButton_BUTTON_DPAD_LEFT;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
#else
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
#endif
return ControllerButton_BUTTON_DPAD_RIGHT; return ControllerButton_BUTTON_DPAD_RIGHT;
default: default:
break; break;
@ -86,41 +178,105 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
return ControllerButton_NONE; return ControllerButton_NONE;
} }
#ifdef USE_SDL3
SDL_GamepadButton GameController::ToSdlGameControllerButton(ControllerButton button)
#else
SDL_GameControllerButton GameController::ToSdlGameControllerButton(ControllerButton button) SDL_GameControllerButton GameController::ToSdlGameControllerButton(ControllerButton button)
#endif
{ {
if (button == ControllerButton_AXIS_TRIGGERLEFT || button == ControllerButton_AXIS_TRIGGERRIGHT) if (button == ControllerButton_AXIS_TRIGGERLEFT || button == ControllerButton_AXIS_TRIGGERRIGHT)
UNIMPLEMENTED(); UNIMPLEMENTED();
switch (button) { switch (button) {
case ControllerButton_BUTTON_A: case ControllerButton_BUTTON_A:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_SOUTH;
#else
return SDL_CONTROLLER_BUTTON_A; return SDL_CONTROLLER_BUTTON_A;
#endif
case ControllerButton_BUTTON_B: case ControllerButton_BUTTON_B:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_EAST;
#else
return SDL_CONTROLLER_BUTTON_B; return SDL_CONTROLLER_BUTTON_B;
#endif
case ControllerButton_BUTTON_X: case ControllerButton_BUTTON_X:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_WEST;
#else
return SDL_CONTROLLER_BUTTON_X; return SDL_CONTROLLER_BUTTON_X;
#endif
case ControllerButton_BUTTON_Y: case ControllerButton_BUTTON_Y:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_NORTH;
#else
return SDL_CONTROLLER_BUTTON_Y; return SDL_CONTROLLER_BUTTON_Y;
#endif
case ControllerButton_BUTTON_BACK: case ControllerButton_BUTTON_BACK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_BACK;
#else
return SDL_CONTROLLER_BUTTON_BACK; return SDL_CONTROLLER_BUTTON_BACK;
#endif
case ControllerButton_BUTTON_START: case ControllerButton_BUTTON_START:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_START;
#else
return SDL_CONTROLLER_BUTTON_START; return SDL_CONTROLLER_BUTTON_START;
#endif
case ControllerButton_BUTTON_LEFTSTICK: case ControllerButton_BUTTON_LEFTSTICK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_LEFT_STICK;
#else
return SDL_CONTROLLER_BUTTON_LEFTSTICK; return SDL_CONTROLLER_BUTTON_LEFTSTICK;
#endif
case ControllerButton_BUTTON_RIGHTSTICK: case ControllerButton_BUTTON_RIGHTSTICK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_RIGHT_STICK;
#else
return SDL_CONTROLLER_BUTTON_RIGHTSTICK; return SDL_CONTROLLER_BUTTON_RIGHTSTICK;
#endif
case ControllerButton_BUTTON_LEFTSHOULDER: case ControllerButton_BUTTON_LEFTSHOULDER:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_LEFT_SHOULDER;
#else
return SDL_CONTROLLER_BUTTON_LEFTSHOULDER; return SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
#endif
case ControllerButton_BUTTON_RIGHTSHOULDER: case ControllerButton_BUTTON_RIGHTSHOULDER:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER;
#else
return SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; return SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
#endif
case ControllerButton_BUTTON_DPAD_UP: case ControllerButton_BUTTON_DPAD_UP:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_UP;
#else
return SDL_CONTROLLER_BUTTON_DPAD_UP; return SDL_CONTROLLER_BUTTON_DPAD_UP;
#endif
case ControllerButton_BUTTON_DPAD_DOWN: case ControllerButton_BUTTON_DPAD_DOWN:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_DOWN;
#else
return SDL_CONTROLLER_BUTTON_DPAD_DOWN; return SDL_CONTROLLER_BUTTON_DPAD_DOWN;
#endif
case ControllerButton_BUTTON_DPAD_LEFT: case ControllerButton_BUTTON_DPAD_LEFT:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_LEFT;
#else
return SDL_CONTROLLER_BUTTON_DPAD_LEFT; return SDL_CONTROLLER_BUTTON_DPAD_LEFT;
#endif
case ControllerButton_BUTTON_DPAD_RIGHT: case ControllerButton_BUTTON_DPAD_RIGHT:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
#else
return SDL_CONTROLLER_BUTTON_DPAD_RIGHT; return SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
#endif
default: default:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_INVALID;
#else
return SDL_CONTROLLER_BUTTON_INVALID; return SDL_CONTROLLER_BUTTON_INVALID;
#endif
} }
} }
@ -130,29 +286,56 @@ bool GameController::IsPressed(ControllerButton button) const
return trigger_left_is_down_; return trigger_left_is_down_;
if (button == ControllerButton_AXIS_TRIGGERRIGHT) if (button == ControllerButton_AXIS_TRIGGERRIGHT)
return trigger_right_is_down_; return trigger_right_is_down_;
#ifdef USE_SDL3
const SDL_GamepadButton gcButton = ToSdlGameControllerButton(button);
return SDL_GamepadHasButton(sdl_game_controller_, gcButton) && SDL_GetGamepadButton(sdl_game_controller_, gcButton);
#else
const SDL_GameControllerButton gcButton = ToSdlGameControllerButton(button); const SDL_GameControllerButton gcButton = ToSdlGameControllerButton(button);
return SDL_GameControllerHasButton(sdl_game_controller_, gcButton) && SDL_GameControllerGetButton(sdl_game_controller_, gcButton) != 0; return SDL_GameControllerHasButton(sdl_game_controller_, gcButton) && SDL_GameControllerGetButton(sdl_game_controller_, gcButton) != 0;
#endif
} }
bool GameController::ProcessAxisMotion(const SDL_Event &event) bool GameController::ProcessAxisMotion(const SDL_Event &event)
{ {
if (event.type != SDL_CONTROLLERAXISMOTION) #ifdef USE_SDL3
return false; if (event.type != SDL_EVENT_GAMEPAD_AXIS_MOTION) return false;
switch (event.caxis.axis) { const auto &axis = event.gaxis;
#else
if (event.type != SDL_CONTROLLERAXISMOTION) return false;
const auto &axis = event.caxis;
#endif
switch (axis.axis) {
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFTX:
#else
case SDL_CONTROLLER_AXIS_LEFTX: case SDL_CONTROLLER_AXIS_LEFTX:
leftStickXUnscaled = static_cast<float>(event.caxis.value); #endif
leftStickXUnscaled = static_cast<float>(axis.value);
leftStickNeedsScaling = true; leftStickNeedsScaling = true;
break; break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFTY:
#else
case SDL_CONTROLLER_AXIS_LEFTY: case SDL_CONTROLLER_AXIS_LEFTY:
leftStickYUnscaled = static_cast<float>(-event.caxis.value); #endif
leftStickYUnscaled = static_cast<float>(-axis.value);
leftStickNeedsScaling = true; leftStickNeedsScaling = true;
break; break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHTX:
#else
case SDL_CONTROLLER_AXIS_RIGHTX: case SDL_CONTROLLER_AXIS_RIGHTX:
rightStickXUnscaled = static_cast<float>(event.caxis.value); #endif
rightStickXUnscaled = static_cast<float>(axis.value);
rightStickNeedsScaling = true; rightStickNeedsScaling = true;
break; break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHTY:
#else
case SDL_CONTROLLER_AXIS_RIGHTY: case SDL_CONTROLLER_AXIS_RIGHTY:
rightStickYUnscaled = static_cast<float>(-event.caxis.value); #endif
rightStickYUnscaled = static_cast<float>(-axis.value);
rightStickNeedsScaling = true; rightStickNeedsScaling = true;
break; break;
default: default:
@ -161,22 +344,37 @@ bool GameController::ProcessAxisMotion(const SDL_Event &event)
return true; return true;
} }
#ifdef USE_SDL3
void GameController::Add(SDL_JoystickID joystickId)
#else
void GameController::Add(int joystickIndex) void GameController::Add(int joystickIndex)
#endif
{ {
Log("Opening game controller for joystick at index {}", joystickIndex);
GameController result; GameController result;
#ifdef USE_SDL3
Log("Opening game controller for joystick with ID {}", joystickId);
result.sdl_game_controller_ = SDL_OpenGamepad(joystickId);
#else
Log("Opening game controller for joystick at index {}", joystickIndex);
result.sdl_game_controller_ = SDL_GameControllerOpen(joystickIndex); result.sdl_game_controller_ = SDL_GameControllerOpen(joystickIndex);
#endif
if (result.sdl_game_controller_ == nullptr) { if (result.sdl_game_controller_ == nullptr) {
Log("{}", SDL_GetError()); Log("{}", SDL_GetError());
SDL_ClearError(); SDL_ClearError();
return; return;
} }
SDL_Joystick *const sdlJoystick = SDL_GameControllerGetJoystick(result.sdl_game_controller_);
result.instance_id_ = SDL_JoystickInstanceID(sdlJoystick);
controllers_.push_back(result); controllers_.push_back(result);
#ifdef USE_SDL3
result.instance_id_ = joystickId;
const SDLUniquePtr<char> mapping { SDL_GetGamepadMappingForID(joystickId) };
#else
SDL_Joystick *const sdlJoystick = SDL_GameControllerGetJoystick(result.sdl_game_controller_);
result.instance_id_ = SDL_JoystickInstanceID(sdlJoystick);
const SDL_JoystickGUID guid = SDL_JoystickGetGUID(sdlJoystick); const SDL_JoystickGUID guid = SDL_JoystickGetGUID(sdlJoystick);
const SDLUniquePtr<char> mapping { SDL_GameControllerMappingForGUID(guid) }; const SDLUniquePtr<char> mapping { SDL_GameControllerMappingForGUID(guid) };
#endif
if (mapping) { if (mapping) {
Log("Opened game controller with mapping:\n{}", mapping.get()); Log("Opened game controller with mapping:\n{}", mapping.get());
} }
@ -207,11 +405,19 @@ GameController *GameController::Get(SDL_JoystickID instanceId)
GameController *GameController::Get(const SDL_Event &event) GameController *GameController::Get(const SDL_Event &event)
{ {
switch (event.type) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
return Get(event.gaxis.which);
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
return Get(event.gbutton.which);
#else
case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERAXISMOTION:
return Get(event.caxis.which); return Get(event.caxis.which);
case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERBUTTONUP:
return Get(event.cbutton.which); return Get(event.cbutton.which);
#endif
default: default:
return nullptr; return nullptr;
} }
@ -239,7 +445,24 @@ GamepadLayout GameController::getLayout(const SDL_Event &event)
#if defined(DEVILUTIONX_GAMEPAD_TYPE) #if defined(DEVILUTIONX_GAMEPAD_TYPE)
return GamepadLayout:: return GamepadLayout::
DEVILUTIONX_GAMEPAD_TYPE; DEVILUTIONX_GAMEPAD_TYPE;
#else // !defined(DEVILUTIONX_GAMEPAD_TYPE) #elif USE_SDL3
switch (SDL_GetGamepadTypeForID(event.gdevice.which)) {
case SDL_GAMEPAD_TYPE_XBOX360:
case SDL_GAMEPAD_TYPE_XBOXONE:
return GamepadLayout::Xbox;
case SDL_GAMEPAD_TYPE_PS3:
case SDL_GAMEPAD_TYPE_PS4:
case SDL_GAMEPAD_TYPE_PS5:
return GamepadLayout::PlayStation;
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
return GamepadLayout::Nintendo;
default:
return GamepadLayout::Generic;
}
#else
#if SDL_VERSION_ATLEAST(2, 0, 12) #if SDL_VERSION_ATLEAST(2, 0, 12)
const int index = event.cdevice.which; const int index = event.cdevice.which;
const SDL_GameControllerType gamepadType = SDL_GameControllerTypeForIndex(index); const SDL_GameControllerType gamepadType = SDL_GameControllerTypeForIndex(index);

10
Source/controls/devices/game_controller.h

@ -13,7 +13,11 @@ class GameController {
static std::vector<GameController> controllers_; static std::vector<GameController> controllers_;
public: public:
#ifdef USE_SDL3
static void Add(SDL_JoystickID joystickId);
#else
static void Add(int joystickIndex); static void Add(int joystickIndex);
#endif
static void Remove(SDL_JoystickID instanceId); static void Remove(SDL_JoystickID instanceId);
static GameController *Get(SDL_JoystickID instanceId); static GameController *Get(SDL_JoystickID instanceId);
static GameController *Get(const SDL_Event &event); static GameController *Get(const SDL_Event &event);
@ -27,7 +31,13 @@ public:
bool IsPressed(ControllerButton button) const; bool IsPressed(ControllerButton button) const;
static bool ProcessAxisMotion(const SDL_Event &event); static bool ProcessAxisMotion(const SDL_Event &event);
#ifdef USE_SDL3
static SDL_GamepadButton ToSdlGameControllerButton(ControllerButton button);
#else
static SDL_GameControllerButton ToSdlGameControllerButton(ControllerButton button); static SDL_GameControllerButton ToSdlGameControllerButton(ControllerButton button);
#endif
static GamepadLayout getLayout(const SDL_Event &event); static GamepadLayout getLayout(const SDL_Event &event);
private: private:

77
Source/controls/devices/joystick.cpp

@ -2,6 +2,18 @@
#include <cstddef> #include <cstddef>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_joystick.h>
#else
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#endif
#include "controls/controller_motion.h" #include "controls/controller_motion.h"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/stubs.h" #include "utils/stubs.h"
@ -13,9 +25,19 @@ std::vector<Joystick> Joystick::joysticks_;
StaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const SDL_Event &event) StaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const SDL_Event &event)
{ {
switch (event.type) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
#else
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: { case SDL_JOYBUTTONUP:
#endif
{
#ifdef USE_SDL3
const bool up = !event.jbutton.down;
#else
const bool up = (event.jbutton.state == SDL_RELEASED); const bool up = (event.jbutton.state == SDL_RELEASED);
#endif
#if defined(JOY_BUTTON_A) || defined(JOY_BUTTON_B) || defined(JOY_BUTTON_X) || defined(JOY_BUTTON_Y) \ #if defined(JOY_BUTTON_A) || defined(JOY_BUTTON_B) || defined(JOY_BUTTON_X) || defined(JOY_BUTTON_Y) \
|| defined(JOY_BUTTON_LEFTSTICK) || defined(JOY_BUTTON_RIGHTSTICK) || defined(JOY_BUTTON_LEFTSHOULDER) || defined(JOY_BUTTON_RIGHTSHOULDER) \ || defined(JOY_BUTTON_LEFTSTICK) || defined(JOY_BUTTON_RIGHTSTICK) || defined(JOY_BUTTON_LEFTSHOULDER) || defined(JOY_BUTTON_RIGHTSHOULDER) \
|| defined(JOY_BUTTON_TRIGGERLEFT) || defined(JOY_BUTTON_TRIGGERRIGHT) || defined(JOY_BUTTON_START) || defined(JOY_BUTTON_BACK) \ || defined(JOY_BUTTON_TRIGGERLEFT) || defined(JOY_BUTTON_TRIGGERRIGHT) || defined(JOY_BUTTON_START) || defined(JOY_BUTTON_BACK) \
@ -92,15 +114,25 @@ StaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const
return { ControllerButtonEvent { ControllerButton_IGNORE, up } }; return { ControllerButtonEvent { ControllerButton_IGNORE, up } };
#endif #endif
} }
case SDL_JOYHATMOTION: { #ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_HAT_MOTION:
#else
case SDL_JOYHATMOTION:
#endif
{
Joystick *joystick = Get(event); Joystick *joystick = Get(event);
if (joystick == nullptr) if (joystick == nullptr)
return { ControllerButtonEvent { ControllerButton_IGNORE, false } }; return { ControllerButtonEvent { ControllerButton_IGNORE, false } };
joystick->UpdateHatState(event.jhat); joystick->UpdateHatState(event.jhat);
return joystick->GetHatEvents(); return joystick->GetHatEvents();
} }
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
case SDL_EVENT_JOYSTICK_BALL_MOTION:
#else
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION: case SDL_JOYBALLMOTION:
#endif
// ProcessAxisMotion() requires a ControllerButtonEvent parameter // ProcessAxisMotion() requires a ControllerButtonEvent parameter
// so provide one here using ControllerButton_NONE // so provide one here using ControllerButton_NONE
return { ControllerButtonEvent { ControllerButton_NONE, false } }; return { ControllerButtonEvent { ControllerButton_NONE, false } };
@ -331,6 +363,27 @@ bool Joystick::ProcessAxisMotion(const SDL_Event &event)
#endif #endif
} }
#ifdef USE_SDL3
void Joystick::Add(SDL_JoystickID id)
{
Joystick result;
const char *name = SDL_GetJoystickNameForID(id);
if (name == nullptr) {
LogWarn("Error getting name for joystick {}", id, SDL_GetError());
SDL_ClearError();
} else {
Log("Adding joystick {}: {}", id, name);
}
result.sdl_joystick_ = SDL_OpenJoystick(id);
if (result.sdl_joystick_ == nullptr) {
LogError("{}", SDL_GetError());
SDL_ClearError();
return;
}
result.instance_id_ = id;
joysticks_.push_back(result);
}
#else
void Joystick::Add(int deviceIndex) void Joystick::Add(int deviceIndex)
{ {
if (SDL_NumJoysticks() <= deviceIndex) if (SDL_NumJoysticks() <= deviceIndex)
@ -340,7 +393,7 @@ void Joystick::Add(int deviceIndex)
SDL_JoystickNameForIndex(deviceIndex)); SDL_JoystickNameForIndex(deviceIndex));
result.sdl_joystick_ = SDL_JoystickOpen(deviceIndex); result.sdl_joystick_ = SDL_JoystickOpen(deviceIndex);
if (result.sdl_joystick_ == nullptr) { if (result.sdl_joystick_ == nullptr) {
Log("{}", SDL_GetError()); LogError("{}", SDL_GetError());
SDL_ClearError(); SDL_ClearError();
return; return;
} }
@ -349,6 +402,7 @@ void Joystick::Add(int deviceIndex)
#endif #endif
joysticks_.push_back(result); joysticks_.push_back(result);
} }
#endif
void Joystick::Remove(SDL_JoystickID instanceId) void Joystick::Remove(SDL_JoystickID instanceId)
{ {
@ -383,14 +437,31 @@ Joystick *Joystick::Get(const SDL_Event &event)
{ {
switch (event.type) { switch (event.type) {
#ifndef USE_SDL1 #ifndef USE_SDL1
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
#else
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
#endif
return Get(event.jaxis.which); return Get(event.jaxis.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BALL_MOTION:
#else
case SDL_JOYBALLMOTION: case SDL_JOYBALLMOTION:
#endif
return Get(event.jball.which); return Get(event.jball.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_HAT_MOTION:
#else
case SDL_JOYHATMOTION: case SDL_JOYHATMOTION:
#endif
return Get(event.jhat.which); return Get(event.jhat.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
#else
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: case SDL_JOYBUTTONUP:
#endif
return Get(event.jbutton.which); return Get(event.jbutton.which);
default: default:
return nullptr; return nullptr;

8
Source/controls/devices/joystick.h

@ -4,11 +4,15 @@
#include <array> #include <array>
#include <vector> #include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#ifdef USE_SDL1 #ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h" #include "utils/sdl2_to_1_2_backports.h"
#endif #endif
#endif
#include "controls/controller.h" #include "controls/controller.h"
#include "controls/controller_buttons.h" #include "controls/controller_buttons.h"
@ -20,7 +24,11 @@ class Joystick {
static std::vector<Joystick> joysticks_; static std::vector<Joystick> joysticks_;
public: public:
#ifdef USE_SDL3
static void Add(SDL_JoystickID deviceIndex);
#else
static void Add(int deviceIndex); static void Add(int deviceIndex);
#endif
static void Remove(SDL_JoystickID instanceId); static void Remove(SDL_JoystickID instanceId);
static Joystick *Get(SDL_JoystickID instanceId); static Joystick *Get(SDL_JoystickID instanceId);
static Joystick *Get(const SDL_Event &event); static Joystick *Get(const SDL_Event &event);

27
Source/controls/devices/kbcontroller.cpp

@ -1,6 +1,16 @@
#include "controls/devices/kbcontroller.h" #include "controls/devices/kbcontroller.h"
#if HAS_KBCTRL == 1 #if HAS_KBCTRL == 1
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keyboard.h>
#else
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#endif
#include "controls/controller_motion.h" #include "controls/controller_motion.h"
#include "utils/sdl_compat.h" #include "utils/sdl_compat.h"
@ -11,9 +21,16 @@ namespace devilution {
ControllerButton KbCtrlToControllerButton(const SDL_Event &event) ControllerButton KbCtrlToControllerButton(const SDL_Event &event)
{ {
switch (event.type) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_DOWN:
switch (event.key.key)
#else
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_KEYUP: case SDL_KEYUP:
switch (event.key.keysym.sym) { switch (event.key.keysym.sym)
#endif
{
#ifdef KBCTRL_IGNORE_1 #ifdef KBCTRL_IGNORE_1
case KBCTRL_IGNORE_1: case KBCTRL_IGNORE_1:
return ControllerButton_IGNORE; return ControllerButton_IGNORE;
@ -167,10 +184,12 @@ bool IsKbCtrlButtonPressed(ControllerButton button)
SDL_Keycode key_code = ControllerButtonToKbCtrlKeyCode(button); SDL_Keycode key_code = ControllerButtonToKbCtrlKeyCode(button);
if (key_code == SDLK_UNKNOWN) if (key_code == SDLK_UNKNOWN)
return false; return false;
#ifndef USE_SDL1 #ifdef USE_SDL3
return SDL_GetKeyboardState(NULL)[SDL_GetScancodeFromKey(key_code)]; return SDL_GetKeyboardState(nullptr)[SDL_GetScancodeFromKey(key_code, nullptr)];
#elif !defined(USE_SDL1)
return SDL_GetKeyboardState(nullptr)[SDL_GetScancodeFromKey(key_code)];
#else #else
return SDL_GetKeyState(NULL)[key_code]; return SDL_GetKeyState(nullptr)[key_code];
#endif #endif
} }

7
Source/controls/devices/kbcontroller.h

@ -6,12 +6,17 @@
#endif #endif
#if HAS_KBCTRL == 1 #if HAS_KBCTRL == 1
#include "controls/controller_buttons.h" #ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#ifdef USE_SDL1 #ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h" #include "utils/sdl2_to_1_2_backports.h"
#endif #endif
#endif
#include "controls/controller_buttons.h"
namespace devilution { namespace devilution {

21
Source/controls/game_controls.cpp

@ -2,6 +2,12 @@
#include <cstdint> #include <cstdint>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h>
#endif
#include "controls/control_mode.hpp" #include "controls/control_mode.hpp"
#include "controls/controller_motion.h" #include "controls/controller_motion.h"
#ifndef USE_SDL1 #ifndef USE_SDL1
@ -92,7 +98,12 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, Game
#ifndef USE_SDL1 #ifndef USE_SDL1
if (ControlMode == ControlTypes::VirtualGamepad) { if (ControlMode == ControlTypes::VirtualGamepad) {
if (event.type == SDL_FINGERDOWN) { switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_FINGER_DOWN:
#else
case SDL_FINGERDOWN:
#endif
if (VirtualGamepadState.menuPanel.charButton.isHeld && VirtualGamepadState.menuPanel.charButton.didStateChange) { if (VirtualGamepadState.menuPanel.charButton.isHeld && VirtualGamepadState.menuPanel.charButton.didStateChange) {
*action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO); *action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO);
return true; return true;
@ -161,13 +172,19 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, Game
*action = GameAction(GameActionType_USE_MANA_POTION); *action = GameAction(GameActionType_USE_MANA_POTION);
return true; return true;
} }
} else if (event.type == SDL_FINGERUP) { break;
#ifdef USE_SDL3
case SDL_EVENT_FINGER_UP:
#else
case SDL_FINGERUP:
#endif
if ((!VirtualGamepadState.primaryActionButton.isHeld && ControllerActionHeld == GameActionType_PRIMARY_ACTION) if ((!VirtualGamepadState.primaryActionButton.isHeld && ControllerActionHeld == GameActionType_PRIMARY_ACTION)
|| (!VirtualGamepadState.secondaryActionButton.isHeld && ControllerActionHeld == GameActionType_SECONDARY_ACTION) || (!VirtualGamepadState.secondaryActionButton.isHeld && ControllerActionHeld == GameActionType_SECONDARY_ACTION)
|| (!VirtualGamepadState.spellActionButton.isHeld && ControllerActionHeld == GameActionType_CAST_SPELL)) { || (!VirtualGamepadState.spellActionButton.isHeld && ControllerActionHeld == GameActionType_CAST_SPELL)) {
ControllerActionHeld = GameActionType_NONE; ControllerActionHeld = GameActionType_NONE;
LastPlayerAction = PlayerActionType::None; LastPlayerAction = PlayerActionType::None;
} }
break;
} }
} }
#endif #endif

9
Source/controls/game_controls.h

@ -1,9 +1,14 @@
#pragma once #pragma once
#include <SDL.h>
#include <cstdint> #include <cstdint>
#include "./axis_direction.h" #ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h>
#endif
#include "controls/axis_direction.h"
#include "controls/controller.h" #include "controls/controller.h"
namespace devilution { namespace devilution {

5
Source/engine/render/dun_render.hpp

@ -8,13 +8,12 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <SDL_endian.h>
#include "engine/point.hpp" #include "engine/point.hpp"
#include "engine/render/light_render.hpp" #include "engine/render/light_render.hpp"
#include "engine/surface.hpp" #include "engine/surface.hpp"
#include "levels/dun_tile.hpp" #include "levels/dun_tile.hpp"
#include "utils/attributes.h" #include "utils/attributes.h"
#include "utils/endian_swap.hpp"
// #define DUN_RENDER_STATS // #define DUN_RENDER_STATS
#ifdef DUN_RENDER_STATS #ifdef DUN_RENDER_STATS
@ -124,7 +123,7 @@ void RenderTileFrame(const Surface &out, const Lightmap &lightmap, const Point &
DVL_ALWAYS_INLINE const uint8_t *GetDunFrame(const std::byte *dungeonCelData, uint32_t frame) DVL_ALWAYS_INLINE const uint8_t *GetDunFrame(const std::byte *dungeonCelData, uint32_t frame)
{ {
const auto *frameTable = reinterpret_cast<const uint32_t *>(dungeonCelData); const auto *frameTable = reinterpret_cast<const uint32_t *>(dungeonCelData);
return reinterpret_cast<const uint8_t *>(&dungeonCelData[SDL_SwapLE32(frameTable[frame])]); return reinterpret_cast<const uint8_t *>(&dungeonCelData[Swap32LE(frameTable[frame])]);
} }
/** /**

25
Source/levels/gendung.cpp

@ -29,6 +29,7 @@
#include "objects.h" #include "objects.h"
#include "utils/algorithm/container.hpp" #include "utils/algorithm/container.hpp"
#include "utils/bitset2d.hpp" #include "utils/bitset2d.hpp"
#include "utils/endian_swap.hpp"
#include "utils/is_of.hpp" #include "utils/is_of.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/status_macros.hpp" #include "utils/status_macros.hpp"
@ -526,7 +527,7 @@ void SetDungeonMicros(std::unique_ptr<std::byte[]> &dungeonCels, uint_fast8_t &m
for (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) { for (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) {
uint16_t *pieces = &levelPieces[blocks * levelPieceId]; uint16_t *pieces = &levelPieces[blocks * levelPieceId];
for (uint32_t block = 0; block < blocks; block++) { for (uint32_t block = 0; block < blocks; block++) {
const LevelCelBlock levelCelBlock { SDL_SwapLE16(pieces[blocks - 2 + (block & 1) - (block & 0xE)]) }; const LevelCelBlock levelCelBlock { Swap16LE(pieces[blocks - 2 + (block & 1) - (block & 0xE)]) };
DPieceMicros[levelPieceId].mt[block] = levelCelBlock; DPieceMicros[levelPieceId].mt[block] = levelCelBlock;
if (levelCelBlock.hasValue()) { if (levelCelBlock.hasValue()) {
if (const auto it = frameToTypeMap.find(levelCelBlock.frame()); it == frameToTypeMap.end()) { if (const auto it = frameToTypeMap.find(levelCelBlock.frame()); it == frameToTypeMap.end()) {
@ -607,7 +608,7 @@ void LoadTransparency(const uint16_t *dunData)
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
dTransVal[16 + i][16 + j] = static_cast<int8_t>(SDL_SwapLE16(*transparentLayer)); dTransVal[16 + i][16 + j] = static_cast<int8_t>(Swap16LE(*transparentLayer));
transparentLayer++; transparentLayer++;
} }
} }
@ -694,7 +695,7 @@ void PlaceDunTiles(const uint16_t *dunData, Point position, int floorId)
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * size.width + i])); auto tileId = static_cast<uint8_t>(Swap16LE(tileLayer[j * size.width + i]));
if (tileId != 0) { if (tileId != 0) {
dungeon[position.x + i][position.y + j] = tileId; dungeon[position.x + i][position.y + j] = tileId;
Protected.set(position.x + i, position.y + j); Protected.set(position.x + i, position.y + j);
@ -761,17 +762,17 @@ void DRLG_HoldThemeRooms()
WorldTileSize GetDunSize(const uint16_t *dunData) WorldTileSize GetDunSize(const uint16_t *dunData)
{ {
return WorldTileSize(static_cast<WorldTileCoord>(SDL_SwapLE16(dunData[0])), static_cast<WorldTileCoord>(SDL_SwapLE16(dunData[1]))); return WorldTileSize(static_cast<WorldTileCoord>(Swap16LE(dunData[0])), static_cast<WorldTileCoord>(Swap16LE(dunData[1])));
} }
void DRLG_LPass3(int lv) void DRLG_LPass3(int lv)
{ {
{ {
const MegaTile mega = pMegaTiles[lv]; const MegaTile mega = pMegaTiles[lv];
const int v1 = SDL_SwapLE16(mega.micro1); const int v1 = Swap16LE(mega.micro1);
const int v2 = SDL_SwapLE16(mega.micro2); const int v2 = Swap16LE(mega.micro2);
const int v3 = SDL_SwapLE16(mega.micro3); const int v3 = Swap16LE(mega.micro3);
const int v4 = SDL_SwapLE16(mega.micro4); const int v4 = Swap16LE(mega.micro4);
for (int j = 0; j < MAXDUNY; j += 2) { for (int j = 0; j < MAXDUNY; j += 2) {
for (int i = 0; i < MAXDUNX; i += 2) { for (int i = 0; i < MAXDUNX; i += 2) {
@ -789,10 +790,10 @@ void DRLG_LPass3(int lv)
for (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert) for (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)
const int tileId = dungeon[i][j] - 1; const int tileId = dungeon[i][j] - 1;
const MegaTile mega = pMegaTiles[tileId]; const MegaTile mega = pMegaTiles[tileId];
dPiece[xx + 0][yy + 0] = SDL_SwapLE16(mega.micro1); dPiece[xx + 0][yy + 0] = Swap16LE(mega.micro1);
dPiece[xx + 1][yy + 0] = SDL_SwapLE16(mega.micro2); dPiece[xx + 1][yy + 0] = Swap16LE(mega.micro2);
dPiece[xx + 0][yy + 1] = SDL_SwapLE16(mega.micro3); dPiece[xx + 0][yy + 1] = Swap16LE(mega.micro3);
dPiece[xx + 1][yy + 1] = SDL_SwapLE16(mega.micro4); dPiece[xx + 1][yy + 1] = Swap16LE(mega.micro4);
xx += 2; xx += 2;
} }
yy += 2; yy += 2;

15
Source/objects.cpp

@ -45,6 +45,7 @@
#include "towners.h" #include "towners.h"
#include "track.h" #include "track.h"
#include "utils/algorithm/container.hpp" #include "utils/algorithm/container.hpp"
#include "utils/endian_swap.hpp"
#include "utils/is_of.hpp" #include "utils/is_of.hpp"
#include "utils/language.h" #include "utils/language.h"
#include "utils/log.hpp" #include "utils/log.hpp"
@ -574,7 +575,7 @@ void LoadMapObjects(const char *path, Point start, WorldTileRectangle mapRange =
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[j * size.width + i])); auto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));
if (objectId != 0) { if (objectId != 0) {
const Point mapPos = start + Displacement { i, j }; const Point mapPos = start + Displacement { i, j };
Object *mapObject = AddObject(ObjTypeConv[objectId], mapPos); Object *mapObject = AddObject(ObjTypeConv[objectId], mapPos);
@ -1669,10 +1670,10 @@ void ObjSetMini(Point position, int v)
const Point megaOrigin = position.megaToWorld(); const Point megaOrigin = position.megaToWorld();
ObjSetMicro(megaOrigin, SDL_SwapLE16(mega.micro1)); ObjSetMicro(megaOrigin, Swap16LE(mega.micro1));
ObjSetMicro(megaOrigin + Direction::SouthEast, SDL_SwapLE16(mega.micro2)); ObjSetMicro(megaOrigin + Direction::SouthEast, Swap16LE(mega.micro2));
ObjSetMicro(megaOrigin + Direction::SouthWest, SDL_SwapLE16(mega.micro3)); ObjSetMicro(megaOrigin + Direction::SouthWest, Swap16LE(mega.micro3));
ObjSetMicro(megaOrigin + Direction::South, SDL_SwapLE16(mega.micro4)); ObjSetMicro(megaOrigin + Direction::South, Swap16LE(mega.micro4));
} }
void ObjL1Special(int x1, int y1, int x2, int y2) void ObjL1Special(int x1, int y1, int x2, int y2)
@ -3988,7 +3989,7 @@ void SetMapObjects(const uint16_t *dunData, int startx, int starty)
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[j * size.width + i])); auto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));
if (objectId != 0) { if (objectId != 0) {
const ObjectData &objectData = AllObjects[ObjTypeConv[objectId]]; const ObjectData &objectData = AllObjects[ObjTypeConv[objectId]];
filesWidths[objectData.ofindex] = objectData.animWidth; filesWidths[objectData.ofindex] = objectData.animWidth;
@ -4000,7 +4001,7 @@ void SetMapObjects(const uint16_t *dunData, int startx, int starty)
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[j * size.width + i])); auto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));
if (objectId != 0) { if (objectId != 0) {
AddObject(ObjTypeConv[objectId], { startx + 16 + i, starty + 16 + j }); AddObject(ObjTypeConv[objectId], { startx + 16 + i, starty + 16 + j });
} }

7
Source/panels/console.cpp

@ -5,12 +5,17 @@
#include <cstdint> #include <cstdint>
#include <string_view> #include <string_view>
#include <SDL.h>
#include <function_ref.hpp> #include <function_ref.hpp>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h>
#ifdef USE_SDL1 #ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h" #include "utils/sdl2_to_1_2_backports.h"
#endif #endif
#endif
#include "DiabloUI/text_input.hpp" #include "DiabloUI/text_input.hpp"
#include "control.h" #include "control.h"

4
Source/panels/console.hpp

@ -3,7 +3,11 @@
#include <string_view> #include <string_view>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#else
#include <SDL.h> #include <SDL.h>
#endif
#include "engine/surface.hpp" #include "engine/surface.hpp"

3
Source/quests.cpp

@ -30,6 +30,7 @@
#include "panels/ui_panels.hpp" #include "panels/ui_panels.hpp"
#include "stores.h" #include "stores.h"
#include "towners.h" #include "towners.h"
#include "utils/endian_swap.hpp"
#include "utils/is_of.hpp" #include "utils/is_of.hpp"
#include "utils/language.h" #include "utils/language.h"
#include "utils/utf8.hpp" #include "utils/utf8.hpp"
@ -126,7 +127,7 @@ void DrawLTBanner(Point position)
for (WorldTileCoord j = 0; j < size.height; j++) { for (WorldTileCoord j = 0; j < size.height; j++) {
for (WorldTileCoord i = 0; i < size.width; i++) { for (WorldTileCoord i = 0; i < size.width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * size.width + i])); auto tileId = static_cast<uint8_t>(Swap16LE(tileLayer[j * size.width + i]));
if (tileId != 0) { if (tileId != 0) {
pdungeon[position.x + i][position.y + j] = tileId; pdungeon[position.x + i][position.y + j] = tileId;
} }

Loading…
Cancel
Save