From f82418724834cae980d4dd8f7c08a1999e283971 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Wed, 1 Jan 2025 17:32:58 +0000 Subject: [PATCH] initial work on touch support list of things not done: - no scrolling - only some menus - no widgets - no buttons --- sphaira/include/ui/types.hpp | 32 ++++++---------------------- sphaira/include/ui/widget.hpp | 2 ++ sphaira/source/app.cpp | 27 +++++++++-------------- sphaira/source/ui/menus/appstore.cpp | 21 ++++++++++++++++++ sphaira/source/ui/menus/homebrew.cpp | 21 ++++++++++++++++++ sphaira/source/ui/menus/themezer.cpp | 30 ++++++++++++++++++++++++++ sphaira/source/ui/widget.cpp | 11 ++++++++++ 7 files changed, 101 insertions(+), 43 deletions(-) diff --git a/sphaira/include/ui/types.hpp b/sphaira/include/ui/types.hpp index caa7cfd..2788fb8 100644 --- a/sphaira/include/ui/types.hpp +++ b/sphaira/include/ui/types.hpp @@ -196,39 +196,19 @@ struct Theme { fs::FsPath path; PLSR_BFSTM music; ElementEntry elements[ThemeEntryID_MAX]; - - // NVGcolor background; // bg - // NVGcolor lines; // grid lines - // NVGcolor spacer; // lines in popup box - // NVGcolor text; // text colour - // NVGcolor text_info; // description text - NVGcolor selected; // selected colours - // NVGcolor overlay; // popup overlay colour - - // void DrawElement(float x, float y, float w, float h, ThemeEntryID id); -}; - -enum class TouchState { - Start, // set when touch has started - Touching, // set when touch is held longer than 1 frame - Stop, // set after touch is released - None, // set when there is no touch }; struct TouchInfo { - s32 initial_x; - s32 initial_y; + HidTouchState initial; + HidTouchState cur; - s32 cur_x; - s32 cur_y; - - s32 prev_x; - s32 prev_y; - - u32 finger_id; + auto in_range(s32 x, s32 y, s32 w, s32 h) const -> bool { + return cur.x >= x && cur.x <= x + w && cur.y >= y && cur.y <= y + h; + } bool is_touching; bool is_tap; + bool is_clicked; }; enum class Button : u64 { diff --git a/sphaira/include/ui/widget.hpp b/sphaira/include/ui/widget.hpp index 9f1bc32..974ed05 100644 --- a/sphaira/include/ui/widget.hpp +++ b/sphaira/include/ui/widget.hpp @@ -49,6 +49,8 @@ struct Widget : public Object { m_actions.clear(); } + auto FireAction(Button button, u8 type = ActionType::DOWN) -> bool; + void SetPop(bool pop = true) { m_pop = pop; } diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index b8c702e..601d831 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -707,34 +707,27 @@ void App::Poll() { m_controller.m_kup = padGetButtonsUp(&m_pad); m_controller.UpdateButtonHeld(static_cast(Button::ANY_DIRECTION)); - HidTouchScreenState touch_state{}; - hidGetTouchScreenStates(&touch_state, 1); + HidTouchScreenState state{}; + hidGetTouchScreenStates(&state, 1); + m_touch_info.is_clicked = false; - if (touch_state.count == 1 && !m_touch_info.is_touching) { - m_touch_info.initial_x = m_touch_info.prev_x = m_touch_info.cur_x = touch_state.touches[0].x; - m_touch_info.initial_y = m_touch_info.prev_y = m_touch_info.cur_y = touch_state.touches[0].y; - m_touch_info.finger_id = touch_state.touches[0].finger_id; + if (state.count == 1 && !m_touch_info.is_touching) { + m_touch_info.initial = m_touch_info.cur = state.touches[0]; m_touch_info.is_touching = true; m_touch_info.is_tap = true; // PlaySoundEffect(SoundEffect_Limit); - } else if (touch_state.count >= 1 && m_touch_info.is_touching && m_touch_info.finger_id == touch_state.touches[0].finger_id) { - m_touch_info.prev_x = m_touch_info.cur_x; - m_touch_info.prev_y = m_touch_info.cur_y; - - m_touch_info.cur_x = touch_state.touches[0].x; - m_touch_info.cur_y = touch_state.touches[0].y; + } else if (state.count >= 1 && m_touch_info.is_touching) { + m_touch_info.cur = state.touches[0]; if (m_touch_info.is_tap && - (std::abs(m_touch_info.initial_x - m_touch_info.cur_x) > 20 || - std::abs(m_touch_info.initial_y - m_touch_info.cur_y) > 20)) { + (std::abs((s32)m_touch_info.initial.x - (s32)m_touch_info.cur.x) > 20 || + std::abs((s32)m_touch_info.initial.y - (s32)m_touch_info.cur.y) > 20)) { m_touch_info.is_tap = false; } } else if (m_touch_info.is_touching) { m_touch_info.is_touching = false; - - // check if we clicked on anything, if so, handle it if (m_touch_info.is_tap) { - // todo: + m_touch_info.is_clicked = true; } } } diff --git a/sphaira/source/ui/menus/appstore.cpp b/sphaira/source/ui/menus/appstore.cpp index 123af1a..76292fe 100644 --- a/sphaira/source/ui/menus/appstore.cpp +++ b/sphaira/source/ui/menus/appstore.cpp @@ -1014,6 +1014,27 @@ Menu::~Menu() { void Menu::Update(Controller* controller, TouchInfo* touch) { MenuBase::Update(controller, touch); + + const u64 SCROLL = m_start; + const u64 max_entry_display = 9; + const u64 nro_total = m_entries.size(); + const u64 cursor_pos = m_index; + + if (touch->is_clicked) { + for (u64 i = 0, pos = SCROLL, y = 110, w = 370, h = 155; pos < nro_total && i < max_entry_display; y += h + 10) { + for (u64 j = 0, x = 75; j < 3 && pos < nro_total && i < max_entry_display; j++, i++, pos++, x += w + 10) { + if (touch->in_range(x, y, w, h)) { + if (pos == m_index) { + FireAction(Button::A); + } else { + App::PlaySoundEffect(SoundEffect_Focus); + SetIndex(pos); + } + break; + } + } + } + } } void Menu::Draw(NVGcontext* vg, Theme* theme) { diff --git a/sphaira/source/ui/menus/homebrew.cpp b/sphaira/source/ui/menus/homebrew.cpp index 5ec0f1e..c875f63 100644 --- a/sphaira/source/ui/menus/homebrew.cpp +++ b/sphaira/source/ui/menus/homebrew.cpp @@ -153,6 +153,27 @@ Menu::~Menu() { void Menu::Update(Controller* controller, TouchInfo* touch) { MenuBase::Update(controller, touch); + + const u64 SCROLL = m_start; + const u64 max_entry_display = 9; + const u64 nro_total = m_entries.size(); + const u64 cursor_pos = m_index; + + if (touch->is_clicked) { + for (u64 i = 0, pos = SCROLL, y = 110, w = 370, h = 155; pos < nro_total && i < max_entry_display; y += h + 10) { + for (u64 j = 0, x = 75; j < 3 && pos < nro_total && i < max_entry_display; j++, i++, pos++, x += w + 10) { + if (touch->in_range(x, y, w, h)) { + if (pos == m_index) { + FireAction(Button::A); + } else { + App::PlaySoundEffect(SoundEffect_Focus); + SetIndex(pos); + } + break; + } + } + } + } } void Menu::Draw(NVGcontext* vg, Theme* theme) { diff --git a/sphaira/source/ui/menus/themezer.cpp b/sphaira/source/ui/menus/themezer.cpp index 4647274..1e4efd0 100644 --- a/sphaira/source/ui/menus/themezer.cpp +++ b/sphaira/source/ui/menus/themezer.cpp @@ -553,6 +553,36 @@ Menu::~Menu() { void Menu::Update(Controller* controller, TouchInfo* touch) { MenuBase::Update(controller, touch); + + if (m_pages.empty()) { + return; + } + + const auto& page = m_pages[m_page_index]; + if (page.m_ready != PageLoadState::Done) { + return; + } + + const u64 SCROLL = m_start; + const u64 max_entry_display = 9; + const u64 nro_total = page.m_packList.size();// m_entries_current.size(); + const u64 cursor_pos = m_index; + + if (touch->is_clicked) { + for (u64 i = 0, pos = SCROLL, y = 110, w = 350, h = 250; pos < nro_total && i < max_entry_display; y += h + 10) { + for (u64 j = 0, x = 75; j < 3 && pos < nro_total && i < max_entry_display; j++, i++, pos++, x += w + 10) { + if (touch->in_range(x, y, w, h)) { + if (pos == m_index) { + FireAction(Button::A); + } else { + App::PlaySoundEffect(SoundEffect_Focus); + SetIndex(pos); + } + break; + } + } + } + } } void Menu::Draw(NVGcontext* vg, Theme* theme) { diff --git a/sphaira/source/ui/widget.cpp b/sphaira/source/ui/widget.cpp index 208d212..ccf7a6b 100644 --- a/sphaira/source/ui/widget.cpp +++ b/sphaira/source/ui/widget.cpp @@ -47,4 +47,15 @@ void Widget::RemoveAction(Button button) { } } +auto Widget::FireAction(Button b, u8 type) -> bool { + for (const auto& [button, action] : m_actions) { + if (button == b && (action.m_type & type)) { + App::PlaySoundEffect(SoundEffect_Focus); + action.Invoke(true); + return true; + } + } + return false; +} + } // namespace sphaira::ui