add layout options to grid based menues.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user