mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-14 10:55:14 +00:00
More Lib mouse (#1414)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
* system/msgdialog: callback available to be used by host * sdl window: mouse capture var * lib/pad: basic special pad impl scaffold & steering wheel (config specialPadClass set to 6 is required) * handle all mouse inputs & ask to capture when first opened
This commit is contained in:
parent
92b9903467
commit
8dc956a476
|
@ -425,6 +425,13 @@ constexpr int ORBIS_PAD_ERROR_INVALID_REPORT_LENGTH = 0x80920103;
|
||||||
constexpr int ORBIS_PAD_ERROR_INVALID_REPORT_ID = 0x80920104;
|
constexpr int ORBIS_PAD_ERROR_INVALID_REPORT_ID = 0x80920104;
|
||||||
constexpr int ORBIS_PAD_ERROR_SEND_AGAIN = 0x80920105;
|
constexpr int ORBIS_PAD_ERROR_SEND_AGAIN = 0x80920105;
|
||||||
|
|
||||||
|
// Mouse library
|
||||||
|
constexpr int ORBIS_MOUSE_ERROR_INVALID_ARG = 0x80DF0001;
|
||||||
|
constexpr int ORBIS_MOUSE_ERROR_INVALID_HANDLE = 0x80DF0003;
|
||||||
|
constexpr int ORBIS_MOUSE_ERROR_ALREADY_OPENED = 0x80DF0004;
|
||||||
|
constexpr int ORBIS_MOUSE_ERROR_NOT_INITIALIZED = 0x80DF0005;
|
||||||
|
constexpr int ORBIS_MOUSE_ERROR_FATAL = 0x80DF00FF;
|
||||||
|
|
||||||
// UserService library
|
// UserService library
|
||||||
constexpr int ORBIS_USER_SERVICE_ERROR_INTERNAL = 0x80960001;
|
constexpr int ORBIS_USER_SERVICE_ERROR_INTERNAL = 0x80960001;
|
||||||
constexpr int ORBIS_USER_SERVICE_ERROR_NOT_INITIALIZED = 0x80960002;
|
constexpr int ORBIS_USER_SERVICE_ERROR_NOT_INITIALIZED = 0x80960002;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
// Generated By moduleGenerator
|
// Generated By moduleGenerator
|
||||||
#include <common/singleton.h>
|
#include <common/singleton.h>
|
||||||
|
#include <core/libraries/system/msgdialog_ui.h>
|
||||||
#include <input/mouse.h>
|
#include <input/mouse.h>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
|
@ -11,10 +12,32 @@
|
||||||
|
|
||||||
namespace Libraries::Mouse {
|
namespace Libraries::Mouse {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseClose() {
|
static bool g_initialized = false;
|
||||||
LOG_ERROR(Lib_Mouse, "(STUBBED) called");
|
static bool g_mouse1_open = false;
|
||||||
|
static bool g_mouse2_open = false;
|
||||||
|
|
||||||
|
constexpr auto MOUSE1_HANDLE = 0xF1;
|
||||||
|
constexpr auto MOUSE2_HANDLE = 0xF2;
|
||||||
|
|
||||||
|
constexpr auto ORBIS_MOUSE_OPEN_PARAM_NORMAL = 0x00;
|
||||||
|
constexpr auto ORBIS_MOUSE_OPEN_PARAM_MERGED = 0x01;
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceMouseClose(s32 handle) {
|
||||||
|
LOG_INFO(Lib_Mouse, "called");
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_MOUSE_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
if (handle == MOUSE1_HANDLE && g_mouse1_open) {
|
||||||
|
g_mouse1_open = false;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
if (handle == MOUSE2_HANDLE && g_mouse2_open) {
|
||||||
|
g_mouse2_open = false;
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseConnectPort() {
|
int PS4_SYSV_ABI sceMouseConnectPort() {
|
||||||
LOG_ERROR(Lib_Mouse, "(STUBBED) called");
|
LOG_ERROR(Lib_Mouse, "(STUBBED) called");
|
||||||
|
@ -48,6 +71,7 @@ int PS4_SYSV_ABI sceMouseGetDeviceInfo() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseInit() {
|
int PS4_SYSV_ABI sceMouseInit() {
|
||||||
LOG_INFO(Lib_Mouse, "called");
|
LOG_INFO(Lib_Mouse, "called");
|
||||||
|
g_initialized = true;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,28 +81,93 @@ int PS4_SYSV_ABI sceMouseMbusInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseOpen(s32 userId, s32 type, s32 index, OrbisMouseOpenParam* pParam) {
|
int PS4_SYSV_ABI sceMouseOpen(s32 userId, s32 type, s32 index, OrbisMouseOpenParam* pParam) {
|
||||||
LOG_INFO(Lib_Mouse, "(DUMMY) called");
|
LOG_INFO(Lib_Mouse, "called");
|
||||||
return 2; // dummy
|
if (!g_initialized) {
|
||||||
|
return ORBIS_MOUSE_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
bool merge = pParam != nullptr && (pParam->behaviorFlag & ORBIS_MOUSE_OPEN_PARAM_MERGED) != 0;
|
||||||
|
|
||||||
|
if (merge || index == 0) {
|
||||||
|
if (g_mouse1_open) {
|
||||||
|
return ORBIS_PAD_ERROR_ALREADY_OPENED;
|
||||||
|
}
|
||||||
|
g_mouse1_open = true;
|
||||||
|
if (!Common::Singleton<Input::GameMouse>::Instance()->m_connected) {
|
||||||
|
MsgDialog::ShowMsgDialog(
|
||||||
|
MsgDialog::MsgDialogState(MsgDialog::MsgDialogState::UserState{
|
||||||
|
.type = MsgDialog::ButtonType::YESNO,
|
||||||
|
.msg = "Game wants to use your mouse.\nDo you want to allow it?",
|
||||||
|
}),
|
||||||
|
false, [](MsgDialog::DialogResult result) {
|
||||||
|
if (result.buttonId == MsgDialog::ButtonId::YES) {
|
||||||
|
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
||||||
|
mouse->m_connected = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return MOUSE1_HANDLE;
|
||||||
|
}
|
||||||
|
if (index == 1) {
|
||||||
|
if (g_mouse2_open) {
|
||||||
|
return ORBIS_PAD_ERROR_ALREADY_OPENED;
|
||||||
|
}
|
||||||
|
g_mouse2_open = true;
|
||||||
|
return MOUSE2_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseRead(s32 handle, OrbisMouseData* pData, s32 num) {
|
int PS4_SYSV_ABI sceMouseRead(s32 handle, OrbisMouseData* pData, s32 num) {
|
||||||
bool connected = false;
|
LOG_TRACE(Lib_Mouse, "called");
|
||||||
Input::MouseState states[64];
|
|
||||||
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
|
||||||
int ret_num = mouse->ReadStates(states, num, &connected);
|
|
||||||
|
|
||||||
if (!connected) {
|
if (!g_initialized) {
|
||||||
ret_num = 1;
|
return ORBIS_MOUSE_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (num < 1 || num > 64 || pData == nullptr) {
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
||||||
|
|
||||||
|
if (handle == MOUSE1_HANDLE) {
|
||||||
|
if (!g_mouse1_open) {
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
} else if (handle == MOUSE2_HANDLE) {
|
||||||
|
if (!g_mouse2_open) {
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
// Mouse 2 will never be connected
|
||||||
|
pData[0] = OrbisMouseData{
|
||||||
|
.connected = false,
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return ORBIS_MOUSE_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mouse->m_connected) {
|
||||||
|
pData[0] = OrbisMouseData{
|
||||||
|
.connected = false,
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::MouseState states[64];
|
||||||
|
int ret_num = mouse->ReadStates(states, num);
|
||||||
|
|
||||||
for (int i = 0; i < ret_num; i++) {
|
for (int i = 0; i < ret_num; i++) {
|
||||||
pData[i].buttons = states[i].buttonsState;
|
const auto& s = states[i];
|
||||||
pData[i].connected = connected;
|
pData[i] = OrbisMouseData{
|
||||||
pData[i].timestamp = states[i].time;
|
.timestamp = s.time,
|
||||||
pData[i].xAxis = 0;
|
.connected = true,
|
||||||
pData[i].yAxis = 0;
|
.buttons = s.button_state,
|
||||||
pData[i].wheel = 0;
|
.xAxis = s.x_axis,
|
||||||
pData[i].tilt = 0;
|
.yAxis = s.y_axis,
|
||||||
|
.wheel = s.wheel,
|
||||||
|
.tilt = s.tilt,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return ret_num;
|
return ret_num;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,15 +23,18 @@ struct OrbisMouseData {
|
||||||
s32 yAxis;
|
s32 yAxis;
|
||||||
s32 wheel;
|
s32 wheel;
|
||||||
s32 tilt;
|
s32 tilt;
|
||||||
u8 reserve[8];
|
std::array<u8, 8> reserve{};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OrbisMouseButtonDataOffset {
|
enum OrbisMouseButtonDataOffset {
|
||||||
ORBIS_MOUSE_BUTTON_PRIMARY = 0x00000001,
|
ORBIS_MOUSE_BUTTON_PRIMARY = 0x00000001,
|
||||||
ORBIS_MOUSE_BUTTON_SECONDARY = 0x00000002
|
ORBIS_MOUSE_BUTTON_SECONDARY = 0x00000002,
|
||||||
|
ORBIS_MOUSE_BUTTON_OPTIONAL = 0x00000004,
|
||||||
|
ORBIS_MOUSE_BUTTON_OPTIONAL2 = 0x00000008,
|
||||||
|
ORBIS_MOUSE_BUTTON_OPTIONAL3 = 0x00000010,
|
||||||
};
|
};
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceMouseClose();
|
int PS4_SYSV_ABI sceMouseClose(s32 handle);
|
||||||
int PS4_SYSV_ABI sceMouseConnectPort();
|
int PS4_SYSV_ABI sceMouseConnectPort();
|
||||||
int PS4_SYSV_ABI sceMouseDebugGetDeviceId();
|
int PS4_SYSV_ABI sceMouseDebugGetDeviceId();
|
||||||
int PS4_SYSV_ABI sceMouseDeviceOpen();
|
int PS4_SYSV_ABI sceMouseDeviceOpen();
|
||||||
|
|
|
@ -12,8 +12,62 @@
|
||||||
|
|
||||||
namespace Libraries::Pad {
|
namespace Libraries::Pad {
|
||||||
|
|
||||||
|
static bool g_initialized = false;
|
||||||
|
|
||||||
|
static bool g_pad_standard_connected = false;
|
||||||
|
static bool g_pad_standard_special_connected = false;
|
||||||
|
|
||||||
|
constexpr auto PAD_STANDARD_HANDLER = 0xBC1;
|
||||||
|
constexpr auto PAD_SPECIAL_HANDLER = 0xBC2;
|
||||||
|
|
||||||
|
void OrbisPadData::CopyFromState(const Input::State& state) {
|
||||||
|
buttons = state.buttonsState;
|
||||||
|
leftStick.x = state.axes[static_cast<int>(Input::Axis::LeftX)];
|
||||||
|
leftStick.y = state.axes[static_cast<int>(Input::Axis::LeftY)];
|
||||||
|
rightStick.x = state.axes[static_cast<int>(Input::Axis::RightX)];
|
||||||
|
rightStick.y = state.axes[static_cast<int>(Input::Axis::RightY)];
|
||||||
|
analogButtons.l2 = state.axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
||||||
|
analogButtons.r2 = state.axes[static_cast<int>(Input::Axis::TriggerRight)];
|
||||||
|
orientation.x = 0.0f;
|
||||||
|
orientation.y = 0.0f;
|
||||||
|
orientation.z = 0.0f;
|
||||||
|
orientation.w = 1.0f;
|
||||||
|
acceleration.x = 0.0f;
|
||||||
|
acceleration.y = 0.0f;
|
||||||
|
acceleration.z = 0.0f;
|
||||||
|
angularVelocity.x = 0.0f;
|
||||||
|
angularVelocity.y = 0.0f;
|
||||||
|
angularVelocity.z = 0.0f;
|
||||||
|
touchData.touchNum = (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
|
||||||
|
touchData.touch[0].x = state.touchpad[0].x;
|
||||||
|
touchData.touch[0].y = state.touchpad[0].y;
|
||||||
|
touchData.touch[0].id = 1;
|
||||||
|
touchData.touch[1].x = state.touchpad[1].x;
|
||||||
|
touchData.touch[1].y = state.touchpad[1].y;
|
||||||
|
touchData.touch[1].id = 2;
|
||||||
|
connected = true;
|
||||||
|
timestamp = state.time;
|
||||||
|
connectedCount = 1;
|
||||||
|
deviceUniqueDataLen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadClose(s32 handle) {
|
int PS4_SYSV_ABI scePadClose(s32 handle) {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
g_pad_standard_connected = false;
|
||||||
|
}
|
||||||
|
if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
g_pad_standard_special_connected = false;
|
||||||
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,16 +78,135 @@ int PS4_SYSV_ABI scePadConnectPort() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadDeviceClassGetExtendedInformation(
|
int PS4_SYSV_ABI scePadDeviceClassGetExtendedInformation(
|
||||||
s32 handle, OrbisPadDeviceClassExtendedInformation* pExtInfo) {
|
s32 handle, OrbisPadDeviceClassExtendedInformation* pExtInfo) {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
||||||
if (Config::getUseSpecialPad()) {
|
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pExtInfo == nullptr) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
pExtInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD;
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
pExtInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass();
|
pExtInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass();
|
||||||
|
switch (pExtInfo->deviceClass) {
|
||||||
|
case ORBIS_PAD_DEVICE_CLASS_STEERING_WHEEL: {
|
||||||
|
auto& data = pExtInfo->classData.steeringWheel;
|
||||||
|
data.maxPhysicalWheelAngle = 360;
|
||||||
|
data.capability = 0b1110; // Handbrake, Shift, 3 pedals
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
memset(pExtInfo->classData.data, 0, sizeof(pExtInfo->classData.data));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadDeviceClassParseData(s32 handle, const OrbisPadData* pData,
|
int PS4_SYSV_ABI scePadDeviceClassParseData(s32 handle, const OrbisPadData* pData,
|
||||||
OrbisPadDeviceClassData* pDeviceClassData) {
|
OrbisPadDeviceClassData* pDeviceClassData) {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_TRACE(Lib_Pad, "called handle = {}", handle);
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
if (pData == nullptr || pDeviceClassData == nullptr) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
pDeviceClassData->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD;
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
auto pad_class = (OrbisPadDeviceClass)Config::getSpecialPadClass();
|
||||||
|
pDeviceClassData->deviceClass = pad_class;
|
||||||
|
switch (pad_class) {
|
||||||
|
case ORBIS_PAD_DEVICE_CLASS_GUITAR: {
|
||||||
|
LOG_ERROR(Lib_Pad, "(STUBBED) guitar not implemented");
|
||||||
|
auto& data = pDeviceClassData->classData.guitar;
|
||||||
|
// TODO implement guitar
|
||||||
|
} break;
|
||||||
|
case ORBIS_PAD_DEVICE_CLASS_DRUM: {
|
||||||
|
LOG_ERROR(Lib_Pad, "(STUBBED) drum not implemented");
|
||||||
|
auto& data = pDeviceClassData->classData.drum;
|
||||||
|
// TODO implement drum
|
||||||
|
} break;
|
||||||
|
case ORBIS_PAD_DEVICE_CLASS_STEERING_WHEEL: {
|
||||||
|
auto& data = pDeviceClassData->classData.steeringWheel;
|
||||||
|
// TODO proper implement steering wheel
|
||||||
|
auto& left_stick = pData->leftStick.x;
|
||||||
|
data.steeringWheelAngle = static_cast<float>(left_stick - 0x7F) / 127.0f * 180.0f;
|
||||||
|
if (data.steeringWheelAngle == 0.0) {
|
||||||
|
data.steeringWheel = 0x80;
|
||||||
|
} else {
|
||||||
|
data.steeringWheel =
|
||||||
|
static_cast<u16>((data.steeringWheelAngle / 360.0f + 0.5f) * 0xFFFF);
|
||||||
|
}
|
||||||
|
data.acceleratorPedal = static_cast<u16>(pData->analogButtons.r2) * 0x102;
|
||||||
|
data.brakePedal = static_cast<u16>(pData->analogButtons.l2) * 0x102;
|
||||||
|
data.clutchPedal = pData->buttons & ORBIS_PAD_BUTTON_L1 ? 0xFFFF : 0x0000;
|
||||||
|
data.handBrake = pData->buttons & ORBIS_PAD_BUTTON_R1 ? 0xFFFF : 0x0000;
|
||||||
|
|
||||||
|
static int gear = 1;
|
||||||
|
static bool switch_gear_up_pressed_last = false;
|
||||||
|
static bool switch_gear_down_pressed_last = false;
|
||||||
|
bool switch_gear_up_pressed = pData->buttons & ORBIS_PAD_BUTTON_SQUARE;
|
||||||
|
bool switch_gear_down_pressed = pData->buttons & ORBIS_PAD_BUTTON_CROSS;
|
||||||
|
if (switch_gear_up_pressed != switch_gear_up_pressed_last) {
|
||||||
|
switch_gear_up_pressed_last = switch_gear_up_pressed;
|
||||||
|
if (switch_gear_up_pressed) {
|
||||||
|
if (gear < 7) {
|
||||||
|
++gear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (switch_gear_down_pressed != switch_gear_down_pressed_last) {
|
||||||
|
switch_gear_down_pressed_last = switch_gear_down_pressed;
|
||||||
|
if (switch_gear_down_pressed) {
|
||||||
|
if (gear > 0) {
|
||||||
|
--gear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gear == 0) {
|
||||||
|
data.gear = 1 << 7;
|
||||||
|
} else {
|
||||||
|
data.gear = 1 << (gear - 1);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ORBIS_PAD_DEVICE_CLASS_FLIGHT_STICK: {
|
||||||
|
LOG_ERROR(Lib_Pad, "(STUBBED) flight stick not implemented");
|
||||||
|
auto& data = pDeviceClassData->classData.flightStick;
|
||||||
|
// TODO implement flight stick
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
pDeviceClassData->bDataValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,32 +262,39 @@ int PS4_SYSV_ABI scePadGetCapability() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerInformation* pInfo) {
|
int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerInformation* pInfo) {
|
||||||
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
||||||
if (handle < 0) {
|
|
||||||
pInfo->touchPadInfo.pixelDensity = 1;
|
if (!g_initialized) {
|
||||||
pInfo->touchPadInfo.resolution.x = 1920;
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
pInfo->touchPadInfo.resolution.y = 950;
|
|
||||||
pInfo->stickInfo.deadZoneLeft = 2;
|
|
||||||
pInfo->stickInfo.deadZoneRight = 2;
|
|
||||||
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD;
|
|
||||||
pInfo->connectedCount = 1;
|
|
||||||
pInfo->connected = false;
|
|
||||||
pInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD;
|
|
||||||
return SCE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
} else if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
pInfo->touchPadInfo.pixelDensity = 1;
|
pInfo->touchPadInfo.pixelDensity = 1;
|
||||||
pInfo->touchPadInfo.resolution.x = 1920;
|
pInfo->touchPadInfo.resolution.x = 1920;
|
||||||
pInfo->touchPadInfo.resolution.y = 950;
|
pInfo->touchPadInfo.resolution.y = 950;
|
||||||
pInfo->stickInfo.deadZoneLeft = 2;
|
pInfo->stickInfo.deadZoneLeft = 2;
|
||||||
pInfo->stickInfo.deadZoneRight = 2;
|
pInfo->stickInfo.deadZoneRight = 2;
|
||||||
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD;
|
pInfo->connectionType = 0; // Local connection
|
||||||
pInfo->connectedCount = 1;
|
pInfo->connectedCount = 1;
|
||||||
pInfo->connected = true;
|
pInfo->connected = true;
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
pInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD;
|
pInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD;
|
||||||
if (Config::getUseSpecialPad()) {
|
} else if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_SPECIAL;
|
|
||||||
pInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass();
|
pInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass();
|
||||||
|
} else {
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return SCE_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadGetDataInternal() {
|
int PS4_SYSV_ABI scePadGetDataInternal() {
|
||||||
|
@ -134,7 +314,7 @@ int PS4_SYSV_ABI scePadGetDeviceInfo() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadGetExtControllerInformation(s32 handle,
|
int PS4_SYSV_ABI scePadGetExtControllerInformation(s32 handle,
|
||||||
OrbisPadExtendedControllerInformation* pInfo) {
|
OrbisPadExtendedControllerInformation* pInfo) {
|
||||||
LOG_INFO(Lib_Pad, "called handle = {}", handle);
|
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
||||||
|
|
||||||
pInfo->padType1 = 0;
|
pInfo->padType1 = 0;
|
||||||
pInfo->padType2 = 0;
|
pInfo->padType2 = 0;
|
||||||
|
@ -200,7 +380,8 @@ int PS4_SYSV_ABI scePadGetVersionInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadInit() {
|
int PS4_SYSV_ABI scePadInit() {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_DEBUG(Lib_Pad, "called");
|
||||||
|
g_initialized = true;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,28 +426,40 @@ int PS4_SYSV_ABI scePadMbusTerm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam) {
|
int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam) {
|
||||||
LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index);
|
LOG_DEBUG(Lib_Pad, "Called user_id = {} type = {} index = {}", userId,
|
||||||
if (Config::getUseSpecialPad()) {
|
type == ORBIS_PAD_PORT_TYPE_STANDARD ? "standard"
|
||||||
if (type != ORBIS_PAD_PORT_TYPE_SPECIAL)
|
: type == ORBIS_PAD_PORT_TYPE_SPECIAL ? "special"
|
||||||
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
|
: "unknown",
|
||||||
} else {
|
index);
|
||||||
if (type != ORBIS_PAD_PORT_TYPE_STANDARD && type != ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL)
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
if (type == ORBIS_PAD_PORT_TYPE_STANDARD) {
|
||||||
|
if (g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_ALREADY_OPENED;
|
||||||
|
}
|
||||||
|
g_pad_standard_connected = true;
|
||||||
|
return PAD_STANDARD_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ORBIS_PAD_PORT_TYPE_SPECIAL) {
|
||||||
|
if (!Config::getUseSpecialPad()) {
|
||||||
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
|
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
return 1; // dummy
|
if (g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_ALREADY_OPENED;
|
||||||
|
}
|
||||||
|
g_pad_standard_special_connected = true;
|
||||||
|
return PAD_SPECIAL_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index,
|
int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index,
|
||||||
const OrbisPadOpenExtParam* pParam) {
|
const OrbisPadOpenExtParam* pParam) {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_DEBUG(Lib_Pad, "Redirecting call to scePadOpen");
|
||||||
if (Config::getUseSpecialPad()) {
|
return scePadOpen(userId, type, index, nullptr);
|
||||||
if (type != ORBIS_PAD_PORT_TYPE_SPECIAL)
|
|
||||||
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
} else {
|
|
||||||
if (type != ORBIS_PAD_PORT_TYPE_STANDARD && type != ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL)
|
|
||||||
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
return 1; // dummy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadOpenExt2() {
|
int PS4_SYSV_ABI scePadOpenExt2() {
|
||||||
|
@ -280,49 +473,80 @@ int PS4_SYSV_ABI scePadOutputReport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
||||||
|
LOG_TRACE(Lib_Pad, "called handle = {} num = {}", handle, num);
|
||||||
|
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 1 || num > 64) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack to copy state between pads
|
||||||
|
static bool connected = false;
|
||||||
|
static std::array<Input::State, 64> states;
|
||||||
|
static int state_count = 0;
|
||||||
|
static bool has_std_data = false;
|
||||||
|
static bool has_special_data = false;
|
||||||
|
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_special_data) {
|
||||||
int connected_count = 0;
|
int connected_count = 0;
|
||||||
bool connected = false;
|
|
||||||
Input::State states[64];
|
|
||||||
auto* controller = Common::Singleton<Input::GameController>::Instance();
|
auto* controller = Common::Singleton<Input::GameController>::Instance();
|
||||||
int ret_num = controller->ReadStates(states, num, &connected, &connected_count);
|
state_count = controller->ReadStates(states.data(), num, &connected, &connected_count);
|
||||||
|
has_std_data = true;
|
||||||
|
} else {
|
||||||
|
has_special_data = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
ret_num = 1;
|
pData[0] = OrbisPadData{
|
||||||
|
.connected = false,
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ret_num; i++) {
|
for (int i = 0; i < state_count; i++) {
|
||||||
pData[i].buttons = states[i].buttonsState;
|
pData[i].CopyFromState(states[i]);
|
||||||
pData[i].leftStick.x = states[i].axes[static_cast<int>(Input::Axis::LeftX)];
|
|
||||||
pData[i].leftStick.y = states[i].axes[static_cast<int>(Input::Axis::LeftY)];
|
|
||||||
pData[i].rightStick.x = states[i].axes[static_cast<int>(Input::Axis::RightX)];
|
|
||||||
pData[i].rightStick.y = states[i].axes[static_cast<int>(Input::Axis::RightY)];
|
|
||||||
pData[i].analogButtons.l2 = states[i].axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
|
||||||
pData[i].analogButtons.r2 = states[i].axes[static_cast<int>(Input::Axis::TriggerRight)];
|
|
||||||
pData[i].orientation.x = 0.0f;
|
|
||||||
pData[i].orientation.y = 0.0f;
|
|
||||||
pData[i].orientation.z = 0.0f;
|
|
||||||
pData[i].orientation.w = 1.0f;
|
|
||||||
pData[i].acceleration.x = 0.0f;
|
|
||||||
pData[i].acceleration.y = 0.0f;
|
|
||||||
pData[i].acceleration.z = 0.0f;
|
|
||||||
pData[i].angularVelocity.x = 0.0f;
|
|
||||||
pData[i].angularVelocity.y = 0.0f;
|
|
||||||
pData[i].angularVelocity.z = 0.0f;
|
|
||||||
pData[i].touchData.touchNum =
|
|
||||||
(states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0);
|
|
||||||
pData[i].touchData.touch[0].x = states[i].touchpad[0].x;
|
|
||||||
pData[i].touchData.touch[0].y = states[i].touchpad[0].y;
|
|
||||||
pData[i].touchData.touch[0].id = 1;
|
|
||||||
pData[i].touchData.touch[1].x = states[i].touchpad[1].x;
|
|
||||||
pData[i].touchData.touch[1].y = states[i].touchpad[1].y;
|
|
||||||
pData[i].touchData.touch[1].id = 2;
|
|
||||||
pData[i].connected = connected;
|
|
||||||
pData[i].timestamp = states[i].time;
|
|
||||||
pData[i].connectedCount = connected_count;
|
|
||||||
pData[i].deviceUniqueDataLen = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret_num;
|
return state_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_std_data) {
|
||||||
|
int connected_count = 0;
|
||||||
|
auto* controller = Common::Singleton<Input::GameController>::Instance();
|
||||||
|
state_count = controller->ReadStates(states.data(), num, &connected, &connected_count);
|
||||||
|
has_special_data = true;
|
||||||
|
} else {
|
||||||
|
has_std_data = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connected) {
|
||||||
|
pData[0] = OrbisPadData{
|
||||||
|
.connected = false,
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < state_count; i++) {
|
||||||
|
pData[i].CopyFromState(states[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadReadBlasterForTracker() {
|
int PS4_SYSV_ABI scePadReadBlasterForTracker() {
|
||||||
|
@ -346,42 +570,36 @@ int PS4_SYSV_ABI scePadReadHistory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
||||||
|
LOG_TRACE(Lib_Pad, "called handle = {}", handle);
|
||||||
|
|
||||||
|
if (!g_initialized) {
|
||||||
|
return ORBIS_PAD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == PAD_STANDARD_HANDLER) {
|
||||||
|
if (!g_pad_standard_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_handler:
|
||||||
auto* controller = Common::Singleton<Input::GameController>::Instance();
|
auto* controller = Common::Singleton<Input::GameController>::Instance();
|
||||||
int connectedCount = 0;
|
int connectedCount = 0;
|
||||||
bool isConnected = false;
|
bool isConnected = false;
|
||||||
Input::State state;
|
Input::State state;
|
||||||
controller->ReadState(&state, &isConnected, &connectedCount);
|
controller->ReadState(&state, &isConnected, &connectedCount);
|
||||||
pData->buttons = state.buttonsState;
|
|
||||||
pData->leftStick.x = state.axes[static_cast<int>(Input::Axis::LeftX)];
|
|
||||||
pData->leftStick.y = state.axes[static_cast<int>(Input::Axis::LeftY)];
|
|
||||||
pData->rightStick.x = state.axes[static_cast<int>(Input::Axis::RightX)];
|
|
||||||
pData->rightStick.y = state.axes[static_cast<int>(Input::Axis::RightY)];
|
|
||||||
pData->analogButtons.l2 = state.axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
|
||||||
pData->analogButtons.r2 = state.axes[static_cast<int>(Input::Axis::TriggerRight)];
|
|
||||||
pData->orientation.x = 0;
|
|
||||||
pData->orientation.y = 0;
|
|
||||||
pData->orientation.z = 0;
|
|
||||||
pData->orientation.w = 1;
|
|
||||||
pData->acceleration.x = 0.0f;
|
|
||||||
pData->acceleration.y = 0.0f;
|
|
||||||
pData->acceleration.z = 0.0f;
|
|
||||||
pData->angularVelocity.x = 0.0f;
|
|
||||||
pData->angularVelocity.y = 0.0f;
|
|
||||||
pData->angularVelocity.z = 0.0f;
|
|
||||||
pData->touchData.touchNum =
|
|
||||||
(state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
|
|
||||||
pData->touchData.touch[0].x = state.touchpad[0].x;
|
|
||||||
pData->touchData.touch[0].y = state.touchpad[0].y;
|
|
||||||
pData->touchData.touch[0].id = 1;
|
|
||||||
pData->touchData.touch[1].x = state.touchpad[1].x;
|
|
||||||
pData->touchData.touch[1].y = state.touchpad[1].y;
|
|
||||||
pData->touchData.touch[1].id = 2;
|
|
||||||
pData->timestamp = state.time;
|
|
||||||
pData->connected = true; // isConnected; //TODO fix me proper
|
|
||||||
pData->connectedCount = 1; // connectedCount;
|
|
||||||
pData->deviceUniqueDataLen = 0;
|
|
||||||
|
|
||||||
return SCE_OK;
|
pData->CopyFromState(state);
|
||||||
|
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
if (handle == PAD_SPECIAL_HANDLER) {
|
||||||
|
if (!g_pad_standard_special_connected) {
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
// TODO implement special pad
|
||||||
|
goto standard_handler;
|
||||||
|
}
|
||||||
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadReadStateExt() {
|
int PS4_SYSV_ABI scePadReadStateExt() {
|
||||||
|
|
|
@ -9,6 +9,10 @@ namespace Core::Loader {
|
||||||
class SymbolsResolver;
|
class SymbolsResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
struct State;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Libraries::Pad {
|
namespace Libraries::Pad {
|
||||||
|
|
||||||
constexpr int ORBIS_PAD_MAX_TOUCH_NUM = 2;
|
constexpr int ORBIS_PAD_MAX_TOUCH_NUM = 2;
|
||||||
|
@ -188,6 +192,8 @@ struct OrbisPadData {
|
||||||
u8 reserve[2];
|
u8 reserve[2];
|
||||||
u8 deviceUniqueDataLen;
|
u8 deviceUniqueDataLen;
|
||||||
u8 deviceUniqueData[ORBIS_PAD_MAX_DEVICE_UNIQUE_DATA_SIZE];
|
u8 deviceUniqueData[ORBIS_PAD_MAX_DEVICE_UNIQUE_DATA_SIZE];
|
||||||
|
|
||||||
|
void CopyFromState(const Input::State& state);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OrbisPadTouchPadInformation {
|
struct OrbisPadTouchPadInformation {
|
||||||
|
|
|
@ -238,11 +238,21 @@ void MsgDialogUi::Finish(ButtonId buttonId, Result r) {
|
||||||
}
|
}
|
||||||
if (status) {
|
if (status) {
|
||||||
*status = Status::FINISHED;
|
*status = Status::FINISHED;
|
||||||
|
if (callback.has_value()) {
|
||||||
|
callback.value()(DialogResult{
|
||||||
|
.result = r,
|
||||||
|
.buttonId = buttonId,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
state = nullptr;
|
state = nullptr;
|
||||||
status = nullptr;
|
status = nullptr;
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
RemoveLayer(this);
|
RemoveLayer(this);
|
||||||
|
if (self_destruct) {
|
||||||
|
self_destruct = false;
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MsgDialogUi::Draw() {
|
void MsgDialogUi::Draw() {
|
||||||
|
@ -282,19 +292,24 @@ void MsgDialogUi::Draw() {
|
||||||
first_render = false;
|
first_render = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogResult Libraries::MsgDialog::ShowMsgDialog(MsgDialogState p_state, bool block) {
|
void Libraries::MsgDialog::ShowMsgDialog(
|
||||||
static DialogResult result{};
|
MsgDialogState p_state, bool block, std::optional<std::function<void(DialogResult)>> callback) {
|
||||||
static Status status;
|
auto status = new Status{Status::RUNNING};
|
||||||
static MsgDialogUi dialog;
|
auto state = new MsgDialogState{std::move(p_state)};
|
||||||
static MsgDialogState state;
|
auto dialog = new MsgDialogUi(state, status, nullptr);
|
||||||
dialog = MsgDialogUi{};
|
bool running = true;
|
||||||
status = Status::RUNNING;
|
dialog->SetSelfDestruct();
|
||||||
state = std::move(p_state);
|
dialog->SetCallback([&, status, state, callback = std::move(callback)](auto result) {
|
||||||
dialog = MsgDialogUi(&state, &status, &result);
|
running = false;
|
||||||
|
delete status;
|
||||||
|
delete state;
|
||||||
|
if (callback.has_value()) {
|
||||||
|
callback.value()(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
if (block) {
|
if (block) {
|
||||||
while (status == Status::RUNNING) {
|
while (running) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@
|
||||||
#include "core/libraries/system/commondialog.h"
|
#include "core/libraries/system/commondialog.h"
|
||||||
#include "imgui/imgui_layer.h"
|
#include "imgui/imgui_layer.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace Libraries::MsgDialog {
|
namespace Libraries::MsgDialog {
|
||||||
|
|
||||||
using OrbisUserServiceUserId = s32;
|
using OrbisUserServiceUserId = s32;
|
||||||
|
@ -157,6 +160,10 @@ class MsgDialogUi final : public ImGui::Layer {
|
||||||
CommonDialog::Status* status{};
|
CommonDialog::Status* status{};
|
||||||
DialogResult* result{};
|
DialogResult* result{};
|
||||||
|
|
||||||
|
// HOST ONLY
|
||||||
|
bool self_destruct{false};
|
||||||
|
std::optional<std::function<void(DialogResult)>> callback;
|
||||||
|
|
||||||
void DrawUser();
|
void DrawUser();
|
||||||
void DrawProgressBar();
|
void DrawProgressBar();
|
||||||
void DrawSystemMessage();
|
void DrawSystemMessage();
|
||||||
|
@ -169,13 +176,22 @@ public:
|
||||||
MsgDialogUi(MsgDialogUi&& other) noexcept;
|
MsgDialogUi(MsgDialogUi&& other) noexcept;
|
||||||
MsgDialogUi& operator=(MsgDialogUi other);
|
MsgDialogUi& operator=(MsgDialogUi other);
|
||||||
|
|
||||||
|
void SetSelfDestruct() {
|
||||||
|
self_destruct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCallback(std::function<void(DialogResult)> callback) {
|
||||||
|
this->callback = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK);
|
void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK);
|
||||||
|
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility function to show a message dialog
|
// Utility function to show a message dialog from host code
|
||||||
// !!! This function can block !!!
|
// callback is called from the present thread
|
||||||
DialogResult ShowMsgDialog(MsgDialogState state, bool block = true);
|
void ShowMsgDialog(MsgDialogState state, bool block = false,
|
||||||
|
std::optional<std::function<void(DialogResult)>> callback = std::nullopt);
|
||||||
|
|
||||||
}; // namespace Libraries::MsgDialog
|
}; // namespace Libraries::MsgDialog
|
|
@ -83,7 +83,7 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
|
||||||
StyleColorsDark();
|
StyleColorsDark();
|
||||||
|
|
||||||
::Core::Devtools::Layer::SetupSettings();
|
::Core::Devtools::Layer::SetupSettings();
|
||||||
Sdl::Init(window.GetSdlWindow());
|
Sdl::Init(&window);
|
||||||
|
|
||||||
const Vulkan::InitInfo vk_info{
|
const Vulkan::InitInfo vk_info{
|
||||||
.instance = instance.GetInstance(),
|
.instance = instance.GetInstance(),
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
// SDL
|
// SDL
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "sdl_window.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,6 +26,9 @@ namespace ImGui::Sdl {
|
||||||
|
|
||||||
// SDL Data
|
// SDL Data
|
||||||
struct SdlData {
|
struct SdlData {
|
||||||
|
// SDL Wrapper
|
||||||
|
const Frontend::WindowSDL* wrapper{};
|
||||||
|
|
||||||
SDL_Window* window{};
|
SDL_Window* window{};
|
||||||
SDL_WindowID window_id{};
|
SDL_WindowID window_id{};
|
||||||
Uint64 time{};
|
Uint64 time{};
|
||||||
|
@ -501,7 +507,7 @@ static void SetupPlatformHandles(ImGuiViewport* viewport, SDL_Window* window) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(SDL_Window* window) {
|
bool Init(const Frontend::WindowSDL* wrapper) {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||||
|
@ -514,8 +520,9 @@ bool Init(SDL_Window* window) {
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests
|
||||||
// (optional, rarely used)
|
// (optional, rarely used)
|
||||||
|
|
||||||
bd->window = window;
|
bd->wrapper = wrapper;
|
||||||
bd->window_id = SDL_GetWindowID(window);
|
bd->window = wrapper->GetSdlWindow();
|
||||||
|
bd->window_id = SDL_GetWindowID(bd->window);
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
platform_io.Platform_SetClipboardTextFn = SetClipboardText;
|
platform_io.Platform_SetClipboardTextFn = SetClipboardText;
|
||||||
|
@ -543,7 +550,7 @@ bool Init(SDL_Window* window) {
|
||||||
// Set platform dependent data in viewport
|
// Set platform dependent data in viewport
|
||||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
SetupPlatformHandles(main_viewport, window);
|
SetupPlatformHandles(main_viewport, bd->window);
|
||||||
|
|
||||||
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't
|
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't
|
||||||
// emit the event. Without this, when clicking to gain focus, our widgets wouldn't activate even
|
// emit the event. Without this, when clicking to gain focus, our widgets wouldn't activate even
|
||||||
|
@ -593,7 +600,6 @@ static void UpdateMouseData() {
|
||||||
// (below)
|
// (below)
|
||||||
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries
|
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries
|
||||||
// shouldn't e.g. trigger other operations outside
|
// shouldn't e.g. trigger other operations outside
|
||||||
SDL_CaptureMouse((bd->mouse_buttons_down != 0) ? true : false);
|
|
||||||
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||||
const bool is_app_focused = (bd->window == focused_window);
|
const bool is_app_focused = (bd->window == focused_window);
|
||||||
|
|
||||||
|
@ -662,9 +668,11 @@ static void UpdateMouseCursor() {
|
||||||
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
|
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
|
||||||
bd->mouse_last_cursor = expected_cursor;
|
bd->mouse_last_cursor = expected_cursor;
|
||||||
}
|
}
|
||||||
|
if (!bd->wrapper->isCapturingMouse()) {
|
||||||
SDL_ShowCursor();
|
SDL_ShowCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void CloseGamepads() {
|
static void CloseGamepads() {
|
||||||
SdlData* bd = GetBackendData();
|
SdlData* bd = GetBackendData();
|
||||||
|
|
|
@ -10,9 +10,13 @@ struct SDL_Renderer;
|
||||||
struct SDL_Gamepad;
|
struct SDL_Gamepad;
|
||||||
typedef union SDL_Event SDL_Event;
|
typedef union SDL_Event SDL_Event;
|
||||||
|
|
||||||
|
namespace Frontend {
|
||||||
|
class WindowSDL;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ImGui::Sdl {
|
namespace ImGui::Sdl {
|
||||||
|
|
||||||
bool Init(SDL_Window* window);
|
bool Init(const Frontend::WindowSDL* window);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void NewFrame();
|
void NewFrame();
|
||||||
bool ProcessEvent(const SDL_Event* event);
|
bool ProcessEvent(const SDL_Event* event);
|
||||||
|
|
|
@ -11,70 +11,71 @@ GameMouse::GameMouse() {
|
||||||
m_last_state = MouseState();
|
m_last_state = MouseState();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GameMouse::ReadStates(MouseState* states, int states_num, bool* isConnected) {
|
int GameMouse::ReadStates(MouseState* states, int states_num) {
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
*isConnected = m_connected;
|
const u32 count = std::min(m_states_num, u32(states_num));
|
||||||
|
|
||||||
int ret_num = 0;
|
u32 begin = (m_index - m_states_num + 1) % MAX_MOUSE_STATES;
|
||||||
|
for (u32 i = 0; i < count; i++) {
|
||||||
if (m_connected) {
|
u32 idx = (begin + i) % MAX_MOUSE_STATES;
|
||||||
if (m_states_num == 0) {
|
states[i] = m_states[idx];
|
||||||
ret_num = 1;
|
|
||||||
states[0] = m_last_state;
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < m_states_num; i++) {
|
|
||||||
if (ret_num >= states_num) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto index = (m_first_state + i) % MAX_MOUSE_STATES;
|
|
||||||
if (!m_private[index].obtained) {
|
|
||||||
m_private[index].obtained = true;
|
|
||||||
|
|
||||||
states[ret_num++] = m_states[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret_num;
|
m_states_num -= count;
|
||||||
}
|
return static_cast<int>(count);
|
||||||
|
|
||||||
MouseState GameMouse::GetLastState() const {
|
|
||||||
if (m_states_num == 0) {
|
|
||||||
return m_last_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto last = (m_first_state + m_states_num - 1) % MAX_MOUSE_STATES;
|
|
||||||
|
|
||||||
return m_states[last];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMouse::AddState(const MouseState& state) {
|
void GameMouse::AddState(const MouseState& state) {
|
||||||
if (m_states_num >= MAX_MOUSE_STATES) {
|
|
||||||
m_states_num = MAX_MOUSE_STATES - 1;
|
|
||||||
m_first_state = (m_first_state + 1) % MAX_MOUSE_STATES;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = (m_first_state + m_states_num) % MAX_MOUSE_STATES;
|
|
||||||
|
|
||||||
m_states[index] = state;
|
|
||||||
m_last_state = state;
|
|
||||||
m_private[index].obtained = false;
|
|
||||||
m_states_num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameMouse::CheckButton(int id, u32 button, bool isPressed) {
|
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
auto state = GetLastState();
|
|
||||||
|
m_index = (m_index + 1) % MAX_MOUSE_STATES;
|
||||||
|
if (m_states_num < MAX_MOUSE_STATES) {
|
||||||
|
++m_states_num;
|
||||||
|
}
|
||||||
|
m_states[m_index] = state;
|
||||||
|
m_last_state = MouseState{
|
||||||
|
.button_state = state.button_state,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMouse::CheckButton(u32 button, bool isPressed) {
|
||||||
|
if (!m_connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MouseState state = m_last_state;
|
||||||
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
state.buttonsState |= button;
|
state.button_state |= button;
|
||||||
} else {
|
} else {
|
||||||
state.buttonsState &= ~button;
|
state.button_state &= ~button;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddState(state);
|
AddState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameMouse::CheckMove(int x, int y) {
|
||||||
|
if (!m_connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MouseState state = m_last_state;
|
||||||
|
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||||
|
state.x_axis = x;
|
||||||
|
state.y_axis = y;
|
||||||
|
|
||||||
|
AddState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMouse::CheckWheel(int x, int y) {
|
||||||
|
if (!m_connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MouseState state = m_last_state;
|
||||||
|
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||||
|
state.wheel = y;
|
||||||
|
state.tilt = x;
|
||||||
|
|
||||||
|
AddState(state);
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace Input
|
}; // namespace Input
|
||||||
|
|
|
@ -8,8 +8,12 @@
|
||||||
namespace Input {
|
namespace Input {
|
||||||
|
|
||||||
struct MouseState {
|
struct MouseState {
|
||||||
u32 buttonsState = 0;
|
|
||||||
u64 time = 0;
|
u64 time = 0;
|
||||||
|
u32 button_state = 0;
|
||||||
|
s32 x_axis = 0;
|
||||||
|
s32 y_axis = 0;
|
||||||
|
s32 wheel = 0;
|
||||||
|
s32 tilt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr u32 MAX_MOUSE_STATES = 64;
|
constexpr u32 MAX_MOUSE_STATES = 64;
|
||||||
|
@ -19,25 +23,23 @@ public:
|
||||||
GameMouse();
|
GameMouse();
|
||||||
virtual ~GameMouse() = default;
|
virtual ~GameMouse() = default;
|
||||||
|
|
||||||
int ReadStates(MouseState* states, int states_num, bool* isConnected);
|
int ReadStates(MouseState* states, int states_num);
|
||||||
MouseState GetLastState() const;
|
|
||||||
void CheckButton(int id, u32 button, bool isPressed);
|
void CheckButton(u32 button, bool isPressed);
|
||||||
void AddState(const MouseState& state);
|
void CheckMove(int x, int y);
|
||||||
|
void CheckWheel(int x, int y);
|
||||||
|
|
||||||
|
bool m_connected = false;
|
||||||
|
float speed = 1.0f;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct StateInternal {
|
void AddState(const MouseState& state);
|
||||||
bool obtained = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
bool m_connected = true;
|
|
||||||
MouseState m_last_state;
|
MouseState m_last_state;
|
||||||
int m_connected_count = 0;
|
|
||||||
u32 m_states_num = 0;
|
u32 m_states_num = 0;
|
||||||
u32 m_first_state = 0;
|
u32 m_index = 0;
|
||||||
std::array<MouseState, MAX_MOUSE_STATES> m_states;
|
std::array<MouseState, MAX_MOUSE_STATES> m_states;
|
||||||
std::array<StateInternal, MAX_MOUSE_STATES> m_private;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Input
|
} // namespace Input
|
|
@ -118,8 +118,10 @@ void WindowSDL::waitEvent() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
onMouseAction(&event);
|
onMouseAction(&event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -127,19 +129,50 @@ void WindowSDL::waitEvent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void WindowSDL::onMouseAction(const SDL_Event* event) {
|
void WindowSDL::onMouseAction(const SDL_Event* event) {
|
||||||
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
auto& mouse = *Common::Singleton<Input::GameMouse>::Instance();
|
||||||
using Libraries::Mouse::OrbisMouseButtonDataOffset;
|
|
||||||
u32 button = 0;
|
if (mouse.m_connected && !is_capturing_mouse) {
|
||||||
switch (event->button.button) {
|
SDL_SetWindowRelativeMouseMode(window, true);
|
||||||
case SDL_BUTTON_LEFT:
|
is_capturing_mouse = true;
|
||||||
button = OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_PRIMARY;
|
} else if (!mouse.m_connected && is_capturing_mouse) {
|
||||||
break;
|
SDL_SetWindowRelativeMouseMode(window, false);
|
||||||
case SDL_BUTTON_RIGHT:
|
is_capturing_mouse = false;
|
||||||
button = OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_SECONDARY;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (button != 0) {
|
|
||||||
mouse->CheckButton(0, button, event->type == SDL_EVENT_MOUSE_BUTTON_DOWN);
|
bool pressed_down = false;
|
||||||
|
switch (event->type) {
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
pressed_down = true;
|
||||||
|
[[fallthrough]];
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
|
using Libraries::Mouse::OrbisMouseButtonDataOffset;
|
||||||
|
|
||||||
|
auto btn = event->button.button;
|
||||||
|
if (btn < 1 || btn > 5) { // 1..5 range
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
constexpr static std::array sdl_to_orbis_buttons = {
|
||||||
|
static_cast<OrbisMouseButtonDataOffset>(0x00),
|
||||||
|
OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_PRIMARY,
|
||||||
|
OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_OPTIONAL,
|
||||||
|
OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_SECONDARY,
|
||||||
|
OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_OPTIONAL2,
|
||||||
|
OrbisMouseButtonDataOffset::ORBIS_MOUSE_BUTTON_OPTIONAL3,
|
||||||
|
};
|
||||||
|
mouse.CheckButton(sdl_to_orbis_buttons[btn], pressed_down);
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_MOTION: {
|
||||||
|
const auto x = static_cast<int>(event->motion.xrel * mouse.speed);
|
||||||
|
const auto y = static_cast<int>(event->motion.yrel * mouse.speed);
|
||||||
|
mouse.CheckMove(x, y);
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_WHEEL: {
|
||||||
|
const auto x = static_cast<int>(event->wheel.x);
|
||||||
|
const auto y = static_cast<int>(event->wheel.y);
|
||||||
|
mouse.CheckWheel(x, y);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void WindowSDL::onResize() {
|
void WindowSDL::onResize() {
|
||||||
|
|
|
@ -58,6 +58,10 @@ public:
|
||||||
return is_open;
|
return is_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCapturingMouse() const {
|
||||||
|
return is_capturing_mouse;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] SDL_Window* GetSdlWindow() const {
|
[[nodiscard]] SDL_Window* GetSdlWindow() const {
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +87,8 @@ private:
|
||||||
SDL_Window* window{};
|
SDL_Window* window{};
|
||||||
bool is_shown{};
|
bool is_shown{};
|
||||||
bool is_open{true};
|
bool is_open{true};
|
||||||
|
|
||||||
|
bool is_capturing_mouse{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Frontend
|
} // namespace Frontend
|
||||||
|
|
Loading…
Reference in a new issue