Add touch input support, add fast scrolling support for coverflow display mode, fix use after free bug in banner list mode

This commit is contained in:
Gericom
2026-04-04 19:24:39 +02:00
parent 21a8790ebc
commit 97762b14d3
119 changed files with 2251 additions and 762 deletions

View File

@@ -7,6 +7,7 @@
#include "gui/palette/GradientPalette.h"
#include "gui/OamBuilder.h"
#include "folderIcon.h"
#include "upIcon.h"
#include "checkboxChecked.h"
#include "checkboxUnchecked.h"
#include "cheatSelector.h"
@@ -30,28 +31,37 @@
#define LIST_WIDTH 224
#define LIST_HEIGHT 108
CheatsBottomSheetView::CheatsBottomSheetView(std::unique_ptr<CheatsViewModel> viewModel,
CheatsBottomSheetView::CheatsBottomSheetView(SharedPtr<CheatsViewModel> viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
FocusManager* focusManager)
: _viewModel(std::move(viewModel))
, _titleLabel(64, 16, 25, fontRepository->GetFont(FontType::Medium11))
, _secondaryLabel(177, 16, 64, fontRepository->GetFont(FontType::Regular10))
, _descriptionLabel(224, 16, 256, fontRepository->GetFont(FontType::Medium7_5))
, _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("");
AddChildTail(&_titleLabel);
AddChildTail(&_secondaryLabel);
AddChildTail(&_descriptionLabel);
_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)
@@ -61,21 +71,17 @@ void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_vramOffsets.folderIconVramOffset = objVramManager->Alloc(folderIconTilesLen);
dma_ntrCopy32(3, folderIconTiles,
objVramManager->GetVramAddress(_vramOffsets.folderIconVramOffset), folderIconTilesLen);
_vramOffsets.checkboxUncheckedIconVramOffset = objVramManager->Alloc(checkboxUncheckedTilesLen);
dma_ntrCopy32(3, checkboxUncheckedTiles,
objVramManager->GetVramAddress(_vramOffsets.checkboxUncheckedIconVramOffset), checkboxUncheckedTilesLen);
_vramOffsets.checkboxCheckedIconVramOffset = objVramManager->Alloc(checkboxCheckedTilesLen);
dma_ntrCopy32(3, checkboxCheckedTiles,
objVramManager->GetVramAddress(_vramOffsets.checkboxCheckedIconVramOffset), checkboxCheckedTilesLen);
_vramOffsets.cheatSelectorVramOffset = objVramManager->Alloc(cheatSelectorTilesLen);
dma_ntrCopy32(3, cheatSelectorTiles,
objVramManager->GetVramAddress(_vramOffsets.cheatSelectorVramOffset), cheatSelectorTilesLen);
_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();
@@ -83,23 +89,34 @@ void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
void CheatsBottomSheetView::Update()
{
_titleLabel.SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y);
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);
_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);
_secondaryLabel->SetPosition(NO_CHEATS_FOUND_LABEL_X, _position.y + NO_CHEATS_FOUND_LABEL_Y);
}
_descriptionLabel.SetPosition(DESCRIPTION_LABEL_X, _position.y + DESCRIPTION_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(
_viewModel->GetCurrentCheatCategory(), _materialColorScheme, _fontRepository, _vramOffsets);
_currentCheatCategory, _viewModel, _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter);
// Ugly hack
@@ -108,6 +125,12 @@ void CheatsBottomSheetView::Update()
_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();
@@ -175,21 +198,26 @@ void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
.Build(maskOam[7]);
}
_titleLabel.SetBackgroundColor(backColor);
_titleLabel.SetForegroundColor(_materialColorScheme->onSurface);
_titleLabel.Draw(graphicsContext);
_titleLabel->SetBackgroundColor(backColor);
_titleLabel->SetForegroundColor(_materialColorScheme->onSurface);
_titleLabel->Draw(graphicsContext);
if (_viewModel->GetState() == CheatsViewModel::State::NoCheats ||
_viewModel->ShouldShowCategoryName())
_viewModel->IsInSubCategory())
{
_secondaryLabel.SetBackgroundColor(backColor);
_secondaryLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_secondaryLabel.Draw(graphicsContext);
_secondaryLabel->SetBackgroundColor(backColor);
_secondaryLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_secondaryLabel->Draw(graphicsContext);
}
_descriptionLabel.SetBackgroundColor(backColor);
_descriptionLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_descriptionLabel.Draw(graphicsContext);
_descriptionLabel->SetBackgroundColor(backColor);
_descriptionLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_descriptionLabel->Draw(graphicsContext);
if (_viewModel->IsInSubCategory())
{
_upButton->Draw(graphicsContext);
}
}
graphicsContext.SetPriority(oldPrio);
graphicsContext.ResetClipArea();
@@ -197,29 +225,9 @@ void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::A))
if (inputProvider.Triggered(InputKey::B))
{
if (focusManager.IsFocusInside(_cheatListRecycler.GetPointer()))
{
auto oldCategory = _viewModel->GetCurrentCheatCategory();
_viewModel->ActivateSelectedItem();
if (oldCategory != _viewModel->GetCurrentCheatCategory())
{
_secondaryLabel.SetText(_viewModel->GetCurrentCheatCategory()->GetName());
UpdateCheatList();
}
return true;
}
}
else if (inputProvider.Triggered(InputKey::B))
{
auto oldCategory = _viewModel->GetCurrentCheatCategory();
if (_viewModel->NavigateUp() &&
oldCategory != _viewModel->GetCurrentCheatCategory())
{
UpdateCheatList();
}
_viewModel->NavigateUp();
return true;
}
else if (inputProvider.Triggered(InputKey::Y))
@@ -235,13 +243,16 @@ bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, Focu
return false;
}
void CheatsBottomSheetView::Close()
{
_viewModel->Close();
}
void CheatsBottomSheetView::UpdateCheatList()
{
// Need to unfocus first, otherwise the focus manager still contains a pointer to a view that is going to be destroyed
_focusManager->Unfocus();
_currentCheatCategory = _viewModel->GetCurrentCheatCategory();
_cheatsAdapter = SharedPtr<CheatsAdapter>::MakeShared(
_viewModel->GetCurrentCheatCategory(), _materialColorScheme, _fontRepository, _vramOffsets);
_currentCheatCategory, _viewModel, _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter, _viewModel->GetSelectedItem());
// Ugly hack
@@ -257,13 +268,20 @@ void CheatsBottomSheetView::UpdateDescriptionText()
int selectedItem = _viewModel->GetSelectedItem();
if (selectedItem < 0)
{
_descriptionLabel.SetText("");
_descriptionLabel->SetText("");
}
else
{
auto cheatCategory = _viewModel->GetCurrentCheatCategory();
u32 numberOfSubEntries = 0;
auto subEntries = cheatCategory->GetSubEntries(numberOfSubEntries);
_descriptionLabel.SetText(subEntries[selectedItem].GetDescription());
_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;
}