add layout options to grid based menues.

This commit is contained in:
ITotalJustice
2025-05-11 02:39:03 +01:00
parent 5d9e24af31
commit e279a70606
18 changed files with 579 additions and 244 deletions

View File

@@ -14,6 +14,11 @@ List::List(s64 row, s64 page, const Vec4& pos, const Vec4& v, const Vec2& pad)
SetScrollBarPos(SCREEN_WIDTH - 50, 100, SCREEN_HEIGHT-200);
}
auto List::ClampX(float x, s64 count) const -> float {
const float x_max = count * GetMaxX();
return std::clamp(x, 0.F, x_max);
}
auto List::ClampY(float y, s64 count) const -> float {
float y_max = 0;
@@ -25,16 +30,140 @@ auto List::ClampY(float y, s64 count) const -> float {
y_max = (count - m_page) / m_row * GetMaxY();
}
if (y < 0) {
y = 0;
} else if (y > y_max) {
y = y_max;
}
return y;
return std::clamp(y, 0.F, y_max);
}
void List::OnUpdate(Controller* controller, TouchInfo* touch, s64 index, s64 count, TouchCallback callback) {
switch (m_layout) {
case Layout::HOME:
OnUpdateHome(controller, touch, index, count, callback);
break;
case Layout::GRID:
OnUpdateGrid(controller, touch, index, count, callback);
break;
}
}
void List::Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const {
switch (m_layout) {
case Layout::HOME:
DrawHome(vg, theme, count, callback);
break;
case Layout::GRID:
DrawGrid(vg, theme, count, callback);
break;
}
}
auto List::ScrollDown(s64& index, s64 step, s64 count) -> bool {
const auto old_index = index;
const auto max = m_layout == Layout::GRID ? GetMaxY() : GetMaxX();
if (!count) {
return false;
}
if (index + step < count) {
index += step;
} else {
index = count - 1;
}
if (index != old_index) {
App::PlaySoundEffect(SoundEffect_Scroll);
s64 delta = index - old_index;
s64 start = m_yoff / max * m_row;
while (index < start) {
start -= m_row;
m_yoff -= max;
}
if (index - start >= m_page) {
do {
start += m_row;
delta -= m_row;
m_yoff += max;
} while (delta > 0 && start + m_page < count);
}
return true;
}
return false;
}
auto List::ScrollUp(s64& index, s64 step, s64 count) -> bool {
const auto old_index = index;
const auto max = m_layout == Layout::GRID ? GetMaxY() : GetMaxX();
if (!count) {
return false;
}
if (index >= step) {
index -= step;
} else {
index = 0;
}
if (index != old_index) {
App::PlaySoundEffect(SoundEffect_Scroll);
s64 start = m_yoff / max * m_row;
while (index < start) {
start -= m_row;
m_yoff -= max;
}
while (index - start >= m_page && start + m_page < count) {
start += m_row;
m_yoff += max;
}
return true;
}
return false;
}
void List::OnUpdateHome(Controller* controller, TouchInfo* touch, s64 index, s64 count, TouchCallback callback) {
if (controller->GotDown(Button::RIGHT)) {
if (ScrollDown(index, m_row, count)) {
callback(false, index);
}
} else if (controller->GotDown(Button::LEFT)) {
if (ScrollUp(index, m_row, count)) {
callback(false, index);
}
} else if (touch->is_clicked && touch->in_range(GetPos())) {
auto v = m_v;
v.x -= ClampX(m_yoff + m_y_prog, count);
for (s64 i = 0; i < count; i++, v.x += v.w + m_pad.x) {
if (v.x > GetX() + GetW()) {
break;
}
Vec4 vv = v;
// if not drawing, only return clipped v as its used for touch
vv.w = std::min(v.x + v.w, m_pos.x + m_pos.w) - v.x;
vv.h = std::min(v.y + v.h, m_pos.y + m_pos.h) - v.y;
if (touch->in_range(vv)) {
callback(true, i);
return;
}
}
} else if (touch->is_scroll && touch->in_range(GetPos())) {
m_y_prog = (float)touch->initial.x - (float)touch->cur.x;
} else if (touch->is_end) {
m_yoff = ClampX(m_yoff + m_y_prog, count);
m_y_prog = 0;
}
}
void List::OnUpdateGrid(Controller* controller, TouchInfo* touch, s64 index, s64 count, TouchCallback callback) {
const auto page_up_button = m_row == 1 ? Button::DPAD_LEFT : Button::L2;
const auto page_down_button = m_row == 1 ? Button::DPAD_RIGHT : Button::R2;
@@ -105,7 +234,26 @@ void List::OnUpdate(Controller* controller, TouchInfo* touch, s64 index, s64 cou
}
}
void List::Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const {
void List::DrawHome(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const {
const auto yoff = ClampX(m_yoff + m_y_prog, count);
auto v = m_v;
v.x -= yoff;
nvgSave(vg);
nvgIntersectScissor(vg, GetX(), GetY(), GetW(), GetH());
for (s64 i = 0; i < count; i++, v.x += v.w + m_pad.x) {
if (v.x > GetX() + GetW()) {
break;
}
callback(vg, theme, v, i);
}
nvgRestore(vg);
}
void List::DrawGrid(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const {
const auto yoff = ClampY(m_yoff + m_y_prog, count);
const s64 start = yoff / GetMaxY() * m_row;
gfx::drawScrollbar2(vg, theme, m_scrollbar.x, m_scrollbar.y, m_scrollbar.h, start, count, m_row, m_page);
@@ -114,7 +262,7 @@ void List::Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) cons
v.y -= yoff;
nvgSave(vg);
nvgScissor(vg, GetX(), GetY(), GetW(), GetH());
nvgIntersectScissor(vg, GetX(), GetY(), GetW(), GetH());
for (s64 i = 0; i < count; v.y += v.h + m_pad.y) {
if (v.y > GetY() + GetH()) {
@@ -143,74 +291,4 @@ void List::Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) cons
nvgRestore(vg);
}
auto List::ScrollDown(s64& index, s64 step, s64 count) -> bool {
const auto old_index = index;
if (!count) {
return false;
}
if (index + step < count) {
index += step;
} else {
index = count - 1;
}
if (index != old_index) {
App::PlaySoundEffect(SoundEffect_Scroll);
s64 delta = index - old_index;
s64 start = m_yoff / GetMaxY() * m_row;
while (index < start) {
start -= m_row;
m_yoff -= GetMaxY();
}
if (index - start >= m_page) {
do {
start += m_row;
delta -= m_row;
m_yoff += GetMaxY();
} while (delta > 0 && start + m_page < count);
}
return true;
}
return false;
}
auto List::ScrollUp(s64& index, s64 step, s64 count) -> bool {
const auto old_index = index;
if (!count) {
return false;
}
if (index >= step) {
index -= step;
} else {
index = 0;
}
if (index != old_index) {
App::PlaySoundEffect(SoundEffect_Scroll);
s64 start = m_yoff / GetMaxY() * m_row;
while (index < start) {
start -= m_row;
m_yoff -= GetMaxY();
}
while (index - start >= m_page && start + m_page < count) {
start += m_row;
m_yoff += GetMaxY();
}
return true;
}
return false;
}
} // namespace sphaira::ui