mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-11 10:31:16 +00:00
Integrate SDL Haptic API (#607)
* Integrate SDL Haptic API * Close other devices * Fixes
This commit is contained in:
parent
87c89885ba
commit
f20fc475c7
@ -137,8 +137,6 @@ IsleApp::IsleApp()
|
|||||||
m_drawCursor = FALSE;
|
m_drawCursor = FALSE;
|
||||||
m_use3dSound = TRUE;
|
m_use3dSound = TRUE;
|
||||||
m_useMusic = TRUE;
|
m_useMusic = TRUE;
|
||||||
m_useJoystick = TRUE;
|
|
||||||
m_joystickIndex = 0;
|
|
||||||
m_wideViewAngle = TRUE;
|
m_wideViewAngle = TRUE;
|
||||||
m_islandQuality = 2;
|
m_islandQuality = 2;
|
||||||
m_islandTexture = 1;
|
m_islandTexture = 1;
|
||||||
@ -297,7 +295,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv)
|
|||||||
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
||||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC)) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
SDL_snprintf(
|
SDL_snprintf(
|
||||||
buffer,
|
buffer,
|
||||||
@ -340,6 +338,23 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv)
|
|||||||
// Get reference to window
|
// Get reference to window
|
||||||
*appstate = g_isle->GetWindowHandle();
|
*appstate = g_isle->GetWindowHandle();
|
||||||
|
|
||||||
|
// Currently, SDL doesn't send SDL_EVENT_MOUSE_ADDED at startup (unlike for gamepads)
|
||||||
|
// This will probably be fixed in the future: https://github.com/libsdl-org/SDL/issues/12815
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
SDL_MouseID* mice = SDL_GetMice(&count);
|
||||||
|
|
||||||
|
if (mice) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (InputManager()) {
|
||||||
|
InputManager()->AddMouse(mice[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(mice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
SDL_AddEventWatch(
|
SDL_AddEventWatch(
|
||||||
[](void* userdata, SDL_Event* event) -> bool {
|
[](void* userdata, SDL_Event* event) -> bool {
|
||||||
@ -423,6 +438,10 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
|||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InputManager()) {
|
||||||
|
InputManager()->UpdateLastInputMethod(event);
|
||||||
|
}
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||||
case SDL_EVENT_MOUSE_MOTION:
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
@ -482,13 +501,26 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_EVENT_GAMEPAD_ADDED:
|
case SDL_EVENT_MOUSE_ADDED:
|
||||||
case SDL_EVENT_GAMEPAD_REMOVED: {
|
|
||||||
if (InputManager()) {
|
if (InputManager()) {
|
||||||
InputManager()->GetJoystick();
|
InputManager()->AddMouse(event->mdevice.which);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_REMOVED:
|
||||||
|
if (InputManager()) {
|
||||||
|
InputManager()->RemoveMouse(event->mdevice.which);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_ADDED:
|
||||||
|
if (InputManager()) {
|
||||||
|
InputManager()->AddJoystick(event->jdevice.which);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||||
|
if (InputManager()) {
|
||||||
|
InputManager()->RemoveJoystick(event->jdevice.which);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN: {
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN: {
|
||||||
switch (event->gbutton.button) {
|
switch (event->gbutton.button) {
|
||||||
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
||||||
@ -903,10 +935,6 @@ MxResult IsleApp::SetupWindow()
|
|||||||
MxTransitionManager::configureMxTransitionManager(m_transitionType);
|
MxTransitionManager::configureMxTransitionManager(m_transitionType);
|
||||||
RealtimeView::SetUserMaxLOD(m_maxLod);
|
RealtimeView::SetUserMaxLOD(m_maxLod);
|
||||||
if (LegoOmni::GetInstance()) {
|
if (LegoOmni::GetInstance()) {
|
||||||
if (LegoOmni::GetInstance()->GetInputManager()) {
|
|
||||||
LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick);
|
|
||||||
LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex);
|
|
||||||
}
|
|
||||||
if (LegoOmni::GetInstance()->GetVideoManager()) {
|
if (LegoOmni::GetInstance()->GetVideoManager()) {
|
||||||
LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap);
|
LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap);
|
||||||
}
|
}
|
||||||
@ -998,8 +1026,6 @@ bool IsleApp::LoadConfig()
|
|||||||
iniparser_set(dict, "isle:3DSound", m_use3dSound ? "true" : "false");
|
iniparser_set(dict, "isle:3DSound", m_use3dSound ? "true" : "false");
|
||||||
iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false");
|
iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false");
|
||||||
|
|
||||||
iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false");
|
|
||||||
iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10));
|
|
||||||
SDL_snprintf(buf, sizeof(buf), "%f", m_cursorSensitivity);
|
SDL_snprintf(buf, sizeof(buf), "%f", m_cursorSensitivity);
|
||||||
iniparser_set(dict, "isle:Cursor Sensitivity", buf);
|
iniparser_set(dict, "isle:Cursor Sensitivity", buf);
|
||||||
|
|
||||||
@ -1058,8 +1084,6 @@ bool IsleApp::LoadConfig()
|
|||||||
m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle);
|
m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle);
|
||||||
m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound);
|
m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound);
|
||||||
m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic);
|
m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic);
|
||||||
m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick);
|
|
||||||
m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex);
|
|
||||||
m_cursorSensitivity = iniparser_getdouble(dict, "isle:Cursor Sensitivity", m_cursorSensitivity);
|
m_cursorSensitivity = iniparser_getdouble(dict, "isle:Cursor Sensitivity", m_cursorSensitivity);
|
||||||
|
|
||||||
MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1);
|
MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1);
|
||||||
|
|||||||
@ -80,8 +80,6 @@ class IsleApp {
|
|||||||
MxS32 m_hasLightSupport; // 0x24
|
MxS32 m_hasLightSupport; // 0x24
|
||||||
MxS32 m_use3dSound; // 0x28
|
MxS32 m_use3dSound; // 0x28
|
||||||
MxS32 m_useMusic; // 0x2c
|
MxS32 m_useMusic; // 0x2c
|
||||||
MxS32 m_useJoystick; // 0x30
|
|
||||||
MxS32 m_joystickIndex; // 0x34
|
|
||||||
MxS32 m_wideViewAngle; // 0x38
|
MxS32 m_wideViewAngle; // 0x38
|
||||||
MxS32 m_islandQuality; // 0x3c
|
MxS32 m_islandQuality; // 0x3c
|
||||||
MxS32 m_islandTexture; // 0x40
|
MxS32 m_islandTexture; // 0x40
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "mxpresenter.h"
|
#include "mxpresenter.h"
|
||||||
#include "mxqueue.h"
|
#include "mxqueue.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL_haptic.h>
|
||||||
#include <SDL3/SDL_joystick.h>
|
#include <SDL3/SDL_joystick.h>
|
||||||
#include <SDL3/SDL_keyboard.h>
|
#include <SDL3/SDL_keyboard.h>
|
||||||
#include <SDL3/SDL_keycode.h>
|
#include <SDL3/SDL_keycode.h>
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
class LegoCameraController;
|
class LegoCameraController;
|
||||||
class LegoControlManager;
|
class LegoControlManager;
|
||||||
@ -129,8 +131,6 @@ class LegoInputManager : public MxPresenter {
|
|||||||
void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; }
|
void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; }
|
||||||
void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; }
|
void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; }
|
||||||
void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; }
|
void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; }
|
||||||
void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; }
|
|
||||||
void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; }
|
|
||||||
|
|
||||||
// FUNCTION: BETA10 0x1002e290
|
// FUNCTION: BETA10 0x1002e290
|
||||||
void DisableInputProcessing()
|
void DisableInputProcessing()
|
||||||
@ -153,13 +153,26 @@ class LegoInputManager : public MxPresenter {
|
|||||||
void GetKeyboardState();
|
void GetKeyboardState();
|
||||||
MxResult GetNavigationKeyStates(MxU32& p_keyFlags);
|
MxResult GetNavigationKeyStates(MxU32& p_keyFlags);
|
||||||
MxResult GetNavigationTouchStates(MxU32& p_keyFlags);
|
MxResult GetNavigationTouchStates(MxU32& p_keyFlags);
|
||||||
|
LEGO1_EXPORT void AddMouse(SDL_MouseID p_mouseID);
|
||||||
|
LEGO1_EXPORT void RemoveMouse(SDL_MouseID p_mouseID);
|
||||||
|
LEGO1_EXPORT void AddJoystick(SDL_JoystickID p_joystickID);
|
||||||
|
LEGO1_EXPORT void RemoveJoystick(SDL_JoystickID p_joystickID);
|
||||||
LEGO1_EXPORT MxBool HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme);
|
LEGO1_EXPORT MxBool HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme);
|
||||||
LEGO1_EXPORT MxBool HandleRumbleEvent();
|
LEGO1_EXPORT MxBool HandleRumbleEvent();
|
||||||
|
LEGO1_EXPORT void UpdateLastInputMethod(SDL_Event* p_event);
|
||||||
|
|
||||||
// SYNTHETIC: LEGO1 0x1005b8d0
|
// SYNTHETIC: LEGO1 0x1005b8d0
|
||||||
// LegoInputManager::`scalar deleting destructor'
|
// LegoInputManager::`scalar deleting destructor'
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// clang-format off
|
||||||
|
enum class SDL_MouseID_v : SDL_MouseID {};
|
||||||
|
enum class SDL_JoystickID_v : SDL_JoystickID {};
|
||||||
|
enum class SDL_TouchID_v : SDL_TouchID {};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
void InitializeHaptics();
|
||||||
|
|
||||||
MxCriticalSection m_criticalSection; // 0x58
|
MxCriticalSection m_criticalSection; // 0x58
|
||||||
LegoNotifyList* m_keyboardNotifyList; // 0x5c
|
LegoNotifyList* m_keyboardNotifyList; // 0x5c
|
||||||
LegoCameraController* m_camera; // 0x60
|
LegoCameraController* m_camera; // 0x60
|
||||||
@ -176,16 +189,16 @@ class LegoInputManager : public MxPresenter {
|
|||||||
MxBool m_unk0x88; // 0x88
|
MxBool m_unk0x88; // 0x88
|
||||||
const bool* m_keyboardState;
|
const bool* m_keyboardState;
|
||||||
MxBool m_unk0x195; // 0x195
|
MxBool m_unk0x195; // 0x195
|
||||||
SDL_JoystickID* m_joyids;
|
MxBool m_unk0x335; // 0x335
|
||||||
SDL_Gamepad* m_joystick;
|
MxBool m_unk0x336; // 0x336
|
||||||
MxS32 m_joystickIndex; // 0x19c
|
|
||||||
MxBool m_useJoystick; // 0x334
|
|
||||||
MxBool m_unk0x335; // 0x335
|
|
||||||
MxBool m_unk0x336; // 0x336
|
|
||||||
|
|
||||||
std::map<SDL_FingerID, SDL_FPoint> m_touchOrigins;
|
std::map<SDL_FingerID, SDL_FPoint> m_touchOrigins;
|
||||||
std::map<SDL_FingerID, MxU32> m_touchFlags;
|
std::map<SDL_FingerID, MxU32> m_touchFlags;
|
||||||
std::map<SDL_FingerID, std::pair<MxU32, SDL_FPoint>> m_touchLastMotion;
|
std::map<SDL_FingerID, std::pair<MxU32, SDL_FPoint>> m_touchLastMotion;
|
||||||
|
std::map<SDL_MouseID, std::pair<void*, SDL_Haptic*>> m_mice;
|
||||||
|
std::map<SDL_JoystickID, std::pair<SDL_Gamepad*, SDL_Haptic*>> m_joysticks;
|
||||||
|
std::map<SDL_HapticID, SDL_Haptic*> m_otherHaptics;
|
||||||
|
std::variant<SDL_MouseID_v, SDL_JoystickID_v, SDL_TouchID_v> m_lastInputMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x10028850
|
// TEMPLATE: LEGO1 0x10028850
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#include "mxdebug.h"
|
#include "mxdebug.h"
|
||||||
#include "roi/legoroi.h"
|
#include "roi/legoroi.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL_log.h>
|
||||||
|
|
||||||
DECOMP_SIZE_ASSERT(LegoInputManager, 0x338)
|
DECOMP_SIZE_ASSERT(LegoInputManager, 0x338)
|
||||||
DECOMP_SIZE_ASSERT(LegoNotifyList, 0x18)
|
DECOMP_SIZE_ASSERT(LegoNotifyList, 0x18)
|
||||||
DECOMP_SIZE_ASSERT(LegoNotifyListCursor, 0x10)
|
DECOMP_SIZE_ASSERT(LegoNotifyListCursor, 0x10)
|
||||||
@ -40,10 +42,6 @@ LegoInputManager::LegoInputManager()
|
|||||||
m_unk0x81 = FALSE;
|
m_unk0x81 = FALSE;
|
||||||
m_unk0x88 = FALSE;
|
m_unk0x88 = FALSE;
|
||||||
m_unk0x195 = 0;
|
m_unk0x195 = 0;
|
||||||
m_joyids = NULL;
|
|
||||||
m_joystickIndex = -1;
|
|
||||||
m_joystick = NULL;
|
|
||||||
m_useJoystick = FALSE;
|
|
||||||
m_unk0x335 = FALSE;
|
m_unk0x335 = FALSE;
|
||||||
m_unk0x336 = FALSE;
|
m_unk0x336 = FALSE;
|
||||||
m_unk0x74 = 0x19;
|
m_unk0x74 = 0x19;
|
||||||
@ -71,8 +69,6 @@ MxResult LegoInputManager::Create(HWND p_hwnd)
|
|||||||
m_eventQueue = new LegoEventQueue;
|
m_eventQueue = new LegoEventQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetJoystick();
|
|
||||||
|
|
||||||
if (!m_keyboardNotifyList || !m_eventQueue) {
|
if (!m_keyboardNotifyList || !m_eventQueue) {
|
||||||
Destroy();
|
Destroy();
|
||||||
result = FAILURE;
|
result = FAILURE;
|
||||||
@ -98,7 +94,23 @@ void LegoInputManager::Destroy()
|
|||||||
delete m_controlManager;
|
delete m_controlManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(m_joyids);
|
for (const auto& [id, joystick] : m_joysticks) {
|
||||||
|
if (joystick.second) {
|
||||||
|
SDL_CloseHaptic(joystick.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_CloseGamepad(joystick.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [id, mouse] : m_mice) {
|
||||||
|
if (mouse.second) {
|
||||||
|
SDL_CloseHaptic(mouse.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [id, haptic] : m_otherHaptics) {
|
||||||
|
SDL_CloseHaptic(haptic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1005c0f0
|
// FUNCTION: LEGO1 0x1005c0f0
|
||||||
@ -145,74 +157,33 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags)
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1005c240
|
|
||||||
MxResult LegoInputManager::GetJoystick()
|
|
||||||
{
|
|
||||||
if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) {
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
MxS32 numJoysticks = 0;
|
|
||||||
if (m_joyids != NULL) {
|
|
||||||
SDL_free(m_joyids);
|
|
||||||
m_joyids = NULL;
|
|
||||||
}
|
|
||||||
m_joyids = SDL_GetGamepads(&numJoysticks);
|
|
||||||
|
|
||||||
if (m_useJoystick != FALSE && numJoysticks != 0) {
|
|
||||||
MxS32 joyid = m_joystickIndex;
|
|
||||||
if (joyid >= 0) {
|
|
||||||
m_joystick = SDL_OpenGamepad(m_joyids[joyid]);
|
|
||||||
if (m_joystick != NULL) {
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (joyid = 0; joyid < numJoysticks; joyid++) {
|
|
||||||
m_joystick = SDL_OpenGamepad(m_joyids[joyid]);
|
|
||||||
if (m_joystick != NULL) {
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1005c320
|
// FUNCTION: LEGO1 0x1005c320
|
||||||
MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition)
|
MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition)
|
||||||
{
|
{
|
||||||
if (m_useJoystick != FALSE) {
|
if (m_joysticks.empty()) {
|
||||||
if (GetJoystick() == -1) {
|
return FAILURE;
|
||||||
if (m_joystick != NULL) {
|
}
|
||||||
// GetJoystick() failed but handle to joystick is still open, close it
|
|
||||||
SDL_CloseGamepad(m_joystick);
|
|
||||||
m_joystick = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FAILURE;
|
MxS16 xPos, yPos = 0;
|
||||||
}
|
for (const auto& [id, joystick] : m_joysticks) {
|
||||||
|
xPos = SDL_GetGamepadAxis(joystick.first, SDL_GAMEPAD_AXIS_LEFTX);
|
||||||
MxS16 xPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTX);
|
yPos = SDL_GetGamepadAxis(joystick.first, SDL_GAMEPAD_AXIS_LEFTY);
|
||||||
MxS16 yPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTY);
|
|
||||||
if (xPos > -8000 && xPos < 8000) {
|
if (xPos > -8000 && xPos < 8000) {
|
||||||
// Ignore small axis values
|
|
||||||
xPos = 0;
|
xPos = 0;
|
||||||
}
|
}
|
||||||
if (yPos > -8000 && yPos < 8000) {
|
if (yPos > -8000 && yPos < 8000) {
|
||||||
// Ignore small axis values
|
|
||||||
yPos = 0;
|
yPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize values acquired from joystick axes
|
if (xPos || yPos) {
|
||||||
*p_joystickX = ((xPos + 32768) * 100) / 65535;
|
break;
|
||||||
*p_joystickY = ((yPos + 32768) * 100) / 65535;
|
}
|
||||||
*p_povPosition = -1;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FAILURE;
|
*p_joystickX = ((xPos + 32768) * 100) / 65535;
|
||||||
|
*p_joystickY = ((yPos + 32768) * 100) / 65535;
|
||||||
|
*p_povPosition = -1;
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1005c470
|
// FUNCTION: LEGO1 0x1005c470
|
||||||
@ -546,6 +517,74 @@ MxResult LegoInputManager::GetNavigationTouchStates(MxU32& p_keyStates)
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::AddMouse(SDL_MouseID p_mouseID)
|
||||||
|
{
|
||||||
|
if (m_mice.count(p_mouseID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently no way to get an individual haptic device for a mouse.
|
||||||
|
SDL_Haptic* haptic = SDL_OpenHapticFromMouse();
|
||||||
|
if (haptic) {
|
||||||
|
if (!SDL_InitHapticRumble(haptic)) {
|
||||||
|
SDL_CloseHaptic(haptic);
|
||||||
|
haptic = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mice[p_mouseID] = {nullptr, haptic};
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::RemoveMouse(SDL_MouseID p_mouseID)
|
||||||
|
{
|
||||||
|
if (!m_mice.count(p_mouseID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mice[p_mouseID].second) {
|
||||||
|
SDL_CloseHaptic(m_mice[p_mouseID].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mice.erase(p_mouseID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::AddJoystick(SDL_JoystickID p_joystickID)
|
||||||
|
{
|
||||||
|
if (m_joysticks.count(p_joystickID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Gamepad* joystick = SDL_OpenGamepad(p_joystickID);
|
||||||
|
if (joystick) {
|
||||||
|
SDL_Haptic* haptic = SDL_OpenHapticFromJoystick(SDL_GetGamepadJoystick(joystick));
|
||||||
|
if (haptic) {
|
||||||
|
if (!SDL_InitHapticRumble(haptic)) {
|
||||||
|
SDL_CloseHaptic(haptic);
|
||||||
|
haptic = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_joysticks[p_joystickID] = {joystick, haptic};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_Log("Failed to open gamepad: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::RemoveJoystick(SDL_JoystickID p_joystickID)
|
||||||
|
{
|
||||||
|
if (!m_joysticks.count(p_joystickID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_joysticks[p_joystickID].second) {
|
||||||
|
SDL_CloseHaptic(m_joysticks[p_joystickID].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_CloseGamepad(m_joysticks[p_joystickID].first);
|
||||||
|
m_joysticks.erase(p_joystickID);
|
||||||
|
}
|
||||||
|
|
||||||
MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme)
|
MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme)
|
||||||
{
|
{
|
||||||
const SDL_TouchFingerEvent& event = p_event->tfinger;
|
const SDL_TouchFingerEvent& event = p_event->tfinger;
|
||||||
@ -629,15 +668,118 @@ MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touc
|
|||||||
|
|
||||||
MxBool LegoInputManager::HandleRumbleEvent()
|
MxBool LegoInputManager::HandleRumbleEvent()
|
||||||
{
|
{
|
||||||
if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) {
|
static bool g_hapticsInitialized = false;
|
||||||
const Uint16 frequency = 65535 / 2;
|
|
||||||
const Uint32 durationMs = 700;
|
if (!g_hapticsInitialized) {
|
||||||
SDL_RumbleGamepad(m_joystick, frequency, frequency, durationMs);
|
InitializeHaptics();
|
||||||
}
|
g_hapticsInitialized = true;
|
||||||
else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add support for SDL Haptic API
|
SDL_Haptic* haptic = nullptr;
|
||||||
return TRUE;
|
std::visit(
|
||||||
|
overloaded{
|
||||||
|
[&haptic, this](SDL_MouseID_v p_id) {
|
||||||
|
if (m_mice.count((SDL_MouseID) p_id)) {
|
||||||
|
haptic = m_mice[(SDL_MouseID) p_id].second;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&haptic, this](SDL_JoystickID_v p_id) {
|
||||||
|
if (m_joysticks.count((SDL_JoystickID) p_id)) {
|
||||||
|
haptic = m_joysticks[(SDL_JoystickID) p_id].second;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&haptic, this](SDL_TouchID_v p_id) {
|
||||||
|
// We can't currently correlate Touch devices with Haptic devices
|
||||||
|
if (!m_otherHaptics.empty()) {
|
||||||
|
haptic = m_otherHaptics.begin()->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
m_lastInputMethod
|
||||||
|
);
|
||||||
|
|
||||||
|
const float strength = 0.5f;
|
||||||
|
const Uint32 durationMs = 700;
|
||||||
|
|
||||||
|
if (haptic) {
|
||||||
|
return SDL_PlayHapticRumble(haptic, strength, durationMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A joystick isn't necessarily a haptic device; try basic rumble instead
|
||||||
|
if (const SDL_JoystickID_v* joystick = std::get_if<SDL_JoystickID_v>(&m_lastInputMethod)) {
|
||||||
|
if (m_joysticks.count((SDL_JoystickID) *joystick)) {
|
||||||
|
return SDL_RumbleGamepad(
|
||||||
|
m_joysticks[(SDL_JoystickID) *joystick].first,
|
||||||
|
strength * 65535,
|
||||||
|
strength * 65535,
|
||||||
|
durationMs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::InitializeHaptics()
|
||||||
|
{
|
||||||
|
// We don't get added/removed events for haptic devices that are not joysticks or mice,
|
||||||
|
// so we initialize "otherHaptics" once at this point.
|
||||||
|
std::vector<SDL_HapticID> existingHaptics;
|
||||||
|
|
||||||
|
for (const auto& [id, mouse] : m_mice) {
|
||||||
|
if (mouse.second) {
|
||||||
|
existingHaptics.push_back(SDL_GetHapticID(mouse.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [id, joystick] : m_joysticks) {
|
||||||
|
if (joystick.second) {
|
||||||
|
existingHaptics.push_back(SDL_GetHapticID(joystick.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int count;
|
||||||
|
SDL_HapticID* haptics = SDL_GetHaptics(&count);
|
||||||
|
if (haptics) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (std::find(existingHaptics.begin(), existingHaptics.end(), haptics[i]) == existingHaptics.end()) {
|
||||||
|
SDL_Haptic* haptic = SDL_OpenHaptic(haptics[i]);
|
||||||
|
if (haptic) {
|
||||||
|
if (SDL_InitHapticRumble(haptic)) {
|
||||||
|
m_otherHaptics[haptics[i]] = haptic;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_CloseHaptic(haptic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(haptics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegoInputManager::UpdateLastInputMethod(SDL_Event* p_event)
|
||||||
|
{
|
||||||
|
switch (p_event->type) {
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
m_lastInputMethod = SDL_MouseID_v{p_event->button.which};
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
|
m_lastInputMethod = SDL_MouseID_v{p_event->motion.which};
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||||
|
m_lastInputMethod = SDL_JoystickID_v{p_event->gbutton.which};
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||||
|
m_lastInputMethod = SDL_JoystickID_v{p_event->gaxis.which};
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_FINGER_MOTION:
|
||||||
|
case SDL_EVENT_FINGER_DOWN:
|
||||||
|
case SDL_EVENT_FINGER_UP:
|
||||||
|
m_lastInputMethod = SDL_TouchID_v{p_event->tfinger.touchID};
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,4 +59,12 @@ inline T RToD(T p_r)
|
|||||||
return p_r * 180.0F / 3.1416F;
|
return p_r * 180.0F / 3.1416F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class... Ts>
|
||||||
|
struct overloaded : Ts... {
|
||||||
|
using Ts::operator()...;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class... Ts>
|
||||||
|
overloaded(Ts...) -> overloaded<Ts...>;
|
||||||
|
|
||||||
#endif // __LEGOUTIL_H
|
#endif // __LEGOUTIL_H
|
||||||
|
|||||||
@ -74,3 +74,6 @@ cksize: "Re-defined Windows name"
|
|||||||
fccType: "Re-defined Windows name"
|
fccType: "Re-defined Windows name"
|
||||||
dwDataOffset: "Re-defined Windows name"
|
dwDataOffset: "Re-defined Windows name"
|
||||||
fccType: "Re-defined Windows name"
|
fccType: "Re-defined Windows name"
|
||||||
|
SDL_MouseID_v: "SDL-based name"
|
||||||
|
SDL_JoystickID_v: "SDL-based name"
|
||||||
|
SDL_TouchID_v: "SDL-based name"
|
||||||
Loading…
Reference in New Issue
Block a user