#include "ui/TitleView.hpp" #include "colors.hpp" #include "config.hpp" #include "input.hpp" #include "logger.hpp" #include "ui/render_functions.hpp" #include namespace { constexpr int ICON_ROW_SIZE = 7; } ui::TitleView::TitleView(data::User *user) : m_user(user) { TitleView::refresh(); } void ui::TitleView::update(bool hasFocus) { // These are named like this because of where they sit on the screen. static constexpr double UPPER_THRESHOLD = 32.0f; static constexpr double LOWER_THRESHOLD = 388.0f; if (m_titleTiles.empty()) { return; } // Update pulse if (hasFocus) { m_colorMod.update(); } const bool upPressed = input::button_pressed(HidNpadButton_AnyUp); const bool downPressed = input::button_pressed(HidNpadButton_AnyDown); const bool leftPressed = input::button_pressed(HidNpadButton_AnyLeft); const bool rightPressed = input::button_pressed(HidNpadButton_AnyRight); const bool lShoulderPressed = input::button_pressed(HidNpadButton_L); const bool rShoulderPressed = input::button_pressed(HidNpadButton_R); const int totalTiles = m_titleTiles.size() - 1; if (upPressed) { m_selected -= ICON_ROW_SIZE; } else if (leftPressed) { --m_selected; } else if (lShoulderPressed) { m_selected -= ICON_ROW_SIZE * 3; } else if (downPressed) { m_selected += ICON_ROW_SIZE; } else if (rightPressed) { ++m_selected; } else if (rShoulderPressed) { m_selected += ICON_ROW_SIZE * 3; } if (m_selected < 0) { m_selected = 0; } else if (m_selected > totalTiles) { m_selected = totalTiles; } const double scaling = config::get_animation_scaling(); if (m_selectedY < UPPER_THRESHOLD) { m_y += std::ceil((UPPER_THRESHOLD - m_selectedY) / scaling); } else if (m_selectedY > LOWER_THRESHOLD) { m_y += std::ceil((LOWER_THRESHOLD - m_selectedY) / scaling); } const int tileCount = m_titleTiles.size(); for (int i = 0; i < tileCount; i++) { const bool isSelected = m_selected == i; ui::TitleTile &tile = m_titleTiles[i]; tile.update(isSelected); } } void ui::TitleView::render(SDL_Texture *target, bool hasFocus) { static constexpr int TILE_SPACE_VERT = 144; static constexpr int TILE_SPACE_HOR = 144; if (m_titleTiles.empty()) { return; } const int tileCount = m_titleTiles.size(); for (int i = 0, tempY = m_y; i < tileCount; i += ICON_ROW_SIZE, tempY += TILE_SPACE_VERT) { const int endRow = i + ICON_ROW_SIZE; for (int j = i, tempX = 32; j < endRow && j < tileCount; j++, tempX += TILE_SPACE_HOR) { if (j == m_selected) { m_selectedX = tempX; m_selectedY = tempY; continue; } ui::TitleTile &tile = m_titleTiles[j]; tile.render(target, tempX, tempY); } } if (hasFocus) { sdl::render_rect_fill(target, m_selectedX - 29, m_selectedY - 29, 187, 187, colors::CLEAR_COLOR); ui::render_bounding_box(target, m_selectedX - 30, m_selectedY - 30, 188, 188, m_colorMod); } ui::TitleTile &selectedTile = m_titleTiles.at(m_selected); selectedTile.render(target, m_selectedX, m_selectedY); } int ui::TitleView::get_selected() const { return m_selected; } void ui::TitleView::refresh() { m_titleTiles.clear(); const int entryCount = m_user->get_total_data_entries(); for (int i = 0; i < entryCount; i++) { const uint64_t applicationID = m_user->get_application_id_at(i); const bool isFavorite = config::is_favorite(applicationID); data::TitleInfo *titleInfo = data::get_title_info_by_id(applicationID); sdl::SharedTexture icon = titleInfo->get_icon(); // I don't like this but w/e. m_titleTiles.emplace_back(isFavorite, icon); } const int tileCount = m_titleTiles.size() - 1; if (tileCount <= 0) { m_selected = 0; } else if (m_selected > tileCount) { m_selected = tileCount; } } void ui::TitleView::reset() { for (ui::TitleTile ¤tTile : m_titleTiles) { currentTile.reset(); } }