Browse Source
frontend/input_interpreter: Add InputInterpreter API
frontend/input_interpreter: Add InputInterpreter API
The InputInterpreter class interfaces with HID to retrieve button press states. Input is intended to be polled every 50ms so that a button is considered to be held down after 400ms has elapsed since the initial button press and subsequent repeated presses occur every 50ms. Co-authored-by: Chloe <25727384+ogniK5377@users.noreply.github.com>nce_cpp
3 changed files with 167 additions and 0 deletions
-
2src/core/CMakeLists.txt
-
45src/core/frontend/input_interpreter.cpp
-
120src/core/frontend/input_interpreter.h
@ -0,0 +1,45 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "core/core.h"
|
||||
|
#include "core/frontend/input_interpreter.h"
|
||||
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||
|
#include "core/hle/service/hid/hid.h"
|
||||
|
#include "core/hle/service/sm/sm.h"
|
||||
|
|
||||
|
InputInterpreter::InputInterpreter(Core::System& system) |
||||
|
: npad{system.ServiceManager() |
||||
|
.GetService<Service::HID::Hid>("hid") |
||||
|
->GetAppletResource() |
||||
|
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {} |
||||
|
|
||||
|
InputInterpreter::~InputInterpreter() = default; |
||||
|
|
||||
|
void InputInterpreter::PollInput() { |
||||
|
const u32 button_state = npad.GetAndResetPressState(); |
||||
|
|
||||
|
previous_index = current_index; |
||||
|
current_index = (current_index + 1) % button_states.size(); |
||||
|
|
||||
|
button_states[current_index] = button_state; |
||||
|
} |
||||
|
|
||||
|
bool InputInterpreter::IsButtonPressedOnce(HIDButton button) const { |
||||
|
const bool current_press = |
||||
|
(button_states[current_index] & (1U << static_cast<u8>(button))) != 0; |
||||
|
const bool previous_press = |
||||
|
(button_states[previous_index] & (1U << static_cast<u8>(button))) != 0; |
||||
|
|
||||
|
return current_press && !previous_press; |
||||
|
} |
||||
|
|
||||
|
bool InputInterpreter::IsButtonHeld(HIDButton button) const { |
||||
|
u32 held_buttons{button_states[0]}; |
||||
|
|
||||
|
for (std::size_t i = 1; i < button_states.size(); ++i) { |
||||
|
held_buttons &= button_states[i]; |
||||
|
} |
||||
|
|
||||
|
return (held_buttons & (1U << static_cast<u8>(button))) != 0; |
||||
|
} |
||||
@ -0,0 +1,120 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Core { |
||||
|
class System; |
||||
|
} |
||||
|
|
||||
|
namespace Service::HID { |
||||
|
class Controller_NPad; |
||||
|
} |
||||
|
|
||||
|
enum class HIDButton : u8 { |
||||
|
A, |
||||
|
B, |
||||
|
X, |
||||
|
Y, |
||||
|
LStick, |
||||
|
RStick, |
||||
|
L, |
||||
|
R, |
||||
|
ZL, |
||||
|
ZR, |
||||
|
Plus, |
||||
|
Minus, |
||||
|
|
||||
|
DLeft, |
||||
|
DUp, |
||||
|
DRight, |
||||
|
DDown, |
||||
|
|
||||
|
LStickLeft, |
||||
|
LStickUp, |
||||
|
LStickRight, |
||||
|
LStickDown, |
||||
|
|
||||
|
RStickLeft, |
||||
|
RStickUp, |
||||
|
RStickRight, |
||||
|
RStickDown, |
||||
|
|
||||
|
LeftSL, |
||||
|
LeftSR, |
||||
|
|
||||
|
RightSL, |
||||
|
RightSR, |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* The InputInterpreter class interfaces with HID to retrieve button press states. |
||||
|
* Input is intended to be polled every 50ms so that a button is considered to be |
||||
|
* held down after 400ms has elapsed since the initial button press and subsequent |
||||
|
* repeated presses occur every 50ms. |
||||
|
*/ |
||||
|
class InputInterpreter { |
||||
|
public: |
||||
|
explicit InputInterpreter(Core::System& system); |
||||
|
virtual ~InputInterpreter(); |
||||
|
|
||||
|
/// Gets a button state from HID and inserts it into the array of button states. |
||||
|
void PollInput(); |
||||
|
|
||||
|
/** |
||||
|
* The specified button is considered to be pressed once |
||||
|
* if it is currently pressed and not pressed previously. |
||||
|
* |
||||
|
* @param button The button to check. |
||||
|
* |
||||
|
* @returns True when the button is pressed once. |
||||
|
*/ |
||||
|
[[nodiscard]] bool IsButtonPressedOnce(HIDButton button) const; |
||||
|
|
||||
|
/** |
||||
|
* Checks whether any of the buttons in the parameter list is pressed once. |
||||
|
* |
||||
|
* @tparam HIDButton The buttons to check. |
||||
|
* |
||||
|
* @returns True when at least one of the buttons is pressed once. |
||||
|
*/ |
||||
|
template <HIDButton... T> |
||||
|
[[nodiscard]] bool IsAnyButtonPressedOnce() { |
||||
|
return (IsButtonPressedOnce(T) || ...); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* The specified button is considered to be held down if it is pressed in all 9 button states. |
||||
|
* |
||||
|
* @param button The button to check. |
||||
|
* |
||||
|
* @returns True when the button is held down. |
||||
|
*/ |
||||
|
[[nodiscard]] bool IsButtonHeld(HIDButton button) const; |
||||
|
|
||||
|
/** |
||||
|
* Checks whether any of the buttons in the parameter list is held down. |
||||
|
* |
||||
|
* @tparam HIDButton The buttons to check. |
||||
|
* |
||||
|
* @returns True when at least one of the buttons is held down. |
||||
|
*/ |
||||
|
template <HIDButton... T> |
||||
|
[[nodiscard]] bool IsAnyButtonHeld() { |
||||
|
return (IsButtonHeld(T) || ...); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
Service::HID::Controller_NPad& npad; |
||||
|
|
||||
|
/// Stores 9 consecutive button states polled from HID. |
||||
|
std::array<u32, 9> button_states{}; |
||||
|
|
||||
|
std::size_t previous_index{}; |
||||
|
std::size_t current_index{}; |
||||
|
}; |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue