mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-08 16:01:19 +12:00
Use unordered_map for keydown to allow codes above 255 (#248)
- Adds internal support for 32bit key codes, required for proper keyboard input on Linux - Use gdk_keyval_name to get key name on Linux
This commit is contained in:
parent
5e968eff4f
commit
9f02733a0d
14 changed files with 143 additions and 83 deletions
|
@ -15,8 +15,10 @@ const ControllerState& ControllerBase::update_state()
|
|||
ControllerState result = raw_state();
|
||||
|
||||
// ignore default buttons
|
||||
result.buttons &= ~m_default_state.buttons;
|
||||
|
||||
for (auto&& el : m_default_state.buttons)
|
||||
{
|
||||
result.buttons[el.first] = result.buttons[el.first] && !el.second;
|
||||
}
|
||||
// apply deadzone and range and ignore default axis values
|
||||
apply_axis_setting(result.axis, m_default_state.axis, m_settings.axis);
|
||||
apply_axis_setting(result.rotation, m_default_state.rotation, m_settings.rotation);
|
||||
|
@ -24,22 +26,22 @@ const ControllerState& ControllerBase::update_state()
|
|||
|
||||
#define APPLY_AXIS_BUTTON(_axis_, _flag_) \
|
||||
if (result._axis_.x < -ControllerState::kAxisThreshold) \
|
||||
result.buttons.set((_flag_) + (kAxisXN - kAxisXP)); \
|
||||
result.buttons[(_flag_) + (kAxisXN - kAxisXP)]=true; \
|
||||
else if (result._axis_.x > ControllerState::kAxisThreshold) \
|
||||
result.buttons.set((_flag_)); \
|
||||
result.buttons[(_flag_)]=true; \
|
||||
if (result._axis_.y < -ControllerState::kAxisThreshold) \
|
||||
result.buttons.set((_flag_) + 1 + (kAxisXN - kAxisXP)); \
|
||||
result.buttons[(_flag_) + 1 + (kAxisXN - kAxisXP)]=true; \
|
||||
else if (result._axis_.y > ControllerState::kAxisThreshold) \
|
||||
result.buttons.set((_flag_) + 1);
|
||||
result.buttons[(_flag_) + 1]=true;
|
||||
|
||||
if (result.axis.x < -ControllerState::kAxisThreshold)
|
||||
result.buttons.set((kAxisXP) + (kAxisXN - kAxisXP));
|
||||
result.buttons[(kAxisXP) + (kAxisXN - kAxisXP)]=true;
|
||||
else if (result.axis.x > ControllerState::kAxisThreshold)
|
||||
result.buttons.set((kAxisXP));
|
||||
result.buttons[(kAxisXP)]=true;
|
||||
if (result.axis.y < -ControllerState::kAxisThreshold)
|
||||
result.buttons.set((kAxisXP) + 1 + (kAxisXN - kAxisXP));
|
||||
result.buttons[(kAxisXP) + 1 + (kAxisXN - kAxisXP)]=true;
|
||||
else if (result.axis.y > ControllerState::kAxisThreshold)
|
||||
result.buttons.set((kAxisXP) + 1);;
|
||||
result.buttons[(kAxisXP) + 1]=true;
|
||||
APPLY_AXIS_BUTTON(rotation, kRotationXP);
|
||||
APPLY_AXIS_BUTTON(trigger, kTriggerXP);
|
||||
|
||||
|
@ -68,7 +70,7 @@ const ControllerState& ControllerBase::update_state()
|
|||
|
||||
#undef APPLY_AXIS_BUTTON
|
||||
|
||||
m_last_state = result;
|
||||
m_last_state = std::move(result);
|
||||
return m_last_state;
|
||||
}
|
||||
|
||||
|
@ -127,7 +129,8 @@ bool ControllerBase::operator==(const ControllerBase& c) const
|
|||
|
||||
float ControllerBase::get_axis_value(uint64 button) const
|
||||
{
|
||||
if (m_last_state.buttons.test(button))
|
||||
auto buttonState=m_last_state.buttons.find(button);
|
||||
if (buttonState!=m_last_state.buttons.end() && buttonState->second)
|
||||
{
|
||||
if (button <= kButtonNoneAxisMAX || !has_axis())
|
||||
return 1.0f;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
struct ControllerState
|
||||
|
@ -18,7 +17,7 @@ struct ControllerState
|
|||
glm::vec2 rotation{ };
|
||||
glm::vec2 trigger{ };
|
||||
|
||||
std::bitset<256> buttons{};
|
||||
std::unordered_map<uint32, bool> buttons{};
|
||||
|
||||
uint64 last_state = 0;
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ ControllerState DSUController::raw_state()
|
|||
{
|
||||
if (HAS_BIT(state.data.state1, i))
|
||||
{
|
||||
result.buttons.set(bitindex);
|
||||
result.buttons[bitindex]=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,12 +145,12 @@ ControllerState DSUController::raw_state()
|
|||
{
|
||||
if (HAS_BIT(state.data.state2, i))
|
||||
{
|
||||
result.buttons.set(bitindex);
|
||||
result.buttons[bitindex]=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.data.touch)
|
||||
result.buttons.set(kButton16);
|
||||
result.buttons[kButton16]=true;
|
||||
|
||||
result.axis.x = (float)state.data.lx / std::numeric_limits<uint8>::max();
|
||||
result.axis.x = (result.axis.x * 2.0f) - 1.0f;
|
||||
|
|
|
@ -278,7 +278,7 @@ ControllerState DirectInputController::raw_state()
|
|||
{
|
||||
if (HAS_BIT(state.rgbButtons[i], 7))
|
||||
{
|
||||
result.buttons.set(i);
|
||||
result.buttons[i]=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,19 +316,19 @@ ControllerState DirectInputController::raw_state()
|
|||
{
|
||||
switch (pov)
|
||||
{
|
||||
case 0: result.buttons.set(kButtonUp);
|
||||
case 0: result.buttons[kButtonUp]=true;
|
||||
break;
|
||||
case 4500: result.buttons.set(kButtonUp); // up + right
|
||||
case 9000: result.buttons.set(kButtonRight);
|
||||
case 4500: result.buttons[kButtonUp]=true; // up + right
|
||||
case 9000: result.buttons[kButtonRight]=true;
|
||||
break;
|
||||
case 13500: result.buttons.set(kButtonRight); // right + down
|
||||
case 18000: result.buttons.set(kButtonDown);
|
||||
case 13500: result.buttons[kButtonRight] = true; // right + down
|
||||
case 18000: result.buttons[kButtonDown] = true;
|
||||
break;
|
||||
case 22500: result.buttons.set(kButtonDown); // down + left
|
||||
case 27000: result.buttons.set(kButtonLeft);
|
||||
case 22500: result.buttons[kButtonDown] = true; // down + left
|
||||
case 27000: result.buttons[kButtonLeft] = true;
|
||||
break;
|
||||
case 31500: result.buttons.set(kButtonLeft);; // left + up
|
||||
result.buttons.set(kButtonUp); // left + up
|
||||
case 31500: result.buttons[kButtonLeft] = true; // left + up
|
||||
result.buttons[kButtonUp] = true; // left + up
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,9 +35,13 @@ std::string KeyboardController::get_button_name(uint64 button) const
|
|||
char key_name[128];
|
||||
if (GetKeyNameTextA(scan_code, key_name, std::size(key_name)) != 0)
|
||||
return key_name;
|
||||
#endif
|
||||
|
||||
else
|
||||
return fmt::format("key_{}", button);
|
||||
#elif BOOST_OS_LINUX
|
||||
return gui_gtkRawKeyCodeToString(button);
|
||||
#else
|
||||
return fmt::format("key_{}", button);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern WindowInfo g_window_info;
|
||||
|
@ -47,20 +51,7 @@ ControllerState KeyboardController::raw_state()
|
|||
ControllerState result{};
|
||||
if (g_window_info.app_active)
|
||||
{
|
||||
static_assert(result.buttons.size() == std::size(g_window_info.keydown), "invalid size");
|
||||
for (uint32 i = wxKeyCode::WXK_BACK; i < result.buttons.size(); ++i)
|
||||
{
|
||||
if(const bool v = g_window_info.keydown[i])
|
||||
{
|
||||
result.buttons.set(i, v);
|
||||
}
|
||||
}
|
||||
// ignore generic key codes on Windows when there is also a left/right variant
|
||||
#if BOOST_OS_WINDOWS
|
||||
result.buttons.set(VK_SHIFT, false);
|
||||
result.buttons.set(VK_CONTROL, false);
|
||||
result.buttons.set(VK_MENU, false);
|
||||
#endif
|
||||
g_window_info.get_keystates(result.buttons);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ ControllerState SDLController::raw_state()
|
|||
{
|
||||
if (m_buttons[i] && SDL_GameControllerGetButton(m_controller, (SDL_GameControllerButton)i))
|
||||
{
|
||||
result.buttons.set(i);
|
||||
result.buttons[i]=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -206,23 +206,26 @@ ControllerState NativeWiimoteController::raw_state()
|
|||
return result;
|
||||
|
||||
const auto state = m_provider->get_state(m_index);
|
||||
result.buttons = state.buttons;
|
||||
for (int i = 0; i < std::numeric_limits<uint16>::digits; i++)
|
||||
result.buttons[i] = state.buttons & (1<<i);
|
||||
|
||||
if (std::holds_alternative<NunchuckData>(state.m_extension))
|
||||
{
|
||||
const auto nunchuck = std::get<NunchuckData>(state.m_extension);
|
||||
if (nunchuck.c)
|
||||
result.buttons.set(kWiimoteButton_C);
|
||||
result.buttons[kWiimoteButton_C]=true;
|
||||
|
||||
if (nunchuck.z)
|
||||
result.buttons.set(kWiimoteButton_Z);
|
||||
result.buttons[kWiimoteButton_Z]=true;
|
||||
|
||||
result.axis = nunchuck.axis;
|
||||
}
|
||||
else if (std::holds_alternative<ClassicData>(state.m_extension))
|
||||
{
|
||||
const auto classic = std::get<ClassicData>(state.m_extension);
|
||||
result.buttons |= (uint64)classic.buttons << kHighestWiimote;
|
||||
uint64 buttons = (uint64)classic.buttons << kHighestWiimote;
|
||||
for (int i = 0; i < std::numeric_limits<uint64>::digits; i++)
|
||||
result.buttons[i] = result.buttons[i] || (buttons & (1 << i));
|
||||
|
||||
result.axis = classic.left_axis;
|
||||
result.rotation = classic.right_axis;
|
||||
|
|
|
@ -120,7 +120,8 @@ ControllerState XInputController::raw_state()
|
|||
}
|
||||
|
||||
// Buttons
|
||||
result.buttons = state.Gamepad.wButtons;
|
||||
for(int i=0;i<std::numeric_limits<WORD>::digits;i++)
|
||||
result.buttons[i] = state.Gamepad.wButtons & (1<<i);
|
||||
|
||||
if (state.Gamepad.sThumbLX > 0)
|
||||
result.axis.x = (float)state.Gamepad.sThumbLX / std::numeric_limits<sint16>::max();
|
||||
|
|
|
@ -280,7 +280,9 @@ bool EmulatedController::is_mapping_down(uint64 mapping) const
|
|||
if (it != m_mappings.cend())
|
||||
{
|
||||
if (const auto controller = it->second.controller.lock()) {
|
||||
return controller->get_state().buttons.test(it->second.button);
|
||||
auto& buttons=controller->get_state().buttons;
|
||||
auto buttonState=buttons.find(it->second.button);
|
||||
return buttonState!=buttons.end() && buttonState->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue