Initial commit

This commit is contained in:
Gericom
2025-11-22 17:21:45 +01:00
commit 5d6f67c612
517 changed files with 63025 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
#include "common.h"
#include "AppBarView.h"
#define BUTTON_SIZE 32
AppBarView::AppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme)
: _orientation(orientation)
, _buttons(std::make_unique<IconButtonView*[]>(startButtonCount + endButtonCount))
, _startButtonCount(startButtonCount), _endButtonCount(endButtonCount)
{
SetPosition(x, y);
}
AppBarView::~AppBarView()
{
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{
delete _buttons[i];
_buttons[i] = nullptr;
}
}
Rectangle AppBarView::GetBounds() const
{
if (_orientation == Orientation::Horizontal)
return Rectangle(0, _position.y, 256, BUTTON_SIZE);
else
return Rectangle(_position.x, 0, BUTTON_SIZE, 192);
}
void AppBarView::Update()
{
if (_orientation == Orientation::Horizontal)
UpdateButtonPositionsHorizontal();
else
UpdateButtonPositionsVertical();
ViewContainer::Update();
}
View* AppBarView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
{
int idx = FindButtonIndex(currentFocus);
if (idx >= 0)
{
if (_orientation == Orientation::Horizontal)
{
if (direction == FocusMoveDirection::Left)
idx--;
else if (direction == FocusMoveDirection::Right)
idx++;
else
return View::MoveFocus(currentFocus, direction, this);
}
else
{
if (direction == FocusMoveDirection::Up)
idx--;
else if (direction == FocusMoveDirection::Down)
idx++;
else
return View::MoveFocus(currentFocus, direction, this);
}
if (idx < 0 || idx >= _startButtonCount + _endButtonCount)
return nullptr;
return _buttons[idx];
}
else if ((_orientation == Orientation::Horizontal && (direction == FocusMoveDirection::Up || direction == FocusMoveDirection::Down)) ||
(_orientation == Orientation::Vertical && (direction == FocusMoveDirection::Left || direction == FocusMoveDirection::Right)))
{
if (currentFocus == nullptr)
return _buttons[0];
Point curFocusPoint = currentFocus->GetBounds().GetCenter();
s64 bestDistance = std::numeric_limits<s64>::max();
View* nearestButton = nullptr;
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{
s64 distance = curFocusPoint.DistanceSquaredTo(_buttons[i]->GetBounds().GetCenter());
if (distance < bestDistance)
{
bestDistance = distance;
nearestButton = _buttons[i];
}
}
return nearestButton;
}
else
return View::MoveFocus(currentFocus, direction, this);
}
void AppBarView::Focus(FocusManager& focusManager, int button)
{
focusManager.Focus(_buttons[button]);
}
void AppBarView::UpdateButtonPositionsHorizontal()
{
for (int i = 0; i < _startButtonCount; i++)
_buttons[i]->SetPosition(i * BUTTON_SIZE, _position.y);
int x = 256;
for (int i = _startButtonCount + _endButtonCount - 1; i >= _startButtonCount; i--)
{
x -= BUTTON_SIZE;
_buttons[i]->SetPosition(x, _position.y);
}
}
void AppBarView::UpdateButtonPositionsVertical()
{
for (int i = 0; i < _startButtonCount; i++)
_buttons[i]->SetPosition(_position.x, i * BUTTON_SIZE);
int y = 192;
for (int i = _startButtonCount + _endButtonCount - 1; i >= _startButtonCount; i--)
{
y -= BUTTON_SIZE;
_buttons[i]->SetPosition(_position.x, y);
}
}
int AppBarView::FindButtonIndex(const View* view)
{
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{
if (_buttons[i] == view)
{
return i;
}
}
return -1;
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <memory>
#include "gui/views/ViewContainer.h"
#include "IconButtonView.h"
class MaterialColorScheme;
class AppBarView : public ViewContainer
{
public:
enum class Orientation
{
Horizontal,
Vertical
};
virtual ~AppBarView();
void SetButtonIcon(int button, u32 vramOffset)
{
_buttons[button]->SetIconVramOffset(vramOffset);
}
void SetButtonAction(int button, IconButtonView::button_action_t action, void* arg)
{
_buttons[button]->SetAction(action, arg);
}
Rectangle GetBounds() const override;
void Update() override;
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
void Focus(FocusManager& focusManager, int button);
constexpr Orientation GetOrientation() const { return _orientation; }
protected:
Orientation _orientation;
std::unique_ptr<IconButtonView*[]> _buttons;
int _startButtonCount;
int _endButtonCount;
void UpdateButtonPositionsHorizontal();
void UpdateButtonPositionsVertical();
int FindButtonIndex(const View* view);
AppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme);
};

View File

@@ -0,0 +1,25 @@
#include "common.h"
#include "gui/IVramManager.h"
#include "gui/GraphicsContext.h"
#include "BannerListItemView.h"
BannerListItemView::BannerListItemView(std::unique_ptr<LabelView> firstLine,
std::unique_ptr<LabelView> secondLine, std::unique_ptr<LabelView> thirdLine)
: _firstLine(std::move(firstLine))
, _secondLine(std::move(secondLine))
, _thirdLine(std::move(thirdLine))
{
AddChildTail(_firstLine.get());
AddChildTail(_secondLine.get());
AddChildTail(_thirdLine.get());
}
void BannerListItemView::Update()
{
ViewContainer::Update();
if (_icon)
{
_icon->Update();
}
}

View File

@@ -0,0 +1,67 @@
#pragma once
#include "BannerView.h"
#include "gui/views/LabelView.h"
#include "../FileType/FileIcon.h"
class BannerListItemView : public BannerView
{
public:
class VramToken
{
u32 _vramOffset;
public:
VramToken()
: _vramOffset(0) { }
explicit VramToken(u32 offset)
: _vramOffset(offset) { }
constexpr u32 GetVramOffset() const { return _vramOffset; }
};
BannerListItemView(std::unique_ptr<LabelView> firstLine,
std::unique_ptr<LabelView> secondLine, std::unique_ptr<LabelView> thirdLine);
void Update() override;
virtual void SetGraphics(const VramToken& vramToken) { }
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override
{
_firstLine->SetEllipsis(ellipsis);
if (taskQueue)
_firstLine->SetTextAsync(taskQueue, firstLine);
else
_firstLine->SetText(firstLine);
}
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override
{
_firstLine->SetEllipsis(ellipsis);
if (taskQueue)
_firstLine->SetTextAsync(taskQueue, firstLine, length);
else
_firstLine->SetText(firstLine, length);
}
void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override
{
if (taskQueue)
_secondLine->SetTextAsync(taskQueue, secondLine, length);
else
_secondLine->SetText(secondLine, length);
}
void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override
{
if (taskQueue)
_thirdLine->SetTextAsync(taskQueue, thirdLine, length);
else
_thirdLine->SetText(thirdLine, length);
}
protected:
std::unique_ptr<LabelView> _firstLine;
std::unique_ptr<LabelView> _secondLine;
std::unique_ptr<LabelView> _thirdLine;
};

View File

@@ -0,0 +1,63 @@
#include "common.h"
#include "gui/IVramManager.h"
#include "gui/VramContext.h"
#include "BannerView.h"
void BannerView::InitVram(const VramContext& vramContext)
{
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_iconVramOffset = objVramManager->Alloc(FILE_ICON_VRAM_SIZE);
_iconVram = objVramManager->GetVramAddress(_iconVramOffset);
}
ViewContainer::InitVram(vramContext);
}
void BannerView::SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle)
{
if (useAsTitle)
{
_lines = 1;
SetFirstLineAsync(taskQueue, fileName, true);
SetSecondLineAsync(taskQueue, u"", 0);
SetThirdLineAsync(taskQueue, u"", 0);
}
}
void BannerView::SetGameTitleAsync(TaskQueueBase* taskQueue, const char16_t* gameTitle)
{
const char16_t* p = gameTitle;
int i = 0;
while (true)
{
u16 c = *p++;
if (c == 0 || c == '\n')
{
if (i == 0)
{
_lines = 1;
SetFirstLineAsync(taskQueue, gameTitle, p - gameTitle, false);
}
else if (i == 1)
{
_lines = 2;
SetSecondLineAsync(taskQueue, gameTitle, p - gameTitle);
}
else if (i == 2)
{
_lines = 3;
SetThirdLineAsync(taskQueue, gameTitle, p - gameTitle);
}
gameTitle = p;
i++;
if (c == 0 || i == 3)
break;
}
}
if (i <= 1)
SetSecondLineAsync(taskQueue, u"", 0);
if (i <= 2)
SetThirdLineAsync(taskQueue, u"", 0);
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include "gui/views/ViewContainer.h"
#include "../FileType/FileIcon.h"
class TaskQueueBase;
class BannerView : public ViewContainer
{
public:
void InitVram(const VramContext& vramContext) override;
void SetFileName(const TCHAR* fileName, bool useAsTitle)
{
SetFileNameAsync(nullptr, fileName, useAsTitle);
}
virtual void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle);
void SetGameTitle(const char16_t* gameTitle)
{
SetGameTitleAsync(nullptr, gameTitle);
}
void SetGameTitleAsync(TaskQueueBase* taskQueue, const char16_t* gameTitle);
void SetIcon(std::unique_ptr<FileIcon> icon)
{
_icon = std::move(icon);
}
void UploadIconGraphics() const
{
if (_icon)
{
_icon->UploadGraphics(_iconVram);
}
}
protected:
std::unique_ptr<FileIcon> _icon = nullptr;
vu16* _iconVram;
u32 _iconVramOffset;
u32 _lines;
virtual void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) = 0;
virtual void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) = 0;
virtual void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) = 0;
virtual void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) = 0;
};

View File

@@ -0,0 +1,19 @@
#pragma once
#include "animation/Animator.h"
#include "gui/views/DialogView.h"
class BottomSheetView : public DialogView
{
public:
Rectangle GetBounds() const override
{
return Rectangle(_position.x, _position.y, 256 - _position.x, 192 - _position.y);
}
Rectangle GetFullyCoveredArea() const override
{
return Rectangle(_position.x, _position.y + 12, 256 - _position.x, 148);
}
constexpr DialogType GetDialogType() const override { return DialogType::BottomSheet; }
};

View File

@@ -0,0 +1,138 @@
#include "common.h"
#include <algorithm>
#include <libtwl/dma/dmaNitro.h>
#include "gui/IVramManager.h"
#include "gui/OamManager.h"
#include "gui/OamBuilder.h"
#include "gui/GraphicsContext.h"
#include "core/math/ColorConverter.h"
#include "core/math/RgbMixer.h"
#include "chipFilled.h"
#include "gui/palette/DirectPalette.h"
#include "gui/palette/GradientPalette.h"
#include "themes/material/MaterialColorScheme.h"
#include "ChipView.h"
void ChipView::Draw(GraphicsContext& graphicsContext)
{
if (!graphicsContext.IsVisible(GetBounds()))
return;
u32 paletteRow;
auto bgColor = _materialColorScheme->GetColor(_backgroundColor);
Rgb<8, 8, 8> fgColor;
if (_isSelected)
{
fgColor = _materialColorScheme->secondaryContainer;
if (_isFocused)
fgColor = RgbMixer::Lerp(fgColor, _materialColorScheme->onSurfaceVariant, 12, 100);
u16 chipPltt[16];
for (int i = 0; i < 16; i++)
{
auto blendFactors = ColorConverter::FromXBGR555(chipFilledPal[i]);
auto palColor = Rgb<8, 8, 8>(
(bgColor.r * blendFactors.g + fgColor.r * (blendFactors.r + blendFactors.b) + 16) / 31,
(bgColor.g * blendFactors.g + fgColor.g * (blendFactors.r + blendFactors.b) + 16) / 31,
(bgColor.b * blendFactors.g + fgColor.b * (blendFactors.r + blendFactors.b) + 16) / 31);
chipPltt[i] = ColorConverter::ToGBGR565(palColor.Clamped());
}
paletteRow = graphicsContext.GetPaletteManager().AllocRow(
DirectPalette(chipPltt), _position.y, _position.y + 20);
if (!_isFocused)
{
_label.SetBackgroundColor(_materialColorScheme->secondaryContainer);
_label.SetForegroundColor(_materialColorScheme->onSecondaryContainer);
}
else
{
_label.SetBackgroundColor(fgColor);
_label.SetForegroundColor(_materialColorScheme->onSecondaryContainer);
}
}
else
{
auto selectorFullColor = _materialColorScheme->onSurfaceVariant;
auto outlineColor = _isFocused ? _materialColorScheme->onSurfaceVariant : _materialColorScheme->outline;
fgColor = _isFocused ? RgbMixer::Lerp(bgColor, selectorFullColor, 12, 100) : bgColor;
u16 chipPltt[16];
for (int i = 0; i < 16; i++)
{
auto blendFactors = ColorConverter::FromXBGR555(chipFilledPal[i]);
auto palColor = Rgb<8, 8, 8>(
(fgColor.r * blendFactors.r + bgColor.r * blendFactors.g + outlineColor.r * blendFactors.b + 16) / 31,
(fgColor.g * blendFactors.r + bgColor.g * blendFactors.g + outlineColor.g * blendFactors.b + 16) / 31,
(fgColor.b * blendFactors.r + bgColor.b * blendFactors.g + outlineColor.b * blendFactors.b + 16) / 31);
chipPltt[i] = ColorConverter::ToGBGR565(palColor.Clamped());
}
paletteRow = graphicsContext.GetPaletteManager().AllocRow(
DirectPalette(chipPltt), _position.y, _position.y + 20);
if (!_isFocused)
{
_label.SetBackgroundColor(_materialColorScheme->GetColor(_backgroundColor));
_label.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
}
else
{
_label.SetBackgroundColor(fgColor);
_label.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
}
}
int width = GetWidth();
auto oams = graphicsContext.GetOamManager().AllocOams(2);
OamBuilder::OamWithSize<64, 32>(_position, _vramOffset >> 7)
.WithPalette16(paletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(oams[0]);
OamBuilder::OamWithSize<64, 32>(
_position.x + width - 48 - 16,
_position.y, _vramOffset >> 7)
.WithPalette16(paletteRow)
.WithPriority(graphicsContext.GetPriority())
.WithHFlip()
.Build(oams[1]);
DrawIcon(graphicsContext, fgColor);
_label.SetPosition(_position.x + (_iconVramOffset == 0xFFFFFFFF ? 10 : 22), _position.y + 3);
_label.Draw(graphicsContext);
}
void ChipView::DrawIcon(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& fgColor)
{
if (_iconVramOffset == 0xFFFFFFFF)
return;
u32 iconPaletteRow;
if (_isFocused)
{
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(fgColor, _materialColorScheme->primary),
_position.y, _position.y + 20);
}
else
{
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_isSelected
? _materialColorScheme->secondaryContainer
: _materialColorScheme->GetColor(_backgroundColor),
_materialColorScheme->primary),
_position.y, _position.y + 20);
}
auto iconOam = graphicsContext.GetOamManager().AllocOams(1);
OamBuilder::OamWithSize<16, 16>(_position.x + 5, _position.y + 4, _iconVramOffset >> 7)
.WithPalette16(iconPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(iconOam[0]);
}
ChipView::VramToken ChipView::UploadGraphics(IVramManager& vramManager)
{
u32 vramOffset = vramManager.Alloc(chipFilledTilesLen);
dma_ntrCopy32(3, chipFilledTiles, vramManager.GetVramAddress(vramOffset), chipFilledTilesLen);
return ChipView::VramToken(vramOffset);
}

View File

@@ -0,0 +1,91 @@
#pragma once
#include "gui/views/View.h"
#include "gui/views/Label2DView.h"
#include "gui/materialDesign.h"
#include "themes/IFontRepository.h"
#include "core/math/Rgb.h"
class MaterialColorScheme;
class IVramManager;
#define CHIP_VIEW_MIN_WIDTH 53
#define CHIP_VIEW_MAX_WIDTH 96
class ChipView : public View
{
public:
class VramToken
{
u32 _vramOffset;
public:
VramToken()
: _vramOffset(0) { }
explicit VramToken(u32 offset)
: _vramOffset(offset) { }
constexpr u32 GetVramOffset() const { return _vramOffset; }
};
explicit ChipView(md::sys::color backgroundColor, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository)
: _vramOffset(0), _isSelected(false), _backgroundColor(backgroundColor)
, _label(CHIP_VIEW_MAX_WIDTH - 20, 16, 30, fontRepository->GetFont(FontType::Medium10))
, _iconVramOffset(0xFFFFFFFF), _materialColorScheme(materialColorScheme) { }
void InitVram(const VramContext& vramContext) override { _label.InitVram(vramContext); }
void SetText(const char16_t* text) { _label.SetText(text); }
void SetText(const char16_t* text, u32 length) { _label.SetText(text, length); }
QueueTask<void> SetTextAsync(TaskQueueBase* taskQueue, const char16_t* text) { return _label.SetTextAsync(taskQueue, text); }
QueueTask<void> SetTextAsync(TaskQueueBase* taskQueue, const char16_t* text, u32 length) { return _label.SetTextAsync(taskQueue, text, length); }
void Draw(GraphicsContext& graphicsContext) override;
void VBlank() override { _label.VBlank(); }
void SetGraphics(const VramToken& vramToken)
{
_vramOffset = vramToken.GetVramOffset();
}
void SetSelected(bool selected)
{
_isSelected = selected;
}
void SetIcon(bool enabled, u32 vramOffset)
{
_iconVramOffset = enabled ? vramOffset : 0xFFFFFFFF;
}
int GetWidth() const
{
int width;
if (_iconVramOffset == 0xFFFFFFFF)
width = 10 + _label.GetStringWidth() + 10;
else
width = 22 + _label.GetStringWidth() + 10;
width = std::clamp(width, CHIP_VIEW_MIN_WIDTH, CHIP_VIEW_MAX_WIDTH);
return width;
}
int GetHeight() const { return 20; }
static VramToken UploadGraphics(IVramManager& vramManager);
Rectangle GetBounds() const override
{
return Rectangle(_position, GetWidth(), GetHeight());
}
private:
u32 _vramOffset;
bool _isSelected;
md::sys::color _backgroundColor;
Label2DView _label;
u32 _iconVramOffset;
const MaterialColorScheme* _materialColorScheme;
void DrawIcon(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& fgColor);
};

View File

@@ -0,0 +1,156 @@
#include "common.h"
#include <string.h>
#include <algorithm>
#include <libtwl/mem/memVram.h>
#include "gui/Gx.h"
#include "gui/GraphicsContext.h"
#include "gui/materialDesign.h"
#include "core/math/SinTable.h"
#include "romBrowser/FileType/FileCover.h"
#include "CoverFlowRecyclerView.h"
#define COVER_SPACING 6
void CoverFlowRecyclerView::Update()
{
if (_itemCount == 0)
{
return;
}
int rangeStartIndex = GetSelectedItem() - 4;
int rangeEndIndex = GetSelectedItem() + 1 + 4;
rangeStartIndex = std::clamp(rangeStartIndex, 0, (int)_itemCount - 1);
rangeEndIndex = std::clamp(rangeEndIndex, 0, (int)_itemCount);
if (_curRangeStart != rangeStartIndex || _curRangeLength != rangeEndIndex - rangeStartIndex)
{
LOG_DEBUG("range: %d - %d\n", rangeStartIndex, rangeEndIndex - 1);
if (_curRangeLength != 0)
{
if (_curRangeStart < rangeStartIndex)
ReleaseRange(_curRangeStart, rangeStartIndex);
if (rangeEndIndex < _curRangeStart + _curRangeLength)
ReleaseRange(rangeEndIndex, _curRangeStart + _curRangeLength);
}
BindRange(rangeStartIndex, rangeEndIndex);
_curRangeStart = rangeStartIndex;
_curRangeLength = rangeEndIndex - rangeStartIndex;
}
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
_viewPoolEx[i].yAngleAnimator.Update();
_viewPoolEx[i].xPositionAnimator.Update();
_viewPoolEx[i].zPositionAnimator.Update();
_viewPool[i].view->SetPosition(_viewPoolEx[i].xPositionAnimator.GetValue().Int(), 32 + 80);
_viewPool[i].view->Update();
}
}
void CoverFlowRecyclerView::Draw(GraphicsContext& graphicsContext)
{
Gx::PolygonAttr(GX_LIGHTMASK_0, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 0);
Gx::MtxMode(GX_MTX_MODE_PROJECTION);
Gx::MtxPush();
fix32<12> near = 2;
fix32<12> far = 100;
fix32<12> left = -1;
fix32<12> right = 1;
fix32<12> top = -1;
fix32<12> bottom = 1;
mtx44_t perspectiveMtx =
{
((2 * near) / (right - left)).GetRawValue(), 0, 0, 0,
0, ((2 * near) / (top - bottom)).GetRawValue(), 0, 0,
((right + left) / (right - left)).GetRawValue(), ((top + bottom) / (top - bottom)).GetRawValue(), ((far + near) / (near - far)).GetRawValue(), -FX32_ONE * 64,
0, 0, ((2 * far * near) / (near - far)).GetRawValue(), 0
};
Gx::MtxLoad44(&perspectiveMtx);
Gx::MtxMode(GX_MTX_MODE_POSITION_VECTOR);
Gx::MtxIdentity();
Gx::LightVector(0, 0, 0, -0x200);
Gx::LightColor(0, 0x7FFF);
Gx::DiffuseAmbient(Rgb<5, 5, 5>(16, 16, 16), false, Rgb<5, 5, 5>(20, 20, 20));
Gx::SpecularEmission(0, false, 0);
// Gx::MtxScale(2.0 / (128.0 / 64.0), 2.0 / (96.0 / 64.0), 1);
Gx::MtxTranslate(-128, /*-96*/-128, fix32<12>(-4));
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
graphicsContext.SetPolygonId(i);
Gx::MtxPush();
{
fix32<12> x = _viewPoolEx[i].xPositionAnimator.GetValue();
u32 angle = _viewPoolEx[i].yAngleAnimator.GetValue();
fix32<12> z = _viewPoolEx[i].zPositionAnimator.GetValue();
auto sinCos = gSinTable.SinCos(angle);
mtx43_t rotMtx =
{
fix32<18>(sinCos.cos).GetRawValue(), 0, -fix32<12>(sinCos.sin).GetRawValue(),
0, FX32_ONE * 64, 0,
fix32<18>(sinCos.sin).GetRawValue(), 0, fix32<12>(sinCos.cos).GetRawValue(),
x.GetRawValue() + 2048, 148 * FX32_ONE + 2048, 0
};
Gx::MtxMult43(&rotMtx);
Gx::MtxTranslate(0, 0, z / 64);
Gx::MtxScale(1.0 / 8, /*1.0 / 8*/1.0/*/6*/, 1);
_viewPool[i].view->Draw(graphicsContext);
}
Gx::MtxPop(1);
}
Gx::MtxMode(GX_MTX_MODE_PROJECTION);
Gx::MtxPop(1);
Gx::MtxMode(GX_MTX_MODE_POSITION_VECTOR);
}
void CoverFlowRecyclerView::UpdateItemPosition(int viewPoolIndex, bool initial)
{
ViewPoolEntry* item = &_viewPool[viewPoolIndex];
ViewPoolEntryEx* itemEx = &_viewPoolEx[viewPoolIndex];
int selectedIndex = GetSelectedItem();
if (selectedIndex == -1)
{
selectedIndex = 0;
}
int itemIndex = item->itemIdx;
fix32<12> x;
fix32<12> z = 0;
u32 angle;
if (itemIndex < selectedIndex)
{
x = 256 / 2 - (COVER_HEIGHT / 4) + COVER_SPACING * (itemIndex - selectedIndex);
angle = std::clamp((selectedIndex - itemIndex) * 10 + 45, -90, 90) * (1 << 16) / 360;
z = -(selectedIndex - itemIndex) * 30 - 20;
}
else if (itemIndex > selectedIndex)
{
x = 256 / 2 + (COVER_HEIGHT / 4) + COVER_SPACING * (itemIndex - selectedIndex);
angle = std::clamp((selectedIndex - itemIndex) * 10 - 45, -90, 90) * (1 << 16) / 360;
z = (selectedIndex - itemIndex) * 30 - 20;
}
else
{
x = 256 / 2;
angle = 0;
}
if (initial)
{
itemEx->yAngleAnimator = Animator<int>(angle);
itemEx->xPositionAnimator = Animator(x);
itemEx->zPositionAnimator = Animator(z);
}
else
{
itemEx->yAngleAnimator.Goto(angle, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
itemEx->xPositionAnimator.Goto(x, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
itemEx->zPositionAnimator.Goto(z, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
}
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <array>
#include "CoverFlowRecyclerViewBase.h"
#include "animation/Animator.h"
class CoverFlowRecyclerView : public CoverFlowRecyclerViewBase
{
public:
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
private:
struct ViewPoolEntryEx
{
Animator<int> yAngleAnimator;
Animator<fix32<12>> xPositionAnimator;
Animator<fix32<12>> zPositionAnimator;
};
std::array<ViewPoolEntryEx, 10> _viewPoolEx;
void UpdateItemPosition(int viewPoolIndex, bool initial) override;
void SwapViewPoolEntry(int indexA, int indexB) override
{
CoverFlowRecyclerViewBase::SwapViewPoolEntry(indexA, indexB);
std::swap(_viewPoolEx[indexA], _viewPoolEx[indexB]);
}
};

View File

@@ -0,0 +1,184 @@
#include "common.h"
#include "CoverFlowRecyclerViewBase.h"
void CoverFlowRecyclerViewBase::InitVram(const VramContext& vramContext)
{
for (u32 i = 0; i < _viewPool.size(); i++)
{
_viewPool[i].view->InitVram(vramContext);
}
}
void CoverFlowRecyclerViewBase::SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex)
{
if (_adapter)
{
_selectedItem = nullptr;
for (u32 i = 0; i < _viewPool.size(); i++)
{
_adapter->DestroyView(_viewPool[i].view);
}
}
_adapter = adapter;
// _adapter->GetViewSize(_itemWidth, _itemHeight);
_itemCount = _adapter->GetItemCount();
for (u32 i = 0; i < _viewPool.size(); i++)
{
_viewPool[i].view = _adapter->CreateView();
_viewPool[i].view->SetParent(this);
_viewPool[i].itemIdx = -1;
}
_viewPoolFreeCount = _viewPool.size();
if (initialSelectedIndex < 0 || (u32)initialSelectedIndex >= _itemCount)
{
initialSelectedIndex = 0;
}
if (_itemCount > 0)
{
SetSelectedItem(initialSelectedIndex, true);
}
}
View* CoverFlowRecyclerViewBase::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
{
if (!_selectedItem || currentFocus != _selectedItem->view)
{
// incoming focus
if (direction == FocusMoveDirection::Down)
{
return _selectedItem ? _selectedItem->view : this;
}
else
{
return nullptr;
}
}
if (direction == FocusMoveDirection::Left)
{
int idx = _selectedItem->itemIdx;
if (idx - 1 >= 0)
{
idx -= 1;
}
SetSelectedItem(idx, false);
}
else if (direction == FocusMoveDirection::Right)
{
int idx = _selectedItem->itemIdx + 1;
idx = std::min(idx, (int)_itemCount - 1);
SetSelectedItem(idx, false);
}
else if (direction == FocusMoveDirection::Up || direction == FocusMoveDirection::Down)
{
return View::MoveFocus(currentFocus, direction, this);
}
return _selectedItem ? _selectedItem->view : this;
}
CoverFlowRecyclerViewBase::ViewPoolEntry* CoverFlowRecyclerViewBase::GetViewPoolEntryByItemIndex(int itemIdx)
{
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
if (_viewPool[i].itemIdx == (int)itemIdx)
return &_viewPool[i];
}
return nullptr;
}
CoverFlowRecyclerViewBase::ViewPoolEntry* CoverFlowRecyclerViewBase::BindViewPoolEntry(int itemIdx)
{
if (_viewPoolFreeCount == 0)
{
LOG_FATAL("No free view pool entries left\n");
while (true);
return nullptr;
}
int viewPoolIndex = _viewPoolFreeCount - 1;
auto& entry = _viewPool[viewPoolIndex];
_viewPoolFreeCount--;
entry.itemIdx = itemIdx;
_adapter->BindView(entry.view, itemIdx);
UpdateItemPosition(viewPoolIndex, true);
return &entry;
}
void CoverFlowRecyclerViewBase::BindRange(int start, int end)
{
for (int i = start; i < end; i++)
{
if (_selectedItem && _selectedItem->itemIdx == i)
continue;
if (_curRangeLength != 0 && _curRangeStart <= i && i < _curRangeStart + _curRangeLength)
continue;
BindViewPoolEntry(i);
}
}
void CoverFlowRecyclerViewBase::ReleaseViewPoolEntry(int itemIdx)
{
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
if (_viewPool[i].itemIdx == (int)itemIdx)
{
_adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
_viewPool[i].itemIdx = -1;
SwapViewPoolEntry(i, _viewPoolFreeCount);
if (_selectedItem == &_viewPool[_viewPoolFreeCount])
_selectedItem = &_viewPool[i];
_viewPoolFreeCount++;
break;
}
}
}
void CoverFlowRecyclerViewBase::ReleaseRange(int start, int end)
{
for (int i = start; i < end; i++)
{
if (_selectedItem && _selectedItem->itemIdx == i)
continue;
ReleaseViewPoolEntry(i);
}
}
void CoverFlowRecyclerViewBase::SetSelectedItem(int itemIdx, bool initial)
{
if (_selectedItem)
{
if (_selectedItem->itemIdx == itemIdx)
return;
if (_selectedItem->itemIdx < _curRangeStart ||
_selectedItem->itemIdx >= _curRangeStart + _curRangeLength)
{
ReleaseViewPoolEntry(_selectedItem->itemIdx);
}
_selectedItem = nullptr;
}
if (itemIdx < 0 || itemIdx >= (int)_itemCount)
return;
if (itemIdx >= _curRangeStart &&
itemIdx < _curRangeStart + _curRangeLength)
{
_selectedItem = GetViewPoolEntryByItemIndex(itemIdx);
}
else
{
_selectedItem = BindViewPoolEntry(itemIdx);
}
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
UpdateItemPosition(i, initial);
}
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <array>
#include "gui/views/RecyclerViewBase.h"
class CoverFlowRecyclerViewBase : public RecyclerViewBase
{
public:
void InitVram(const VramContext& vramContext) override;
void SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex = 0) override;
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
Rectangle GetBounds() const override
{
return Rectangle(_position, 256, 160);
}
void Focus(FocusManager& focusManager) override
{
focusManager.Focus(_selectedItem ? _selectedItem->view : this);
}
int GetSelectedItem() const override
{
return _selectedItem ? _selectedItem->itemIdx : -1;
}
protected:
struct ViewPoolEntry
{
View* view;
int itemIdx = -1;
};
std::array<ViewPoolEntry, 10> _viewPool;
u32 _viewPoolFreeCount;
u32 _itemCount;
ViewPoolEntry* _selectedItem = nullptr;
int _curRangeStart = 0;
int _curRangeLength = 0;
ViewPoolEntry* GetViewPoolEntryByItemIndex(int itemIdx);
ViewPoolEntry* BindViewPoolEntry(int itemIdx);
void BindRange(int start, int end);
void ReleaseViewPoolEntry(int itemIdx);
void ReleaseRange(int start, int end);
void SetSelectedItem(int itemIdx, bool initial);
virtual void UpdateItemPosition(int viewPoolIndex, bool initial) = 0;
virtual void SwapViewPoolEntry(int indexA, int indexB)
{
std::swap(_viewPool[indexA], _viewPool[indexB]);
}
};

View File

@@ -0,0 +1,95 @@
#include "common.h"
#include "core/math/SinTable.h"
#include "gui/VramContext.h"
#include "gui/Gx.h"
#include "gui/materialDesign.h"
#include "gui/GraphicsContext.h"
#include "CoverView.h"
void CoverView::InitVram(const VramContext& vramContext)
{
const auto texVramManager = vramContext.GetTexVramManager();
const auto texPlttVramManager = vramContext.GetTexPlttVramManager();
if (texVramManager && texPlttVramManager)
{
_texVramOffset = texVramManager->Alloc(128 * 96);
_plttVramOffset = texPlttVramManager->Alloc(256 * 2);
}
}
void CoverView::Draw(GraphicsContext& graphicsContext)
{
if (_cover.IsValid() && _textureLoadRequest.GetState() == VBlankTextureLoadRequestState::LoadComplete)
{
Gx::TexImageParam(_texVramOffset >> 3, false, true, false, true, GX_TEXSIZE_128,
GX_TEXSIZE_128, GX_TEXFMT_PLTT256, false, GX_TEXGEN_NONE);
Gx::TexPlttBase(_plttVramOffset >> 4);
u32 polygonId = graphicsContext.GetPolygonId();
Gx::PolygonAttr(GX_LIGHTMASK_0, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, polygonId);
auto halfWidth = fix16<12>::FromRawValue(COVER_WIDTH << 8);
auto halfHeight = fix16<12>::FromRawValue((COVER_HEIGHT / 6) << 8);
Gx::Begin(GX_PRIMITIVE_QUAD);
{
Gx::Normal(0, 0, 0x1FF);
Gx::TexCoord(0 + 0.25, -COVER_HEIGHT + 0.25);
Gx::Vtx16(-halfWidth, -halfHeight, 0);
Gx::TexCoord(0 + 0.25, 0 + 0.25);
Gx::VtxXY(-halfWidth, halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.25, 0 + 0.25);
Gx::VtxXY(halfWidth, halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.25, -COVER_HEIGHT + 0.25);
Gx::VtxXY(halfWidth, -halfHeight);
}
Gx::End();
Gx::PolygonAttr(GX_LIGHTMASK_0, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
false, false, false, GX_DEPTH_FUNC_EQUAL, false, 16, polygonId);
Gx::Begin(GX_PRIMITIVE_QUAD);
{
Gx::Normal(0, 0, 0x1FF);
Gx::TexCoord(0 + 0.75, -COVER_HEIGHT + 0.75);
Gx::Vtx16(-halfWidth, -halfHeight, 0);
Gx::TexCoord(0 + 0.75, 0 + 0.75);
Gx::VtxXY(-halfWidth, halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.75, 0 + 0.75);
Gx::VtxXY(halfWidth, halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.75, -COVER_HEIGHT + 0.75);
Gx::VtxXY(halfWidth, -halfHeight);
}
Gx::End();
for (int i = 0; i < 20; ++i)
{
u32 alpha = 20 - i;
Gx::PolygonAttr(GX_LIGHTMASK_0, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
false, false, false, GX_DEPTH_FUNC_LESS, false, alpha, polygonId);
Gx::Begin(GX_PRIMITIVE_QUAD);
{
Gx::Normal(0, 0, 0x1FF);
Gx::TexCoord(0 + 0.5, fix16<4>(i) + 0.5);
Gx::Vtx16(-halfWidth, fix16<12>::FromRawValue(((COVER_HEIGHT + i) << 9) / 6) - halfHeight, 0);
Gx::TexCoord(0 + 0.5, fix16<4>(i) + 1 + 0.5);
Gx::VtxXY(-halfWidth, fix16<12>::FromRawValue(((COVER_HEIGHT + i + 1) << 9) / 6) - halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.5, fix16<4>(i) + 1 + 0.5);
Gx::VtxXY(halfWidth, fix16<12>::FromRawValue(((COVER_HEIGHT + i + 1) << 9) / 6) - halfHeight);
Gx::TexCoord(COVER_WIDTH + 0.5, fix16<4>(i) + 0.5);
Gx::VtxXY(halfWidth, fix16<12>::FromRawValue(((COVER_HEIGHT + i) << 9) / 6) - halfHeight);
}
Gx::End();
}
}
}
void CoverView::UploadCoverGraphics()
{
if (_cover.IsValid())
{
_cover->SetTexVramOffset(_texVramOffset, _plttVramOffset);
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
_textureLoadRequest = _cover->CreateTextureLoadRequest();
_vblankTextureLoader->RequestLoad(_textureLoadRequest);
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <memory>
#include "core/SharedPtr.h"
#include "gui/views/View.h"
#include "../FileType/FileCover.h"
#include "gui/VBlankTextureLoader.h"
#define COVER_THICKNESS (fix32<12>(0.23).GetRawValue())
class CoverView : public View
{
public:
explicit CoverView(VBlankTextureLoader* vblankTextureLoader)
: _vblankTextureLoader(vblankTextureLoader) { }
~CoverView() override
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
void InitVram(const VramContext& vramContext) override;
void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override
{
return Rectangle(_position.x - (COVER_WIDTH / 2), _position.y - (COVER_HEIGHT / 2), COVER_WIDTH, COVER_HEIGHT);
}
void SetCover(SharedPtr<FileCover> cover)
{
if (_cover.IsValid())
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
_cover = std::move(cover);
}
void ClearCover()
{
if (_cover.IsValid())
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
_cover.Reset();
}
void UploadCoverGraphics();
private:
VBlankTextureLoader* _vblankTextureLoader;
SharedPtr<FileCover> _cover;
VBlankTextureLoadRequest _textureLoadRequest;
u32 _texVramOffset = 0;
u32 _plttVramOffset = 0;
};

View File

@@ -0,0 +1,359 @@
#include "common.h"
#include "gui/GraphicsContext.h"
#include "gui/VramContext.h"
#include "gui/IVramManager.h"
#include "hGridIcon.h"
#include "vGridIcon.h"
#include "bannerListIcon.h"
#include "listIcon.h"
#include "sortNameAscendingIcon.h"
#include "sortNameDescendingIcon.h"
#include "recentIcon.h"
#include "gamesIcon.h"
#include "picturesIcon.h"
#include "musicIcon.h"
#include "moviesIcon.h"
#include "unknownIcon.h"
#include "coverflowIcon.h"
#include "../IRomBrowserController.h"
#include "gui/input/InputProvider.h"
#include "themes/material/MaterialColorScheme.h"
#include "themes/IFontRepository.h"
#include "DisplaySettingsBottomSheetView.h"
#define TITLE_LABEL_X 20
#define TITLE_LABEL_Y 16
#define LAYOUT_LABEL_X 20
#define LAYOUT_LABEL_Y 46
#define SORTING_LABEL_X 20
#define SORTING_LABEL_Y 78
#define FILTERS_LABEL_X 20
#define FILTERS_LABEL_Y 112
static RomBrowserLayout sRomBrowserDisplayModes[4] =
{
[0] = RomBrowserLayout::HorizontalIconGrid,
[1] = RomBrowserLayout::VerticalIconGrid,
[2] = RomBrowserLayout::BannerList,
[3] = RomBrowserLayout::CoverFlow
};
static RomBrowserSortMode sRomBrowserSortModes[4] =
{
[0] = RomBrowserSortMode::NameAscending,
[1] = RomBrowserSortMode::NameDescending,
[2] = RomBrowserSortMode::LastModified
};
DisplaySettingsBottomSheetView::DisplaySettingsBottomSheetView(
DisplaySettingsViewModel* viewModel, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository)
: _viewModel(viewModel)
, _titleLabel(128, 16, 25, fontRepository->GetFont(FontType::Medium11))
, _layoutLabel(64, 16, 25, fontRepository->GetFont(FontType::Regular10))
, _sortingLabel(64, 16, 25, fontRepository->GetFont(FontType::Regular10))
, _materialColorScheme(materialColorScheme)
// , _filtersLabel(64, 16, 25, fontRepository->GetFont(FontType::Regular10))
{
_titleLabel.SetText(u"Display Settings");
AddChildTail(&_titleLabel);
_layoutLabel.SetText(u"Layout");
AddChildTail(&_layoutLabel);
_sortingLabel.SetText(u"Sorting");
AddChildTail(&_sortingLabel);
// _filtersLabel.SetText(u"Filters");
// AddChildTail(&_filtersLabel);
for (auto& layoutOption : _layoutOptions)
{
layoutOption = CreateLayoutOptionIconButton();
AddChildTail(&layoutOption);
}
for (auto& sortOption : _sortOptions)
{
sortOption = CreateSortOptionIconButton();
AddChildTail(&sortOption);
}
// for (auto& filterOption : _filterOptions)
// {
// filterOption = CreateFilterOptionIconButton();
// AddChildTail(&filterOption);
// }
// _filterOptions[0].SetState(IconButtonView::State::ToggleSelected);
}
IconButton2DView DisplaySettingsBottomSheetView::CreateLayoutOptionIconButton()
{
IconButton2DView layoutOption
{
IconButtonView::Type::Tonal,
IconButtonView::State::ToggleUnselected,
md::sys::color::surfaceContainerLow,
_materialColorScheme
};
layoutOption.SetAction([] (IconButtonView* sender, void* arg)
{
auto self = reinterpret_cast<DisplaySettingsBottomSheetView*>(arg);
u32 idx = ((IconButton2DView*)sender) - &self->_layoutOptions[0];
self->_viewModel->SetRomBrowserDisplayMode(sRomBrowserDisplayModes[idx]);
}, this);
return layoutOption;
}
IconButton2DView DisplaySettingsBottomSheetView::CreateSortOptionIconButton()
{
IconButton2DView sortOption
{
IconButtonView::Type::Tonal,
IconButtonView::State::ToggleUnselected,
md::sys::color::surfaceContainerLow,
_materialColorScheme
};
sortOption.SetAction([] (IconButtonView* sender, void* arg)
{
auto self = reinterpret_cast<DisplaySettingsBottomSheetView*>(arg);
u32 idx = ((IconButton2DView*)sender) - &self->_sortOptions[0];
self->_viewModel->SetRomBrowserSortMode(sRomBrowserSortModes[idx]);
}, this);
return sortOption;
}
// IconButtonView DisplaySettingsBottomSheetView::CreateFilterOptionIconButton()
// {
// IconButtonView filterOption
// {
// IconButtonView::Type::Tonal,
// IconButtonView::State::ToggleUnselected,
// md::sys::color::surfaceContainerLow,
// _materialColorScheme
// };
// return filterOption;
// }
void DisplaySettingsBottomSheetView::InitVram(const VramContext& vramContext)
{
BottomSheetView::InitVram(vramContext);
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
// layout options
_layoutOptions[0].SetIconVramOffset(LoadIcon(*objVramManager, hGridIconTiles, hGridIconTilesLen));
_layoutOptions[1].SetIconVramOffset(LoadIcon(*objVramManager, vGridIconTiles, vGridIconTilesLen));
_layoutOptions[2].SetIconVramOffset(LoadIcon(*objVramManager, bannerListIconTiles, bannerListIconTilesLen));
_layoutOptions[3].SetIconVramOffset(LoadIcon(*objVramManager, coverflowIconTiles, coverflowIconTilesLen));
// sort options
_sortOptions[0].SetIconVramOffset(LoadIcon(*objVramManager, sortNameAscendingIconTiles, sortNameAscendingIconTilesLen));
_sortOptions[1].SetIconVramOffset(LoadIcon(*objVramManager, sortNameDescendingIconTiles, sortNameDescendingIconTilesLen));
// _sortOptions[2].SetIconVramOffset(LoadIcon(objVramManager, recentIconTiles, recentIconTilesLen));
// filter options
// _filterOptions[0].SetIconVramOffset(LoadIcon(objVramManager, gamesIconTiles, gamesIconTilesLen));
// _filterOptions[1].SetIconVramOffset(LoadIcon(objVramManager, picturesIconTiles, picturesIconTilesLen));
// _filterOptions[2].SetIconVramOffset(LoadIcon(objVramManager, musicIconTiles, musicIconTilesLen));
// _filterOptions[3].SetIconVramOffset(LoadIcon(objVramManager, moviesIconTiles, moviesIconTilesLen));
// _filterOptions[4].SetIconVramOffset(LoadIcon(objVramManager, unknownIconTiles, unknownIconTilesLen));
}
}
void DisplaySettingsBottomSheetView::UpdateLabels()
{
_titleLabel.SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y);
_layoutLabel.SetPosition(LAYOUT_LABEL_X, _position.y + LAYOUT_LABEL_Y);
_sortingLabel.SetPosition(SORTING_LABEL_X, _position.y + SORTING_LABEL_Y);
// _filtersLabel.SetPosition(FILTERS_LABEL_X, _position.y + FILTERS_LABEL_Y);
}
void DisplaySettingsBottomSheetView::Update()
{
BottomSheetView::Update();
UpdateLabels();
auto selectedDisplayMode = _viewModel->GetRomBrowserDisplayMode();
int x = 70;
u32 idx = 0;
for (auto& layoutOption : _layoutOptions)
{
layoutOption.SetPosition(x, _position.y + 38);
layoutOption.SetState(sRomBrowserDisplayModes[idx] == selectedDisplayMode
? IconButtonView::State::ToggleSelected
: IconButtonView::State::ToggleUnselected);
x += 32;
idx++;
}
auto selectedSortMode = _viewModel->GetRomBrowserSortMode();
x = 70;
idx = 0;
for (auto& sortOption : _sortOptions)
{
sortOption.SetPosition(x, _position.y + 70);
sortOption.SetState(sRomBrowserSortModes[idx] == selectedSortMode
? IconButtonView::State::ToggleSelected
: IconButtonView::State::ToggleUnselected);
x += 32;
idx++;
}
// x = 70;
// for (auto& filterOption : _filterOptions)
// {
// filterOption.SetPosition(x, _position.y + 102);
// x += 32;
// }
}
void DisplaySettingsBottomSheetView::Draw(GraphicsContext& graphicsContext)
{
graphicsContext.SetClipArea(GetBounds());
u32 oldPrio = graphicsContext.SetPriority(1);
{
_titleLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow));
_titleLabel.SetForegroundColor(_materialColorScheme->onSurface);
_layoutLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow));
_layoutLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
_sortingLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow));
_sortingLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
// _filtersLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow));
// _filtersLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
BottomSheetView::Draw(graphicsContext);
}
graphicsContext.SetPriority(oldPrio);
graphicsContext.ResetClipArea();
}
bool DisplaySettingsBottomSheetView::HandleInput(
const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::B))
{
_viewModel->Close();
return true;
}
return false;
}
View* DisplaySettingsBottomSheetView::MoveFocus(View* currentFocus,
FocusMoveDirection direction, View* source)
{
int idx = 0;
for (auto& layoutOption : _layoutOptions)
{
if (currentFocus == &layoutOption)
{
if (direction == FocusMoveDirection::Left)
{
if (--idx < 0)
idx += _layoutOptions.size();
return &_layoutOptions[idx];
}
else if (direction == FocusMoveDirection::Right)
{
if (++idx >= (int)_layoutOptions.size())
idx = 0;
return &_layoutOptions[idx];
}
// else if (direction == FocusMoveDirection::Up)
// {
// if (idx >= (int)_filterOptions.size())
// idx = _filterOptions.size() - 1;
// return &_filterOptions[idx];
// }
else //if (direction == FocusMoveDirection::Down)
{
if (idx >= (int)_sortOptions.size())
idx = _sortOptions.size() - 1;
return &_sortOptions[idx];
}
}
idx++;
}
idx = 0;
for (auto& sortOption : _sortOptions)
{
if (currentFocus == &sortOption)
{
if (direction == FocusMoveDirection::Left)
{
if (--idx < 0)
idx += _sortOptions.size();
return &_sortOptions[idx];
}
else if (direction == FocusMoveDirection::Right)
{
if (++idx >= (int)_sortOptions.size())
idx = 0;
return &_sortOptions[idx];
}
else //if (direction == FocusMoveDirection::Up)
{
if (idx >= (int)_layoutOptions.size())
idx = _layoutOptions.size() - 1;
return &_layoutOptions[idx];
}
// else //if (direction == FocusMoveDirection::Down)
// {
// if (idx >= (int)_filterOptions.size())
// idx = _filterOptions.size() - 1;
// return &_filterOptions[idx];
// }
}
idx++;
}
// idx = 0;
// for (auto& filterOption : _filterOptions)
// {
// if (currentFocus == &filterOption)
// {
// if (direction == FocusMoveDirection::Left)
// {
// if (--idx < 0)
// idx += _filterOptions.size();
// return &_filterOptions[idx];
// }
// else if (direction == FocusMoveDirection::Right)
// {
// if (++idx >= (int)_filterOptions.size())
// idx = 0;
// return &_filterOptions[idx];
// }
// else if (direction == FocusMoveDirection::Up)
// {
// if (idx >= (int)_sortOptions.size())
// idx = _sortOptions.size() - 1;
// return &_sortOptions[idx];
// }
// else //if (direction == FocusMoveDirection::Down)
// {
// if (idx >= (int)_layoutOptions.size())
// idx = _layoutOptions.size() - 1;
// return &_layoutOptions[idx];
// }
// }
// idx++;
// }
return nullptr;
}
void DisplaySettingsBottomSheetView::SetGraphics(
const IconButton2DView::VramToken& iconButtonVramToken)
{
for (auto& layoutOption : _layoutOptions)
layoutOption.SetGraphics(iconButtonVramToken);
for (auto& sortOption : _sortOptions)
sortOption.SetGraphics(iconButtonVramToken);
// for (auto& filterOption : _filterOptions)
// filterOption.SetGraphics(iconButtonVramToken);
}
u32 DisplaySettingsBottomSheetView::LoadIcon(IVramManager& vramManager,
const unsigned int* tiles, u32 tilesLength) const
{
u32 vramOffset = vramManager.Alloc(tilesLength);
dma_ntrCopy32(3, tiles, vramManager.GetVramAddress(vramOffset), tilesLength);
return vramOffset;
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <array>
#include "BottomSheetView.h"
#include "gui/views/Label2DView.h"
#include "IconButton2DView.h"
#include "../viewModels/DisplaySettingsViewModel.h"
class IRomBrowserController;
class MaterialColorScheme;
class IFontRepository;
class DisplaySettingsBottomSheetView : public BottomSheetView
{
public:
DisplaySettingsBottomSheetView(DisplaySettingsViewModel* viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository);
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
View* MoveFocus(View* currentFocus,
FocusMoveDirection direction, View* source) override;
void SetGraphics(const IconButton2DView::VramToken& iconButtonVramToken);
void Focus(FocusManager& focusManager) override
{
focusManager.Focus(&_layoutOptions[0]);
}
private:
DisplaySettingsViewModel* _viewModel;
Label2DView _titleLabel;
Label2DView _layoutLabel;
Label2DView _sortingLabel;
// LabelView _filtersLabel;
std::array<IconButton2DView, 4> _layoutOptions;
std::array<IconButton2DView, /*3*/2> _sortOptions;
// std::array<IconButton2DView, 5> _filterOptions;
const MaterialColorScheme* _materialColorScheme;
IconButton2DView CreateLayoutOptionIconButton();
IconButton2DView CreateSortOptionIconButton();
// IconButton2DView CreateFilterOptionIconButton();
void UpdateLabels();
u32 LoadIcon(IVramManager& vramManager, const unsigned int* tiles, u32 tilesLength) const;
};

View File

@@ -0,0 +1,85 @@
#include "common.h"
#include "gui/OamManager.h"
#include "gui/OamBuilder.h"
#include "gui/IVramManager.h"
#include "gui/GraphicsContext.h"
#include "gui/input/InputProvider.h"
#include "iconButtonSelector.h"
#include "core/math/RgbMixer.h"
#include "core/math/ColorConverter.h"
#include "gui/palette/GradientPalette.h"
#include "themes/material/MaterialColorScheme.h"
#include "IconButton2DView.h"
void IconButton2DView::Draw(GraphicsContext& graphicsContext)
{
if (!graphicsContext.IsVisible(GetBounds()))
return;
u32 iconPaletteRow;
if (_isFocused)
{
const auto& bgColor = _materialColorScheme->GetColor(_backgroundColor);
const auto& selectorBaseColor = _materialColorScheme->GetColor(GetCircleBackgroundColor());
const auto& fgColor = _materialColorScheme->GetColor(GetForegroundColor());
auto selectorColor = RgbMixer::Lerp(selectorBaseColor, fgColor, 12, 100);
u32 selectorPlttRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(bgColor, selectorColor), _position.y, _position.y + 32);
gfx_oam_entry_t* selectorOam = graphicsContext.GetOamManager().AllocOams(1);
OamBuilder::OamWithSize<32, 32>(
_position.x + 3,
_position.y + 3, _selectorVramOffset >> 7)
.WithPalette16(selectorPlttRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[0]);
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(selectorColor, fgColor), _position.y + 8, _position.y + 24);
}
else
{
if (IsCircleBackgroundVisible())
{
auto circleBgColor = GetCircleBackgroundColor();
u32 circlePaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_materialColorScheme->GetColor(_backgroundColor),
_materialColorScheme->GetColor(circleBgColor)),
_position.y, _position.y + 32);
gfx_oam_entry_t* selectorOam = graphicsContext.GetOamManager().AllocOams(1);
OamBuilder::OamWithSize<32, 32>(
_position.x + 3,
_position.y + 3, _selectorVramOffset >> 7)
.WithPalette16(circlePaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[0]);
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_materialColorScheme->GetColor(circleBgColor),
_materialColorScheme->GetColor(GetForegroundColor())),
_position.y + 8, _position.y + 24);
}
else
{
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_materialColorScheme->GetColor(_backgroundColor),
_materialColorScheme->GetColor(GetForegroundColor())),
_position.y + 8, _position.y + 24);
}
}
gfx_oam_entry_t* iconOam = graphicsContext.GetOamManager().AllocOams(1);
OamBuilder::OamWithSize<16, 16>(
_position.x + 8,
_position.y + 8, _iconVramOffset >> 7)
.WithPalette16(iconPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(iconOam[0]);
}
IconButton2DView::VramToken IconButton2DView::UploadGraphics(IVramManager& vramManager)
{
u32 vramOffset = vramManager.Alloc(iconButtonSelectorTilesLen);
dma_ntrCopy32(3, iconButtonSelectorTiles, vramManager.GetVramAddress(vramOffset), iconButtonSelectorTilesLen);
return IconButton2DView::VramToken(vramOffset);
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include "IconButtonView.h"
class IconButton2DView : public IconButtonView
{
public:
class VramToken
{
u32 _vramOffset;
public:
VramToken()
: _vramOffset(0) { }
explicit VramToken(u32 offset)
: _vramOffset(offset) { }
constexpr u32 GetVramOffset() const { return _vramOffset; }
};
IconButton2DView() : IconButtonView() { }
IconButton2DView(Type type, State state,
md::sys::color backgroundColor, const MaterialColorScheme* materialColorScheme)
: IconButtonView(type, state, backgroundColor, materialColorScheme) { }
void Draw(GraphicsContext& graphicsContext) override;
void SetGraphics(const VramToken& vramToken)
{
_selectorVramOffset = vramToken.GetVramOffset();
}
static VramToken UploadGraphics(IVramManager& vramManager);
private:
u32 _selectorVramOffset;
};

View File

@@ -0,0 +1,92 @@
#include "common.h"
#include "gui/Gx.h"
#include "gui/VramContext.h"
#include "gui/GraphicsContext.h"
#include "gui/OamBuilder.h"
#include "gui/input/InputProvider.h"
#include "iconButtonSelectorTexture.h"
#include "core/math/RgbMixer.h"
#include "core/math/ColorConverter.h"
#include "gui/palette/GradientPalette.h"
#include "themes/material/MaterialColorScheme.h"
#include "IconButton3DView.h"
u32 IconButton3DView::sSelectorTextureVramOffset = 0;
void IconButton3DView::Draw(GraphicsContext& graphicsContext)
{
if (!graphicsContext.IsVisible(GetBounds()))
return;
u32 iconPaletteRow;
if (_isFocused)
{
const auto& selectorBaseColor = _materialColorScheme->GetColor(GetCircleBackgroundColor());
const auto& fgColor = _materialColorScheme->GetColor(GetForegroundColor());
auto selectorColor = RgbMixer::Lerp(selectorBaseColor, fgColor, 12, 100);
DrawSelector(graphicsContext, selectorColor);
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(selectorColor, fgColor), _position.y + 8, _position.y + 24);
}
else
{
if (IsCircleBackgroundVisible())
{
auto circleBgColor = GetCircleBackgroundColor();
DrawSelector(graphicsContext, _materialColorScheme->GetColor(circleBgColor));
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_materialColorScheme->GetColor(circleBgColor),
_materialColorScheme->GetColor(GetForegroundColor())),
_position.y + 8, _position.y + 24);
}
else
{
iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(
_materialColorScheme->GetColor(_backgroundColor),
_materialColorScheme->GetColor(GetForegroundColor())),
_position.y + 8, _position.y + 24);
}
}
gfx_oam_entry_t* iconOam = graphicsContext.GetOamManager().AllocOams(1);
OamBuilder::OamWithSize<16, 16>(
_position.x + 8,
_position.y + 8, _iconVramOffset >> 7)
.WithPalette16(iconPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(iconOam[0]);
}
void IconButton3DView::UploadGraphics(const VramContext& vramContext)
{
const auto textureVramManager = vramContext.GetTexVramManager();
if (textureVramManager)
{
sSelectorTextureVramOffset = textureVramManager->Alloc(iconButtonSelectorTextureBitmapLen);
dma_ntrCopy32(3, iconButtonSelectorTextureBitmap, textureVramManager->GetVramAddress(sSelectorTextureVramOffset),
iconButtonSelectorTextureBitmapLen);
}
}
void IconButton3DView::DrawSelector(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& color)
{
Gx::MtxIdentity();
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 62);
Gx::TexImageParam(sSelectorTextureVramOffset >> 3, true, true, true, true, GX_TEXSIZE_16,
GX_TEXSIZE_16, GX_TEXFMT_A5I3, false, GX_TEXGEN_NONE);
graphicsContext.GetRgb6Palette()->ApplyColor(Rgb<6, 6, 6>(color));
Gx::Begin(GX_PRIMITIVE_QUAD);
Gx::TexCoord(0, 0);
Gx::Vtx16(fix16<12>(fix32<12>(_position.x) >> 6), fix16<12>(fix32<12>(_position.y) >> 9), -1.0 / 64);
Gx::TexCoord(0, 32);
Gx::Vtx16(fix16<12>(fix32<12>(_position.x) >> 6), fix16<12>(fix32<12>(_position.y + 32) >> 9), -1.0 / 64);
Gx::TexCoord(32, 32);
Gx::Vtx16(fix16<12>(fix32<12>(_position.x + 32) >> 6), fix16<12>(fix32<12>(_position.y + 32) >> 9), -1.0 / 64);
Gx::TexCoord(32, 0);
Gx::Vtx16(fix16<12>(fix32<12>(_position.x + 32) >> 6), fix16<12>(fix32<12>(_position.y) >> 9), -1.0 / 64);
Gx::End();
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include "IconButtonView.h"
#include "core/math/Rgb.h"
#include "gui/Rgb6Palette.h"
class IconButton3DView : public IconButtonView
{
public:
IconButton3DView() : IconButtonView() { }
IconButton3DView(Type type, State state,
md::sys::color backgroundColor, const MaterialColorScheme* materialColorScheme)
: IconButtonView(type, state, backgroundColor, materialColorScheme) { }
void Draw(GraphicsContext& graphicsContext) override;
static void UploadGraphics(const VramContext& vramContext);
private:
static u32 sSelectorTextureVramOffset;
void DrawSelector(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& color);
};

View File

@@ -0,0 +1,98 @@
#include "common.h"
#include "gui/input/InputProvider.h"
#include "IconButtonView.h"
bool IconButtonView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::A))
{
if (_action)
_action(this, _actionArg);
return true;
}
return View::HandleInput(inputProvider, focusManager);
}
bool IconButtonView::IsCircleBackgroundVisible() const
{
switch (_type)
{
case Type::Standard:
{
return false;
}
case Type::Filled:
case Type::Tonal:
{
return true;
}
default:
{
// shouldn't happen
return false;
}
}
}
md::sys::color IconButtonView::GetCircleBackgroundColor() const
{
switch (_type)
{
case Type::Standard:
{
return _backgroundColor;
}
case Type::Filled:
{
if (_state == State::ToggleUnselected)
return md::sys::color::surfaceContainerHighest;
else
return md::sys::color::primary;
}
case Type::Tonal:
{
if (_state == State::ToggleUnselected)
return md::sys::color::surfaceContainerHighest;
else
return md::sys::color::secondaryContainer;
}
default:
{
// shouldn't happen
return md::sys::color::onSurfaceVariant;
}
}
}
md::sys::color IconButtonView::GetForegroundColor() const
{
switch (_type)
{
case Type::Standard:
{
if (_state == State::ToggleSelected)
return md::sys::color::primary;
else
return md::sys::color::onSurfaceVariant;
}
case Type::Filled:
{
if (_state == State::ToggleUnselected)
return md::sys::color::primary;
else
return md::sys::color::onPrimary;
}
case Type::Tonal:
{
if (_state == State::ToggleUnselected)
return md::sys::color::onSurfaceVariant;
else
return md::sys::color::onSecondaryContainer;
}
default:
{
// shouldn't happen
return md::sys::color::onSurfaceVariant;
}
}
}

View File

@@ -0,0 +1,69 @@
#pragma once
#include "gui/views/View.h"
#include "gui/materialDesign.h"
class MaterialColorScheme;
class IVramManager;
class IconButtonView : public View
{
public:
typedef void (*button_action_t)(IconButtonView* sender, void* arg);
enum class Type
{
Standard,
Filled,
Tonal
};
enum class State
{
NoToggle,
ToggleUnselected,
ToggleSelected
};
IconButtonView()
: _iconVramOffset(0), _action(nullptr), _actionArg(nullptr)
, _type(Type::Standard), _state(State::NoToggle) { }
IconButtonView(Type type, State state,
md::sys::color backgroundColor, const MaterialColorScheme* materialColorScheme)
: _iconVramOffset(0), _backgroundColor(backgroundColor)
, _action(nullptr), _actionArg(nullptr), _type(type), _state(state)
, _materialColorScheme(materialColorScheme) { }
void SetIconVramOffset(u32 vramOffset) { _iconVramOffset = vramOffset; }
Rectangle GetBounds() const override
{
return Rectangle(_position, 32, 32);
}
void SetAction(button_action_t action, void* arg)
{
_action = action;
_actionArg = arg;
}
void SetState(State state)
{
_state = state;
}
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
protected:
u32 _iconVramOffset;
md::sys::color _backgroundColor;
button_action_t _action;
void* _actionArg;
Type _type;
State _state;
const MaterialColorScheme* _materialColorScheme;
bool IsCircleBackgroundVisible() const;
md::sys::color GetCircleBackgroundColor() const;
md::sys::color GetForegroundColor() const;
};

View File

@@ -0,0 +1,22 @@
#include "common.h"
#include "gui/IVramManager.h"
#include "gui/VramContext.h"
#include "IconGridItemView.h"
void IconGridItemView::InitVram(const VramContext& vramContext)
{
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_iconVramOffset = objVramManager->Alloc(FILE_ICON_VRAM_SIZE);
_iconVram = objVramManager->GetVramAddress(_iconVramOffset);
}
}
void IconGridItemView::Update()
{
if (_icon)
{
_icon->Update();
}
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <memory>
#include "gui/views/View.h"
#include "../FileType/FileIcon.h"
class MaterialColorScheme;
class IconGridItemView : public View
{
public:
class VramToken
{
u32 _vramOffset;
public:
VramToken()
: _vramOffset(0) { }
explicit VramToken(u32 offset)
: _vramOffset(offset) { }
constexpr u32 GetVramOffset() const { return _vramOffset; }
};
void InitVram(const VramContext& vramContext) override;
void Update() override;
void SetIcon(std::unique_ptr<FileIcon> icon)
{
_icon = std::move(icon);
}
void UploadIconGraphics() const
{
if (_icon)
{
_icon->UploadGraphics(_iconVram);
}
}
virtual void SetGraphics(const VramToken& vramToken) { }
protected:
std::unique_ptr<FileIcon> _icon;
vu16* _iconVram;
u32 _iconVramOffset;
IconGridItemView()
: _icon(nullptr) { }
};

View File

@@ -0,0 +1,80 @@
#include "common.h"
#include <libtwl/dma/dmaNitro.h>
#include "gui/IVramManager.h"
#include "gui/VramContext.h"
#include "gui/GraphicsContext.h"
#include "gui/input/InputProvider.h"
#include "smallHeartIcon.h"
#include "smallHeartIconFilled.h"
#include "../IRomBrowserController.h"
#include "NdsGameDetailsBottomSheetView.h"
NdsGameDetailsBottomSheetView::NdsGameDetailsBottomSheetView(
IRomBrowserController* romBrowserController, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository)
: _romBrowserController(romBrowserController)
, _cheatsChip(md::sys::color::surfaceContainerLow, materialColorScheme, fontRepository)
, _favoriteChip(md::sys::color::surfaceContainerLow, materialColorScheme, fontRepository)
{
_cheatsChip.SetText(u"Cheats");
_cheatsChip.SetSelected(false);
AddChildTail(&_cheatsChip);
_favoriteChip.SetText(u"Favorite");
_favoriteChip.SetSelected(true);
AddChildTail(&_favoriteChip);
}
void NdsGameDetailsBottomSheetView::InitVram(const VramContext& vramContext)
{
BottomSheetView::InitVram(vramContext);
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_smallHeartIconVramOffset = objVramManager->Alloc(smallHeartIconTilesLen);
dma_ntrCopy32(3, smallHeartIconTiles, objVramManager->GetVramAddress(_smallHeartIconVramOffset), smallHeartIconTilesLen);
_smallHeartIconFilledVramOffset = objVramManager->Alloc(smallHeartIconFilledTilesLen);
dma_ntrCopy32(3, smallHeartIconFilledTiles, objVramManager->GetVramAddress(_smallHeartIconFilledVramOffset), smallHeartIconFilledTilesLen);
_favoriteChip.SetIcon(true, _smallHeartIconFilledVramOffset);
}
}
void NdsGameDetailsBottomSheetView::Update()
{
BottomSheetView::Update();
_cheatsChip.SetPosition(92, _position.y + 21);
_favoriteChip.SetPosition(162, _position.y + 21);
}
void NdsGameDetailsBottomSheetView::Draw(GraphicsContext& graphicsContext)
{
graphicsContext.SetClipArea(GetBounds());
u32 oldPrio = graphicsContext.SetPriority(1);
{
BottomSheetView::Draw(graphicsContext);
}
graphicsContext.SetPriority(oldPrio);
graphicsContext.ResetClipArea();
}
View* NdsGameDetailsBottomSheetView::MoveFocus(View* currentFocus,
FocusMoveDirection direction, View* source)
{
if (currentFocus == &_cheatsChip && direction == FocusMoveDirection::Right)
return &_favoriteChip;
else if (currentFocus == &_favoriteChip && direction == FocusMoveDirection::Left)
return &_cheatsChip;
return nullptr;
}
bool NdsGameDetailsBottomSheetView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::B))
{
_romBrowserController->HideGameInfo();
return true;
}
return false;
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include "BottomSheetView.h"
#include "ChipView.h"
#include "gui/FocusManager.h"
class IRomBrowserController;
class IFontRepository;
class NdsGameDetailsBottomSheetView : public BottomSheetView
{
public:
NdsGameDetailsBottomSheetView(
IRomBrowserController* romBrowserController,
const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository);
void SetGraphics(const ChipView::VramToken& chipVramToken)
{
_cheatsChip.SetGraphics(chipVramToken);
_favoriteChip.SetGraphics(chipVramToken);
}
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
void Focus(FocusManager& focusManager) override
{
focusManager.Focus(&_cheatsChip);
}
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
private:
IRomBrowserController* _romBrowserController;
u32 _smallHeartIconVramOffset;
u32 _smallHeartIconFilledVramOffset;
ChipView _cheatsChip;
ChipView _favoriteChip;
};

View File

@@ -0,0 +1,133 @@
#include "common.h"
#include "../viewModels/RomBrowserAppBarViewModel.h"
#include "gui/GraphicsContext.h"
#include "gui/VramContext.h"
#include "backIcon.h"
#include "settingsIcon.h"
#include "heartIcon.h"
#include "recentIcon.h"
#include "hGridIcon.h"
#include "vGridIcon.h"
#include "bannerListIcon.h"
#include "coverflowIcon.h"
#include "listIcon.h"
#include "gui/IVramManager.h"
#include "../DisplayMode/RomBrowserDisplayMode.h"
#include "RomBrowserAppBarView.h"
RomBrowserAppBarView::RomBrowserAppBarView(
RomBrowserAppBarViewModel* viewModel, const RomBrowserDisplayMode& displayMode,
const IRomBrowserViewFactory* romBrowserViewFactory)
: _viewModel(viewModel)
{
_appBarView = displayMode.CreateAppBarView(romBrowserViewFactory, 1, 1);
_appBarView->SetParent(this);
_appBarView->SetButtonAction(APP_BAR_BUTTON_BACK, [] (IconButtonView* sender, void* arg)
{
((RomBrowserAppBarViewModel*)arg)->NavigateUp();
}, _viewModel);
_appBarView->SetButtonAction(APP_BAR_BUTTON_DISPLAY_SETTINGS, [] (IconButtonView* sender, void* arg)
{
((RomBrowserAppBarViewModel*)arg)->ShowDisplaySettings();
}, _viewModel);
}
void RomBrowserAppBarView::InitVram(const VramContext& vramContext)
{
_appBarView->InitVram(vramContext);
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
u32 backIconVramOffset = objVramManager->Alloc(backIconTilesLen);
dma_ntrCopy32(3, backIconTiles, objVramManager->GetVramAddress(backIconVramOffset), backIconTilesLen);
_appBarView->SetButtonIcon(APP_BAR_BUTTON_BACK, backIconVramOffset);
u32 settingsIconVramOffset = objVramManager->Alloc(settingsIconTilesLen);
dma_ntrCopy32(3, settingsIconTiles, objVramManager->GetVramAddress(settingsIconVramOffset), settingsIconTilesLen);
_appBarView->SetButtonIcon(APP_BAR_BUTTON_DISPLAY_SETTINGS, settingsIconVramOffset);
// u32 settingsIconVramOffset = objVramManager->Alloc(settingsIconTilesLen);
// dma_ntrCopy32(3, settingsIconTiles, objVramManager->GetVramAddress(settingsIconVramOffset), settingsIconTilesLen);
// _appBarView->SetButtonIcon(APP_BAR_BUTTON_SETTINGS, settingsIconVramOffset);
// u32 heartIconVramOffset = objVramManager->Alloc(heartIconTilesLen);
// dma_ntrCopy32(3, heartIconTiles, objVramManager->GetVramAddress(heartIconVramOffset), heartIconTilesLen);
// _appBarView->SetButtonIcon(APP_BAR_BUTTON_FAVORITE, heartIconVramOffset);
// u32 recentIconVramOffset = objVramManager->Alloc(recentIconTilesLen);
// dma_ntrCopy32(3, recentIconTiles, objVramManager->GetVramAddress(recentIconVramOffset), recentIconTilesLen);
// _appBarView->SetButtonIcon(APP_BAR_BUTTON_RECENT, recentIconVramOffset);
// u32 displaySettingsIconVramOffset;
// switch (_viewModel->GetRomBrowserLayout())
// {
// case RomBrowserLayout::HorizontalIconGrid:
// default:
// {
// displaySettingsIconVramOffset = objVramManager->Alloc(hGridIconTilesLen);
// dma_ntrCopy32(3, hGridIconTiles, objVramManager->GetVramAddress(displaySettingsIconVramOffset), hGridIconTilesLen);
// break;
// }
// case RomBrowserLayout::VerticalIconGrid:
// {
// displaySettingsIconVramOffset = objVramManager->Alloc(vGridIconTilesLen);
// dma_ntrCopy32(3, vGridIconTiles, objVramManager->GetVramAddress(displaySettingsIconVramOffset), vGridIconTilesLen);
// break;
// }
// case RomBrowserLayout::BannerList:
// {
// displaySettingsIconVramOffset = objVramManager->Alloc(bannerListIconTilesLen);
// dma_ntrCopy32(3, bannerListIconTiles, objVramManager->GetVramAddress(displaySettingsIconVramOffset), bannerListIconTilesLen);
// break;
// }
// case RomBrowserLayout::FileList:
// {
// displaySettingsIconVramOffset = objVramManager->Alloc(listIconTilesLen);
// dma_ntrCopy32(3, listIconTiles, objVramManager->GetVramAddress(displaySettingsIconVramOffset), listIconTilesLen);
// break;
// }
// case RomBrowserLayout::CoverFlow:
// {
// displaySettingsIconVramOffset = objVramManager->Alloc(coverflowIconTilesLen);
// dma_ntrCopy32(3, coverflowIconTiles, objVramManager->GetVramAddress(displaySettingsIconVramOffset), coverflowIconTilesLen);
// break;
// }
// }
// _appBarView->SetButtonIcon(APP_BAR_BUTTON_DISPLAY_SETTINGS, displaySettingsIconVramOffset);
}
}
void RomBrowserAppBarView::Update()
{
_appBarView->Update();
}
void RomBrowserAppBarView::Draw(GraphicsContext& graphicsContext)
{
_appBarView->Draw(graphicsContext);
}
void RomBrowserAppBarView::VBlank()
{
_appBarView->VBlank();
}
View* RomBrowserAppBarView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
{
if (currentFocus == nullptr)
{
return nullptr;
}
if (source == _appBarView.get())
{
return View::MoveFocus(currentFocus, direction, source);
}
else if (source == GetParent())
{
return _appBarView->MoveFocus(currentFocus, direction, this);
}
return nullptr;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "gui/views/View.h"
#include "AppBarView.h"
#include "../viewModels/RomBrowserAppBarViewModel.h"
class RomBrowserDisplayMode;
class IRomBrowserViewFactory;
class RomBrowserAppBarView : public View
{
public:
RomBrowserAppBarView(
RomBrowserAppBarViewModel* viewModel, const RomBrowserDisplayMode& displayMode,
const IRomBrowserViewFactory* romBrowserViewFactory);
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
void VBlank() override;
Rectangle GetBounds() const override
{
return Rectangle(0, 0, 256, 192);
}
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
void Focus(FocusManager& focusManager)
{
_appBarView->Focus(focusManager, 0);
}
private:
enum AppBarButton
{
APP_BAR_BUTTON_BACK = 0,
APP_BAR_BUTTON_DISPLAY_SETTINGS,
// APP_BAR_BUTTON_RECENT,
// APP_BAR_BUTTON_FAVORITE,
// APP_BAR_BUTTON_SETTINGS
};
RomBrowserAppBarViewModel* _viewModel;
std::unique_ptr<AppBarView> _appBarView;
};

View File

@@ -0,0 +1,118 @@
#include "common.h"
#include "../viewModels/RomBrowserViewModel.h"
#include "../views/IconGridItemView.h"
#include "gui/GraphicsContext.h"
#include "backIcon.h"
#include "settingsIcon.h"
#include "heartIcon.h"
#include "recentIcon.h"
#include "listIcon.h"
#include "gui/IVramManager.h"
#include "gui/input/InputProvider.h"
#include "RomBrowserBottomScreenView.h"
RomBrowserBottomScreenView::RomBrowserBottomScreenView(
RomBrowserBottomScreenViewModel* viewModel,
const RomBrowserDisplayMode* displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader)
: _viewModel(viewModel)
, _romBrowserViewFactory(romBrowserViewFactory)
, _romBrowserDisplayMode(displayMode)
, _themeFileIconFactory(themeFileIconFactory)
, _romBrowserAppBarView(_viewModel->GetRomBrowserAppBarViewModel(),
*displayMode, romBrowserViewFactory)
, _vblankTextureLoader(vblankTextureLoader)
{
_romBrowserAppBarView.SetParent(this);
}
void RomBrowserBottomScreenView::InitVram(const VramContext& vramContext)
{
_romBrowserAppBarView.InitVram(vramContext);
}
void RomBrowserBottomScreenView::Update()
{
_romBrowserAppBarView.Update();
if (_romBrowserView && _viewModel->IsRomBrowserVisible())
_romBrowserView->Update();
}
void RomBrowserBottomScreenView::Draw(GraphicsContext& graphicsContext)
{
_romBrowserAppBarView.Draw(graphicsContext);
if (_romBrowserView && _viewModel->IsRomBrowserVisible())
_romBrowserView->Draw(graphicsContext);
}
void RomBrowserBottomScreenView::VBlank()
{
_romBrowserAppBarView.VBlank();
if (_romBrowserView && _viewModel->IsRomBrowserVisible())
_romBrowserView->VBlank();
}
View* RomBrowserBottomScreenView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
{
if (currentFocus == nullptr)
{
return nullptr;
}
if (source == &_romBrowserAppBarView)
{
if (_romBrowserDisplayMode->IsVertical())
{
if (direction == FocusMoveDirection::Right)
return _romBrowserView->MoveFocus(currentFocus, direction, this);
}
else
{
if (direction == FocusMoveDirection::Down)
return _romBrowserView->MoveFocus(currentFocus, direction, this);
}
return nullptr;
}
else if (source == _romBrowserView.get())
{
if (_romBrowserDisplayMode->IsVertical())
{
if (direction == FocusMoveDirection::Left)
return _romBrowserAppBarView.MoveFocus(currentFocus, direction, this);
}
else
{
if (direction == FocusMoveDirection::Up)
return _romBrowserAppBarView.MoveFocus(currentFocus, direction, this);
}
return nullptr;
}
return nullptr;
}
bool RomBrowserBottomScreenView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::B))
{
_viewModel->NavigateUp();
return true;
}
return View::HandleInput(inputProvider, focusManager);
}
void RomBrowserBottomScreenView::RomBrowserViewModelInvalidated(const VramContext& vramContext)
{
if (_viewModel->GetRomBrowserViewModel().IsValid())
{
_romBrowserView = std::make_unique<RomBrowserView>(
_viewModel->GetRomBrowserViewModel(), *_romBrowserDisplayMode,
_themeFileIconFactory, _romBrowserViewFactory, _vblankTextureLoader);
_romBrowserView->SetParent(this);
_romBrowserView->InitVram(vramContext);
}
else
{
_romBrowserView.reset();
}
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include "AppBarView.h"
#include "gui/views/View.h"
#include "gui/views/RecyclerView.h"
#include "../FileRecyclerAdapter.h"
#include "../DisplayMode/RomBrowserDisplayMode.h"
#include "RomBrowserView.h"
#include "RomBrowserAppBarView.h"
#include "core/SharedPtr.h"
#include "../viewModels/RomBrowserBottomScreenViewModel.h"
class IRomBrowserViewFactory;
class VBlankTextureLoader;
class RomBrowserBottomScreenView : public View
{
public:
RomBrowserBottomScreenView(
RomBrowserBottomScreenViewModel* viewModel,
const RomBrowserDisplayMode* displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader);
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
void VBlank() override;
Rectangle GetBounds() const override
{
return Rectangle(0, 0, 256, 192);
}
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
void Focus(FocusManager& focusManager)
{
if (!_romBrowserView || !_romBrowserView->Focus(focusManager))
_romBrowserAppBarView.Focus(focusManager);
}
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
void RomBrowserViewModelInvalidated(const VramContext& vramContext);
bool IsAppBarFocused(const FocusManager& focusManager) const
{
return focusManager.IsFocusInside(&_romBrowserAppBarView);
}
private:
RomBrowserBottomScreenViewModel* _viewModel;
const IRomBrowserViewFactory* _romBrowserViewFactory;
const RomBrowserDisplayMode* _romBrowserDisplayMode;
const IThemeFileIconFactory* _themeFileIconFactory;
RomBrowserAppBarView _romBrowserAppBarView;
std::unique_ptr<RomBrowserView> _romBrowserView;
VBlankTextureLoader* _vblankTextureLoader;
};

View File

@@ -0,0 +1,151 @@
#include "common.h"
#include <libtwl/mem/memVram.h>
#include <libtwl/gfx/gfx.h>
#include <libtwl/gfx/gfxBackground.h>
#include <libtwl/gfx/gfxPalette.h>
#include <libtwl/gfx/gfxWindow.h>
#include "../viewModels/RomBrowserViewModel.h"
#include "gui/GraphicsContext.h"
#include "gui/IVramManager.h"
#include "themes/material/MaterialColorScheme.h"
#include "../Theme/IRomBrowserViewFactory.h"
#include "RomBrowserTopScreenView.h"
RomBrowserTopScreenView::RomBrowserTopScreenView(
const SharedPtr<RomBrowserViewModel>& viewModel,
const RomBrowserDisplayMode* displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory)
: _viewModel(viewModel)
, _themeFileIconFactory(themeFileIconFactory)
, _fileInfoView(romBrowserViewFactory->CreateFileInfoView())
, _showCover(displayMode->ShowCoverOnTopScreen())
{
AddChildTail(_fileInfoView.get());
}
void RomBrowserTopScreenView::InitVram(const VramContext& vramContext)
{
ViewContainer::InitVram(vramContext);
int tileIndex = 0;
vu16* mapPtr = (vu16*)((u8*)GFX_BG_SUB + 0x3800);
for (int y = 0; y < 12; y++)
{
for (int x = 0; x < 14; x++)
{
*mapPtr++ = tileIndex;
tileIndex++;
}
mapPtr += 2;
}
}
void RomBrowserTopScreenView::Update()
{
int selectedItem = _viewModel->GetSelectedItem();
if (selectedItem != _lastSelectedItem)
{
auto& fileInfoManager = _viewModel->GetFileInfoManager();
const auto& item = fileInfoManager.GetItem(selectedItem);
if (item.GetFileType()->HasInternalFileInfo())
{
auto info = fileInfoManager.GetInternalFileInfo(selectedItem);
if (info)
{
bool fileNameAsTitle = true;
const char16_t* gameTitle = info->GetGameTitle();
if (gameTitle)
{
_fileInfoView->SetGameTitleAsync(_viewModel->GetBgTaskQueue(), gameTitle);
fileNameAsTitle = false;
}
_selectedFileIcon = info->CreateGameIcon();
if (!_selectedFileIcon)
{
_selectedFileIcon = item.GetFileType()->CreateFileIcon("", _themeFileIconFactory);
}
if (_selectedFileIcon)
{
_selectedFileIcon->SetAnimFrame(_viewModel->GetIconFrameCounter());
_iconGraphicsUploaded = false;
}
_fileInfoView->SetIcon(std::move(_selectedFileIcon));
_fileInfoView->SetFileNameAsync(_viewModel->GetBgTaskQueue(), item.GetFileName(), fileNameAsTitle);
_lastSelectedItem = selectedItem;
auto cover = fileInfoManager.GetFileCover(selectedItem);
if (cover.IsValid())
{
_selectedFileCover = std::move(cover);
_coverGraphicsUploaded = false;
}
}
}
else
{
auto cover = fileInfoManager.GetFileCover(selectedItem);
if (cover.IsValid())
{
_selectedFileCover = std::move(cover);
_coverGraphicsUploaded = false;
_selectedFileIcon = item.GetFileType()->CreateFileIcon("", _themeFileIconFactory);
if (_selectedFileIcon)
{
_selectedFileIcon->SetAnimFrame(_viewModel->GetIconFrameCounter());
_iconGraphicsUploaded = false;
}
_fileInfoView->SetIcon(std::move(_selectedFileIcon));
_fileInfoView->SetFileNameAsync(_viewModel->GetBgTaskQueue(), item.GetFileName(), true);
_lastSelectedItem = selectedItem;
}
}
}
ViewContainer::Update();
}
void RomBrowserTopScreenView::VBlank()
{
ViewContainer::VBlank();
if (!_coverGraphicsUploaded && _selectedFileCover.IsValid())
{
if (_showCover && _selectedFileCover->IsActualCover())
{
_selectedFileCover->Upload2DCoverBitmap((u8*)GFX_BG_SUB + 0x4000);
mem_setVramHMapping(MEM_VRAM_H_LCDC);
_selectedFileCover->Upload2DCoverPalette((void*)0x0689E000);
GFX_PLTT_BG_SUB[0] = *(vu16*)0x0689E000;
mem_setVramHMapping(MEM_VRAM_H_SUB_BG_EXT_PLTT_SLOT_0123);
}
_coverGraphicsUploaded = true;
}
if (!_showCover || !_selectedFileCover.IsValid() || !_selectedFileCover->IsActualCover())
{
// hide cover
REG_DISPCNT_SUB &= ~(((1 << 3) | (1 << 5)) << 8);
}
else
{
// display cover
REG_BG3PA_SUB = 0x100;
REG_BG3PB_SUB = 0;
REG_BG3PC_SUB = 0;
REG_BG3PD_SUB = -0x100;
REG_BG3X_SUB = -75 << 8;
REG_BG3Y_SUB = 113 << 8;
REG_BG3CNT_SUB = 0x0705;
REG_DISPCNT_SUB |= ((1 << 3) | (1 << 5)) << 8;
gfx_setSubWindow0(75, 18, 75 + 106, 18 + 96);
REG_WININ_SUB = 0x002A;
REG_WINOUT_SUB = ~(1 << 3);
}
if (!_iconGraphicsUploaded)
{
_fileInfoView->UploadIconGraphics();
_iconGraphicsUploaded = true;
}
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "core/SharedPtr.h"
#include "gui/views/ViewContainer.h"
#include "BannerView.h"
#include "gui/views/LabelView.h"
#include "../FileType/FileIcon.h"
#include "../DisplayMode/RomBrowserDisplayMode.h"
class RomBrowserViewModel;
class IRomBrowserViewFactory;
class RomBrowserTopScreenView : public ViewContainer
{
public:
RomBrowserTopScreenView(const SharedPtr<RomBrowserViewModel>& viewModel,
const RomBrowserDisplayMode* displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory);
void InitVram(const VramContext& vramContext) override;
void Update() override;
void VBlank() override;
Rectangle GetBounds() const override
{
return Rectangle(0, 0, 256, 192);
}
private:
SharedPtr<RomBrowserViewModel> _viewModel;
const IThemeFileIconFactory* _themeFileIconFactory;
std::unique_ptr<BannerView> _fileInfoView;
std::unique_ptr<FileIcon> _selectedFileIcon;
SharedPtr<FileCover> _selectedFileCover;
int _lastSelectedItem = -1;
bool _iconGraphicsUploaded = false;
bool _coverGraphicsUploaded = false;
bool _showCover;
};

View File

@@ -0,0 +1,101 @@
#include "common.h"
#include "IconGridItemView.h"
#include "gui/GraphicsContext.h"
#include "gui/input/InputProvider.h"
#include "RomBrowserView.h"
RomBrowserView::RomBrowserView(
const SharedPtr<RomBrowserViewModel>& viewModel,
const RomBrowserDisplayMode& displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader)
: _viewModel(viewModel), _isVertical(displayMode.IsVertical())
{
_fileGridView = displayMode.CreateRecyclerView(romBrowserViewFactory);
_fileGridView->SetParent(this);
_fileRecyclerAdapter = displayMode.CreateRecyclerAdapter(
_viewModel.GetPointer(), themeFileIconFactory, romBrowserViewFactory, vblankTextureLoader);
}
RomBrowserView::~RomBrowserView()
{
_fileGridView.reset();
delete _fileRecyclerAdapter;
}
void RomBrowserView::InitVram(const VramContext& vramContext)
{
_fileRecyclerAdapter->InitVram(vramContext); // first initialize the shared vram for the items
_fileGridView->SetAdapter(_fileRecyclerAdapter, _viewModel->GetSelectedItem()); // set the adapter of the recycler
_fileGridView->InitVram(vramContext); // init the vram for the recycler and its items
}
void RomBrowserView::Update()
{
_fileRecyclerAdapter->SetIconFrameCounter(_viewModel->GetIconFrameCounter());
_fileGridView->Update();
_viewModel->SetSelectedItem(_fileGridView->GetSelectedItem());
}
void RomBrowserView::Draw(GraphicsContext& graphicsContext)
{
_fileGridView->Draw(graphicsContext);
}
void RomBrowserView::VBlank()
{
_fileGridView->VBlank();
}
View* RomBrowserView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
{
if (currentFocus == nullptr)
{
return nullptr;
}
if (source == GetParent())
{
if (_isVertical)
{
if (direction == FocusMoveDirection::Right)
{
return _fileGridView->MoveFocus(currentFocus, direction, this);
}
}
else
{
if (direction == FocusMoveDirection::Down)
{
return _fileGridView->MoveFocus(currentFocus, direction, this);
}
}
return nullptr;
}
else if (source == _fileGridView.get())
{
return View::MoveFocus(currentFocus, direction, source);
}
return nullptr;
}
bool RomBrowserView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::A))
{
if (focusManager.IsFocusInside(_fileGridView.get()))
{
_viewModel->ItemActivated();
return true;
}
}
else if (inputProvider.Triggered(InputKey::Y))
{
if (focusManager.IsFocusInside(_fileGridView.get()))
{
_viewModel->ShowGameInfo();
return true;
}
}
return View::HandleInput(inputProvider, focusManager);
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include "core/SharedPtr.h"
#include "../viewModels/RomBrowserViewModel.h"
#include "gui/views/RecyclerViewBase.h"
#include "../FileRecyclerAdapter.h"
#include "gui/views/View.h"
#include "../DisplayMode/RomBrowserDisplayMode.h"
#include "../Theme/IThemeFileIconFactory.h"
class IRomBrowserViewFactory;
class RomBrowserView : public View
{
public:
RomBrowserView(
const SharedPtr<RomBrowserViewModel>& viewModel,
const RomBrowserDisplayMode& displayMode,
const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader);
~RomBrowserView();
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
void VBlank() override;
Rectangle GetBounds() const override
{
return Rectangle(0, 0, 256, 192);
}
bool Focus(FocusManager& focusManager)
{
if (!_fileRecyclerAdapter || _fileRecyclerAdapter->GetItemCount() == 0)
return false;
_fileGridView->Focus(focusManager);
return true;
}
View* MoveFocus(
View* currentFocus, FocusMoveDirection direction, View* source) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
private:
SharedPtr<RomBrowserViewModel> _viewModel;
std::unique_ptr<RecyclerViewBase> _fileGridView;
FileRecyclerAdapter* _fileRecyclerAdapter;
bool _isVertical;
};