add keyboard navigation support.

This commit is contained in:
ITotalJustice
2025-09-18 17:06:22 +01:00
parent a2300c1a96
commit a6265c3089
3 changed files with 142 additions and 4 deletions

View File

@@ -267,6 +267,7 @@ public:
PadState m_pad{}; PadState m_pad{};
TouchInfo m_touch_info{}; TouchInfo m_touch_info{};
Controller m_controller{}; Controller m_controller{};
KeyboardState m_keyboard{};
std::vector<ThemeMeta> m_theme_meta_entries; std::vector<ThemeMeta> m_theme_meta_entries;
Vec2 m_scale{1, 1}; Vec2 m_scale{1, 1};

View File

@@ -366,6 +366,81 @@ struct Action final {
std::string m_hint{}; std::string m_hint{};
}; };
struct GenericHidState {
GenericHidState() {
Reset();
}
void Reset() {
buttons_cur = 0;
buttons_old = 0;
}
u64 GetButtons() const {
return buttons_cur;
}
u64 GetButtonsDown() const {
return buttons_cur & ~buttons_old;
}
u64 GetButtonsUp() const {
return ~buttons_cur & buttons_old;
}
virtual void Update() = 0;
protected:
u64 buttons_cur;
u64 buttons_old;
};
struct KeyboardState final : GenericHidState {
struct MapEntry {
HidKeyboardKey key;
u64 button;
};
using Map = std::span<const MapEntry>;
void Init(Map map) {
m_map = map;
Reset();
}
void Update() override {
buttons_old = buttons_cur;
buttons_cur = 0;
if (!hidGetKeyboardStates(&m_state, 1)) {
return;
}
const auto ctrl = m_state.modifiers & HidKeyboardModifier_Control;
const auto shift = m_state.modifiers & HidKeyboardModifier_Shift;
for (const auto& map : m_map) {
if (hidKeyboardStateGetKey(&m_state, map.key)) {
if (shift && map.button == static_cast<u64>(Button::L)) {
buttons_cur |= static_cast<u64>(Button::L2);
} else if (shift && map.button == static_cast<u64>(Button::R)) {
buttons_cur |= static_cast<u64>(Button::R2);
} else if (ctrl && map.button == static_cast<u64>(Button::L)) {
buttons_cur |= static_cast<u64>(Button::L3);
} else if (ctrl && map.button == static_cast<u64>(Button::R)) {
buttons_cur |= static_cast<u64>(Button::R3);
} else {
buttons_cur |= map.button;
}
}
}
}
private:
Map m_map{};
HidKeyboardState m_state{};
};
struct Controller { struct Controller {
u64 m_kdown{}; u64 m_kdown{};
u64 m_kheld{}; u64 m_kheld{};

View File

@@ -74,6 +74,37 @@ struct NszOption {
const char* name; const char* name;
}; };
constexpr KeyboardState::MapEntry KEYBOARD_BUTTON_MAP[] = {
{HidKeyboardKey_UpArrow, static_cast<u64>(Button::DPAD_UP)},
{HidKeyboardKey_DownArrow, static_cast<u64>(Button::DPAD_DOWN)},
{HidKeyboardKey_LeftArrow, static_cast<u64>(Button::DPAD_LEFT)},
{HidKeyboardKey_RightArrow, static_cast<u64>(Button::DPAD_RIGHT)},
{HidKeyboardKey_W, static_cast<u64>(Button::DPAD_UP)},
{HidKeyboardKey_S, static_cast<u64>(Button::DPAD_DOWN)},
{HidKeyboardKey_A, static_cast<u64>(Button::DPAD_LEFT)},
{HidKeyboardKey_D, static_cast<u64>(Button::DPAD_RIGHT)},
// options (may swap).
{HidKeyboardKey_X, static_cast<u64>(Button::Y)},
{HidKeyboardKey_Z, static_cast<u64>(Button::X)},
// menus.
{HidKeyboardKey_Q, static_cast<u64>(Button::L)},
{HidKeyboardKey_E, static_cast<u64>(Button::R)},
// select and back.
{HidKeyboardKey_Return, static_cast<u64>(Button::A)},
{HidKeyboardKey_Space, static_cast<u64>(Button::A)},
{HidKeyboardKey_Backspace, static_cast<u64>(Button::B)},
// exit.
{HidKeyboardKey_Escape, static_cast<u64>(Button::START)},
// idk what this should map to.
{HidKeyboardKey_R, static_cast<u64>(Button::SELECT)},
};
constexpr NszOption NSZ_COMPRESS_LEVEL_OPTIONS[] = { constexpr NszOption NSZ_COMPRESS_LEVEL_OPTIONS[] = {
{ .value = 0, .name = "Level 0 (no compression)" }, { .value = 0, .name = "Level 0 (no compression)" },
{ .value = 1, .name = "Level 1" }, { .value = 1, .name = "Level 1" },
@@ -1026,6 +1057,16 @@ void App::Poll() {
hidGetTouchScreenStates(&state, 1); hidGetTouchScreenStates(&state, 1);
m_touch_info.is_clicked = false; m_touch_info.is_clicked = false;
// todo:
#if 0
HidMouseState mouse_state{};
hidGetMouseStates(&mouse_state, 1);
if (mouse_state.buttons) {
log_write("[MOUSE] buttons: 0x%X x: %d y: %d dx: %d dy: %d wx: %d wy: %d\n", mouse_state.buttons, mouse_state.x, mouse_state.y, mouse_state.delta_x, mouse_state.delta_y, mouse_state.wheel_delta_x, mouse_state.wheel_delta_y);
}
#endif
// todo: replace old touch code with gestures from below // todo: replace old touch code with gestures from below
#if 0 #if 0
static HidGestureState prev_gestures[17]{}; static HidGestureState prev_gestures[17]{};
@@ -1071,6 +1112,7 @@ void App::Poll() {
memcpy(prev_gestures, gestures, sizeof(gestures)); memcpy(prev_gestures, gestures, sizeof(gestures));
#endif #endif
// todo: support mouse scroll / touch.
if (state.count == 1 && !m_touch_info.is_touching) { if (state.count == 1 && !m_touch_info.is_touching) {
m_touch_info.initial = m_touch_info.cur = state.touches[0]; m_touch_info.initial = m_touch_info.cur = state.touches[0];
m_touch_info.is_touching = true; m_touch_info.is_touching = true;
@@ -1094,14 +1136,29 @@ void App::Poll() {
} }
} }
u64 kdown = 0;
u64 kup = 0;
u64 kheld = 0;
// todo: better implement this to match hos // todo: better implement this to match hos
if (!m_touch_info.is_touching && !m_touch_info.is_clicked) { if (!m_touch_info.is_touching && !m_touch_info.is_clicked) {
// controller.
padUpdate(&m_pad); padUpdate(&m_pad);
m_controller.m_kdown = padGetButtonsDown(&m_pad); kdown |= padGetButtonsDown(&m_pad);
m_controller.m_kheld = padGetButtons(&m_pad); kheld |= padGetButtons(&m_pad);
m_controller.m_kup = padGetButtonsUp(&m_pad); kup |= padGetButtonsUp(&m_pad);
m_controller.UpdateButtonHeld(static_cast<u64>(Button::ANY_DIRECTION), m_delta_time);
// keyboard.
m_keyboard.Update();
kdown |= m_keyboard.GetButtonsDown();
kheld |= m_keyboard.GetButtons();
kup |= m_keyboard.GetButtonsUp();
} }
m_controller.m_kdown = kdown;
m_controller.m_kheld = kheld;
m_controller.m_kup = kup;
m_controller.UpdateButtonHeld(static_cast<u64>(Button::ANY_DIRECTION), m_delta_time);
} }
void App::Update() { void App::Update() {
@@ -1683,9 +1740,14 @@ App::App(const char* argv0) {
SCOPED_TIMESTAMP("HID init"); SCOPED_TIMESTAMP("HID init");
hidInitializeTouchScreen(); hidInitializeTouchScreen();
hidInitializeGesture(); hidInitializeGesture();
hidInitializeKeyboard();
hidInitializeMouse();
padConfigureInput(8, HidNpadStyleSet_NpadStandard); padConfigureInput(8, HidNpadStyleSet_NpadStandard);
// padInitializeDefault(&m_pad); // padInitializeDefault(&m_pad);
padInitializeAny(&m_pad); padInitializeAny(&m_pad);
m_keyboard.Init(KEYBOARD_BUTTON_MAP);
} }
{ {