mirror of https://github.com/AxioDL/metaforce.git
Add initial rumble support, use modified SDL branch to support all GC controller rumble modes
This commit is contained in:
parent
c679c2e0f8
commit
40669f4dc9
|
@ -10,11 +10,13 @@ namespace metaforce {
|
||||||
struct SAuroraControllerState {
|
struct SAuroraControllerState {
|
||||||
u32 m_which = -1;
|
u32 m_which = -1;
|
||||||
bool m_isGamecube = false;
|
bool m_isGamecube = false;
|
||||||
|
bool m_hasRumble = false;
|
||||||
std::array<int16_t, size_t(aurora::ControllerAxis::MAX)> m_axes{};
|
std::array<int16_t, size_t(aurora::ControllerAxis::MAX)> m_axes{};
|
||||||
std::bitset<size_t(aurora::ControllerButton::MAX)> m_btns{};
|
std::bitset<size_t(aurora::ControllerButton::MAX)> m_btns{};
|
||||||
|
|
||||||
SAuroraControllerState() = default;
|
SAuroraControllerState() = default;
|
||||||
SAuroraControllerState(uint32_t which, bool isGamecube) : m_which(which), m_isGamecube(isGamecube) {}
|
SAuroraControllerState(uint32_t which, bool isGamecube, bool hasRumble)
|
||||||
|
: m_which(which), m_isGamecube(isGamecube), m_hasRumble(hasRumble) {}
|
||||||
void clamp();
|
void clamp();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,8 +84,9 @@ struct CFinalInput {
|
||||||
u32 m_which = -1;
|
u32 m_which = -1;
|
||||||
|
|
||||||
CFinalInput();
|
CFinalInput();
|
||||||
// CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
// CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float
|
||||||
// float rightDiv);
|
// leftDiv,
|
||||||
|
// float rightDiv);
|
||||||
CFinalInput(int cIdx, float dt, const SAuroraControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
CFinalInput(int cIdx, float dt, const SAuroraControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
||||||
float rightDiv);
|
float rightDiv);
|
||||||
CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput);
|
CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput);
|
||||||
|
|
|
@ -45,7 +45,8 @@ void CInputGenerator::controllerAdded(uint32_t which) noexcept {
|
||||||
aurora::set_controller_player_index(which, 0);
|
aurora::set_controller_player_index(which, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_state[player] = SAuroraControllerState(which, aurora::is_controller_gamecube(which));
|
m_state[player] =
|
||||||
|
SAuroraControllerState(which, aurora::is_controller_gamecube(which), aurora::controller_has_rumble(which));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputGenerator::controllerRemoved(uint32_t which) noexcept {
|
void CInputGenerator::controllerRemoved(uint32_t which) noexcept {
|
||||||
|
@ -93,6 +94,18 @@ void CInputGenerator::controllerAxis(uint32_t which, aurora::ControllerAxis axis
|
||||||
m_state[player].m_axes[size_t(axis)] = value;
|
m_state[player].m_axes[size_t(axis)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInputGenerator::SetMotorState(EIOPort port, EMotorState state) {
|
||||||
|
if (m_state[size_t(port)].m_hasRumble && m_state[size_t(port)].m_isGamecube) {
|
||||||
|
if (state == EMotorState::Rumble) {
|
||||||
|
aurora::controller_rumble(m_state[size_t(port)].m_which, 1, 1);
|
||||||
|
} else if (state == EMotorState::Stop) {
|
||||||
|
aurora::controller_rumble(m_state[size_t(port)].m_which, 0, 1);
|
||||||
|
} else if (state == EMotorState::StopHard) {
|
||||||
|
aurora::controller_rumble(m_state[size_t(port)].m_which, 0, 0);
|
||||||
|
}
|
||||||
|
} // TODO: Figure out good intensity values for generic controllers with rumble, support HAPTIC?
|
||||||
|
}
|
||||||
|
|
||||||
const CFinalInput& CInputGenerator::getFinalInput(unsigned int idx, float dt) {
|
const CFinalInput& CInputGenerator::getFinalInput(unsigned int idx, float dt) {
|
||||||
auto input = CFinalInput(idx, dt, m_data, m_lastUpdate);
|
auto input = CFinalInput(idx, dt, m_data, m_lastUpdate);
|
||||||
// Merge controller input with kb/m input
|
// Merge controller input with kb/m input
|
||||||
|
|
|
@ -152,11 +152,11 @@ public:
|
||||||
// if (smashAdapter.get() == device)
|
// if (smashAdapter.get() == device)
|
||||||
// smashAdapter.reset();
|
// smashAdapter.reset();
|
||||||
// }
|
// }
|
||||||
void SetMotorState(EIOPort port, EMotorState state) {
|
void SetMotorState(EIOPort port, EMotorState state);
|
||||||
// TODO aurora
|
|
||||||
}
|
|
||||||
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
|
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
|
||||||
// TODO aurora
|
for (u32 i = 0; i <= size_t(EIOPort::Three); ++i ) {
|
||||||
|
SetMotorState(EIOPort(i), states[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is where the game thread enters */
|
/* This is where the game thread enters */
|
||||||
|
|
|
@ -247,5 +247,7 @@ void set_fullscreen(bool fullscreen) noexcept;
|
||||||
[[nodiscard]] int32_t get_controller_player_index(uint32_t which) noexcept;
|
[[nodiscard]] int32_t get_controller_player_index(uint32_t which) noexcept;
|
||||||
void set_controller_player_index(uint32_t which, int32_t index) noexcept;
|
void set_controller_player_index(uint32_t which, int32_t index) noexcept;
|
||||||
[[nodiscard]] bool is_controller_gamecube(uint32_t which) noexcept;
|
[[nodiscard]] bool is_controller_gamecube(uint32_t which) noexcept;
|
||||||
|
[[nodiscard]] bool controller_has_rumble(uint32_t which) noexcept;
|
||||||
|
void controller_rumble(uint32_t which, uint16_t low_freq_intensity, uint16_t high_freq_intensity, uint32_t duration_ms = 0) noexcept;
|
||||||
[[nodiscard]] std::string get_controller_name(uint32_t which) noexcept;
|
[[nodiscard]] std::string get_controller_name(uint32_t which) noexcept;
|
||||||
} // namespace aurora
|
} // namespace aurora
|
||||||
|
|
|
@ -393,17 +393,19 @@ void set_fullscreen(bool fullscreen) noexcept {
|
||||||
SDL_SetWindowFullscreen(g_Window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
|
SDL_SetWindowFullscreen(g_Window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t get_controller_player_index(uint32_t which) noexcept {
|
int32_t get_controller_player_index(uint32_t instance) noexcept { return input::player_index(instance); }
|
||||||
return input::player_index(which);
|
|
||||||
|
void set_controller_player_index(uint32_t instance, int32_t index) noexcept {
|
||||||
|
input::set_player_index(instance, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_controller_player_index(uint32_t which, int32_t index) noexcept { input::set_player_index(which, index); }
|
bool is_controller_gamecube(uint32_t instance) noexcept { return input::is_gamecube(instance); }
|
||||||
|
|
||||||
bool is_controller_gamecube(uint32_t which) noexcept {
|
bool controller_has_rumble(uint32_t instance) noexcept { return input::controller_has_rumble(instance); }
|
||||||
return input::is_gamecube(which);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_controller_name(uint32_t instance) noexcept {
|
void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity,
|
||||||
return input::controller_name(instance);
|
uint32_t duration_ms) noexcept {
|
||||||
|
input::controller_rumble(instance, low_freq_intensity, high_freq_intensity, duration_ms);
|
||||||
}
|
}
|
||||||
|
std::string get_controller_name(uint32_t instance) noexcept { return input::controller_name(instance); }
|
||||||
} // namespace aurora
|
} // namespace aurora
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
|
#include <SDL_haptic.h>
|
||||||
|
|
||||||
namespace aurora::input {
|
namespace aurora::input {
|
||||||
struct GameController {
|
struct GameController {
|
||||||
SDL_GameController* m_controller;
|
SDL_GameController* m_controller = nullptr;
|
||||||
bool m_isGameCube = false;
|
bool m_isGameCube = false;
|
||||||
Sint32 m_index;
|
Sint32 m_index = -1;
|
||||||
|
bool m_hasRumble = false;
|
||||||
};
|
};
|
||||||
std::unordered_map<Uint32, GameController> g_GameControllers;
|
std::unordered_map<Uint32, GameController> g_GameControllers;
|
||||||
|
|
||||||
Sint32 add_controller(Uint32 which) {
|
Sint32 add_controller(Sint32 which) noexcept {
|
||||||
auto* ctrl = SDL_GameControllerOpen(which);
|
auto* ctrl = SDL_GameControllerOpen(which);
|
||||||
if (ctrl != nullptr) {
|
if (ctrl != nullptr) {
|
||||||
GameController controller;
|
GameController controller;
|
||||||
|
@ -16,7 +18,7 @@ Sint32 add_controller(Uint32 which) {
|
||||||
controller.m_index = which;
|
controller.m_index = which;
|
||||||
controller.m_isGameCube =
|
controller.m_isGameCube =
|
||||||
SDL_GameControllerGetVendor(ctrl) == 0x057E && SDL_GameControllerGetProduct(ctrl) == 0x0337;
|
SDL_GameControllerGetVendor(ctrl) == 0x057E && SDL_GameControllerGetProduct(ctrl) == 0x0337;
|
||||||
|
controller.m_hasRumble = (SDL_GameControllerHasRumble(ctrl) != 0u);
|
||||||
Sint32 instance = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl));
|
Sint32 instance = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl));
|
||||||
g_GameControllers[instance] = controller;
|
g_GameControllers[instance] = controller;
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -25,44 +27,60 @@ Sint32 add_controller(Uint32 which) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_controller(Uint32 which) {
|
void remove_controller(Uint32 instance) noexcept {
|
||||||
if (g_GameControllers.find(which) != g_GameControllers.end()) {
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
SDL_GameControllerClose(g_GameControllers[which].m_controller);
|
SDL_GameControllerClose(g_GameControllers[instance].m_controller);
|
||||||
g_GameControllers.erase(which);
|
g_GameControllers.erase(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_gamecube(Uint32 which) {
|
bool is_gamecube(Uint32 instance) noexcept {
|
||||||
if (g_GameControllers.find(which) != g_GameControllers.end()) {
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
return g_GameControllers[which].m_isGameCube;
|
return g_GameControllers[instance].m_isGameCube;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t player_index(Uint32 which) {
|
int32_t player_index(Uint32 instance) noexcept {
|
||||||
if (g_GameControllers.find(which) != g_GameControllers.end()) {
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
return SDL_GameControllerGetPlayerIndex(g_GameControllers[which].m_controller);
|
return SDL_GameControllerGetPlayerIndex(g_GameControllers[instance].m_controller);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_player_index(Uint32 which, Sint32 index) {
|
void set_player_index(Uint32 instance, Sint32 index) noexcept {
|
||||||
if (g_GameControllers.find(which) != g_GameControllers.end()) {
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
SDL_GameControllerSetPlayerIndex(g_GameControllers[which].m_controller, index);
|
SDL_GameControllerSetPlayerIndex(g_GameControllers[instance].m_controller, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string controller_name(Uint32 which) {
|
std::string controller_name(Uint32 instance) noexcept {
|
||||||
if (g_GameControllers.find(which) != g_GameControllers.end()) {
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
auto* name = SDL_GameControllerName(g_GameControllers[which].m_controller);
|
const auto* name = SDL_GameControllerName(g_GameControllers[instance].m_controller);
|
||||||
if (name) {
|
if (name != nullptr) {
|
||||||
return std::string(name);
|
return {name};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerButton translate_controller_button(SDL_GameControllerButton btn) {
|
bool controller_has_rumble(Uint32 instance) noexcept {
|
||||||
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
|
return g_GameControllers[instance].m_hasRumble;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity,
|
||||||
|
uint16_t duration_ms) noexcept {
|
||||||
|
|
||||||
|
if (g_GameControllers.find(instance) != g_GameControllers.end()) {
|
||||||
|
SDL_GameControllerRumble(g_GameControllers[instance].m_controller, low_freq_intensity, high_freq_intensity,
|
||||||
|
duration_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControllerButton translate_controller_button(SDL_GameControllerButton btn) noexcept {
|
||||||
switch (btn) {
|
switch (btn) {
|
||||||
case SDL_CONTROLLER_BUTTON_A:
|
case SDL_CONTROLLER_BUTTON_A:
|
||||||
return ControllerButton::A;
|
return ControllerButton::A;
|
||||||
|
@ -99,7 +117,7 @@ ControllerButton translate_controller_button(SDL_GameControllerButton btn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) {
|
ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) noexcept {
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||||
return ControllerAxis::LeftX;
|
return ControllerAxis::LeftX;
|
||||||
|
@ -118,7 +136,7 @@ ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym) {
|
char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym) noexcept {
|
||||||
specialSym = SpecialKey::None;
|
specialSym = SpecialKey::None;
|
||||||
modifierSym = ModifierKey::None;
|
modifierSym = ModifierKey::None;
|
||||||
if (sym.sym >= SDLK_F1 && sym.sym <= SDLK_F12) {
|
if (sym.sym >= SDLK_F1 && sym.sym <= SDLK_F12) {
|
||||||
|
@ -171,7 +189,7 @@ char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifier
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifierKey translate_modifiers(Uint16 mods) {
|
ModifierKey translate_modifiers(Uint16 mods) noexcept {
|
||||||
ModifierKey ret = ModifierKey::None;
|
ModifierKey ret = ModifierKey::None;
|
||||||
if ((mods & SDLK_LSHIFT) != 0) {
|
if ((mods & SDLK_LSHIFT) != 0) {
|
||||||
ret |= ModifierKey::LeftShift;
|
ret |= ModifierKey::LeftShift;
|
||||||
|
@ -195,7 +213,7 @@ ModifierKey translate_modifiers(Uint16 mods) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseButton translate_mouse_button(Uint8 button) {
|
MouseButton translate_mouse_button(Uint8 button) noexcept {
|
||||||
if (button == 1) {
|
if (button == 1) {
|
||||||
return MouseButton::Primary;
|
return MouseButton::Primary;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +233,7 @@ MouseButton translate_mouse_button(Uint8 button) {
|
||||||
return MouseButton::None;
|
return MouseButton::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseButton translate_mouse_button_state(Uint8 state) {
|
MouseButton translate_mouse_button_state(Uint8 state) noexcept {
|
||||||
auto ret = MouseButton::None;
|
auto ret = MouseButton::None;
|
||||||
if ((state & 0x01) != 0) {
|
if ((state & 0x01) != 0) {
|
||||||
ret |= MouseButton::Primary;
|
ret |= MouseButton::Primary;
|
||||||
|
|
|
@ -7,16 +7,19 @@
|
||||||
#include "SDL_keycode.h"
|
#include "SDL_keycode.h"
|
||||||
#include "SDL_mouse.h"
|
#include "SDL_mouse.h"
|
||||||
namespace aurora::input {
|
namespace aurora::input {
|
||||||
Sint32 add_controller(Uint32 which);
|
Sint32 add_controller(Sint32 which) noexcept;
|
||||||
void remove_controller(Uint32 which);
|
void remove_controller(Uint32 instance) noexcept;
|
||||||
Sint32 player_index(Uint32 which);
|
Sint32 player_index(Uint32 instance) noexcept;
|
||||||
void set_player_index(Uint32 which, Sint32 index);
|
void set_player_index(Uint32 instance, Sint32 index) noexcept;
|
||||||
std::string controller_name(Uint32 which);
|
std::string controller_name(Uint32 instance) noexcept;
|
||||||
bool is_gamecube(Uint32 which);
|
bool is_gamecube(Uint32 instance) noexcept;
|
||||||
ControllerButton translate_controller_button(SDL_GameControllerButton button);
|
bool controller_has_rumble(Uint32 instance) noexcept;
|
||||||
ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis);
|
void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity,
|
||||||
char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym);
|
uint16_t duration_ms) noexcept;
|
||||||
ModifierKey translate_modifiers(Uint16 mods);
|
ControllerButton translate_controller_button(SDL_GameControllerButton button) noexcept;
|
||||||
MouseButton translate_mouse_button(Uint8 button);
|
ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) noexcept;
|
||||||
MouseButton translate_mouse_button_state(Uint8 state);
|
char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym) noexcept;
|
||||||
}
|
ModifierKey translate_modifiers(Uint16 mods) noexcept;
|
||||||
|
MouseButton translate_mouse_button(Uint8 button) noexcept;
|
||||||
|
MouseButton translate_mouse_button_state(Uint8 state) noexcept;
|
||||||
|
} // namespace aurora::input
|
|
@ -1 +1 @@
|
||||||
Subproject commit 53091e36a3b418e33133bae2f018954c006f86b8
|
Subproject commit b1fafe65d63a947d262e750afccbc6eee28cace1
|
Loading…
Reference in New Issue