initial work on touch support
list of things not done: - no scrolling - only some menus - no widgets - no buttons
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -707,34 +707,27 @@ void App::Poll() {
|
||||
m_controller.m_kup = padGetButtonsUp(&m_pad);
|
||||
m_controller.UpdateButtonHeld(static_cast<u64>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user