Files
pico-launcher/arm9/source/romBrowser/views/cheats/CheatsBottomSheetView.cpp

288 lines
12 KiB
C++

#include "common.h"
#include "gui/GraphicsContext.h"
#include "themes/material/MaterialColorScheme.h"
#include "themes/IFontRepository.h"
#include "gui/input/InputProvider.h"
#include "gui/VramContext.h"
#include "gui/palette/GradientPalette.h"
#include "gui/OamBuilder.h"
#include "folderIcon.h"
#include "upIcon.h"
#include "checkboxChecked.h"
#include "checkboxUnchecked.h"
#include "cheatSelector.h"
#include "gui/DescendingStackVramManager.h"
#include "CheatsBottomSheetView.h"
#define TITLE_LABEL_X 20
#define TITLE_LABEL_Y 16
#define CATEGORY_NAME_LABEL_X (TITLE_LABEL_X + 43)
#define CATEGORY_NAME_LABEL_Y (TITLE_LABEL_Y + 1)
#define NO_CHEATS_FOUND_LABEL_X 20
#define NO_CHEATS_FOUND_LABEL_Y 36
#define DESCRIPTION_LABEL_X 16
#define DESCRIPTION_LABEL_Y 147
#define LIST_X 16
#define LIST_Y 36
#define LIST_WIDTH 224
#define LIST_HEIGHT 108
CheatsBottomSheetView::CheatsBottomSheetView(SharedPtr<CheatsViewModel> viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
FocusManager* focusManager)
: _viewModel(std::move(viewModel))
, _titleLabel(Label2DView::CreateShared(64, 16, 25, fontRepository->GetFont(FontType::Medium11)))
, _secondaryLabel(Label2DView::CreateShared(153, 16, 64, fontRepository->GetFont(FontType::Regular10)))
, _descriptionLabel(Label2DView::CreateShared(224, 16, 256, fontRepository->GetFont(FontType::Medium7_5)))
, _cheatListRecycler(RecyclerView::CreateShared(
LIST_X, LIST_Y, LIST_WIDTH, LIST_HEIGHT, RecyclerView::Mode::VerticalList))
, _upButton(IconButton2DView::CreateShared(
IconButtonView::Type::Standard,
IconButtonView::State::NoToggle,
md::sys::color::inverseOnSurface,
materialColorScheme))
, _materialColorScheme(materialColorScheme)
, _fontRepository(fontRepository)
, _focusManager(focusManager)
{
_titleLabel->SetText(u"Cheats");
_secondaryLabel->SetText(u"No cheats found.");
_secondaryLabel->SetEllipsisStyle(LabelView::EllipsisStyle::Ellipsis);
_descriptionLabel->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee);
_descriptionLabel->SetText(u"");
AddChildTail(_titleLabel.GetPointer());
AddChildTail(_secondaryLabel.GetPointer());
AddChildTail(_descriptionLabel.GetPointer());
AddChildTail(_cheatListRecycler.GetPointer());
_upButton->SetAction([] (IconButtonView*, void* arg)
{
((CheatsBottomSheetView*)arg)->_viewModel->NavigateUp();
}, this);
}
void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
{
BottomSheetView::InitVram(vramContext);
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_vramOffsets.folderIconVramOffset
= LoadSprite(*objVramManager, folderIconTiles, folderIconTilesLen);
_vramOffsets.checkboxUncheckedIconVramOffset
= LoadSprite(*objVramManager, checkboxUncheckedTiles, checkboxUncheckedTilesLen);
_vramOffsets.checkboxCheckedIconVramOffset
= LoadSprite(*objVramManager, checkboxCheckedTiles, checkboxCheckedTilesLen);
_vramOffsets.cheatSelectorVramOffset
= LoadSprite(*objVramManager, cheatSelectorTiles, cheatSelectorTilesLen);
auto iconButtonVramToken = IconButton2DView::UploadGraphics(*objVramManager);
_upButton->SetGraphics(iconButtonVramToken);
_upButton->SetIconVramOffset(LoadSprite(*objVramManager, upIconTiles, upIconTilesLen));
}
_objVramManager = vramContext.GetObjVramManager();
}
void CheatsBottomSheetView::Update()
{
if (_upButton->GetParent() == nullptr && _viewModel->IsInSubCategory())
{
AddChildTail(_upButton.GetPointer());
}
else if (_upButton->GetParent() != nullptr && !_viewModel->IsInSubCategory())
{
RemoveChild(_upButton.GetPointer());
}
_titleLabel->SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y);
if (_viewModel->GetState() == CheatsViewModel::State::DisplayCheats)
{
_secondaryLabel->SetPosition(CATEGORY_NAME_LABEL_X, _position.y + CATEGORY_NAME_LABEL_Y);
}
else
{
_secondaryLabel->SetPosition(NO_CHEATS_FOUND_LABEL_X, _position.y + NO_CHEATS_FOUND_LABEL_Y);
}
_descriptionLabel->SetPosition(DESCRIPTION_LABEL_X, _position.y + DESCRIPTION_LABEL_Y);
_cheatListRecycler->SetPosition(LIST_X, _position.y + LIST_Y);
_upButton->SetPosition(212, _position.y + CATEGORY_NAME_LABEL_Y - 8);
if (_viewModel->GetState() == CheatsViewModel::State::DisplayCheats)
{
if (!_cheatsAdapter && _objVramManager != nullptr)
{
_currentCheatCategory = _viewModel->GetCurrentCheatCategory();
_cheatsAdapter = SharedPtr<CheatsAdapter>::MakeShared(
_currentCheatCategory, _viewModel, _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter);
// Ugly hack
_savedVramState = ((DescendingStackVramManager*)_objVramManager)->GetState();
_cheatListRecycler->InitVram(VramContext(nullptr, _objVramManager, nullptr, nullptr));
_cheatListRecycler->Focus(*_focusManager);
}
else if (_currentCheatCategory != _viewModel->GetCurrentCheatCategory()
&& _viewModel->GetCurrentCheatCategory() != nullptr)
{
// _secondaryLabel->SetText(_viewModel->GetCurrentCheatCategory()->GetName());
UpdateCheatList();
}
}
BottomSheetView::Update();
int selectedItem = _cheatListRecycler->GetSelectedItem();
if (selectedItem != _viewModel->GetSelectedItem())
{
_viewModel->SetSelectedItem(selectedItem);
UpdateDescriptionText();
}
}
void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
{
graphicsContext.SetClipArea(GetBounds());
u32 oldPrio = graphicsContext.SetPriority(1);
{
graphicsContext.SetClipArea(_cheatListRecycler->GetBounds());
_cheatListRecycler->Draw(graphicsContext);
graphicsContext.SetClipArea(GetBounds());
auto backColor = _materialColorScheme->GetColor(md::sys::color::surfaceContainerLow);
auto maskOam = graphicsContext.GetOamManager().AllocOams(8);
// Top
u32 maskPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(backColor, backColor),
_position.y + LIST_Y - 24, _position.y + LIST_Y);
OamBuilder::OamWithSize<64, 32>(LIST_X, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[0]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 64, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[1]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[2]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64 + 32, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[3]);
// Bottom
if (graphicsContext.IsVisible(Rectangle(LIST_X, _position.y + LIST_Y + LIST_HEIGHT, 224, 24)))
{
maskPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(backColor, backColor),
_position.y + LIST_Y + LIST_HEIGHT, 192);
OamBuilder::OamWithSize<64, 32>(LIST_X, _position.y + LIST_Y + LIST_HEIGHT, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[4]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 64, _position.y + LIST_Y + LIST_HEIGHT, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[5]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64, _position.y + LIST_Y + LIST_HEIGHT, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[6]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64 + 32, _position.y + LIST_Y + LIST_HEIGHT, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[7]);
}
_titleLabel->SetBackgroundColor(backColor);
_titleLabel->SetForegroundColor(_materialColorScheme->onSurface);
_titleLabel->Draw(graphicsContext);
if (_viewModel->GetState() == CheatsViewModel::State::NoCheats ||
_viewModel->IsInSubCategory())
{
_secondaryLabel->SetBackgroundColor(backColor);
_secondaryLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_secondaryLabel->Draw(graphicsContext);
}
_descriptionLabel->SetBackgroundColor(backColor);
_descriptionLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_descriptionLabel->Draw(graphicsContext);
if (_viewModel->IsInSubCategory())
{
_upButton->Draw(graphicsContext);
}
}
graphicsContext.SetPriority(oldPrio);
graphicsContext.ResetClipArea();
}
bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::B))
{
_viewModel->NavigateUp();
return true;
}
else if (inputProvider.Triggered(InputKey::Y))
{
_viewModel->Close();
return true;
}
else if (inputProvider.Triggered(InputKey::X))
{
_viewModel->DisableAllCheats();
return true;
}
return false;
}
void CheatsBottomSheetView::Close()
{
_viewModel->Close();
}
void CheatsBottomSheetView::UpdateCheatList()
{
_currentCheatCategory = _viewModel->GetCurrentCheatCategory();
_cheatsAdapter = SharedPtr<CheatsAdapter>::MakeShared(
_currentCheatCategory, _viewModel, _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter, _viewModel->GetSelectedItem());
// Ugly hack
((DescendingStackVramManager*)_objVramManager)->SetState(_savedVramState);
_cheatListRecycler->InitVram(VramContext(nullptr, _objVramManager, nullptr, nullptr));
_cheatListRecycler->Focus(*_focusManager);
UpdateDescriptionText();
}
void CheatsBottomSheetView::UpdateDescriptionText()
{
int selectedItem = _viewModel->GetSelectedItem();
if (selectedItem < 0)
{
_descriptionLabel->SetText("");
}
else
{
auto cheatCategory = _viewModel->GetCurrentCheatCategory();
u32 numberOfSubEntries = 0;
auto subEntries = cheatCategory->GetSubEntries(numberOfSubEntries);
_descriptionLabel->SetText(subEntries[selectedItem].GetDescription());
}
}
u32 CheatsBottomSheetView::LoadSprite(IVramManager& vramManager, const unsigned int* tiles, u32 tilesLength) const
{
u32 vramOffset = vramManager.Alloc(tilesLength);
dma_ntrCopy32(3, tiles, vramManager.GetVramAddress(vramOffset), tilesLength);
return vramOffset;
}