7 Commits

142 changed files with 3387 additions and 1234 deletions

View File

@@ -2,6 +2,16 @@
## [Unreleased] ## [Unreleased]
## [v1.3.0] - 18 Apr 2026
### Added
- Ability to set the position of the top screen cover image in custom themes
- Support for fast scrolling with the L and R buttons in coverflow display mode
- Support for touch input
### Fixed
- Use after free bug with the texture load request in Label3DView. This occurred for example when spamming B in banner list mode.
## [v1.2.0] - 29 Mar 2026 ## [v1.2.0] - 29 Mar 2026
### Added ### Added

View File

@@ -23,7 +23,7 @@ General usage documentation can be found here: [Usage](docs/Usage.md).
We recommend using WSL (Windows Subsystem for Linux), or MSYS2 to compile this repository. We recommend using WSL (Windows Subsystem for Linux), or MSYS2 to compile this repository.
The steps provided will assume you already have one of those environments set up. The steps provided will assume you already have one of those environments set up.
1. Install [BlocksDS](https://blocksds.skylyrac.net/docs/setup/options/) 1. Install [BlocksDS](https://blocksds.skylyrac.net/docs/setup/)
## Compiling ## Compiling

View File

@@ -88,6 +88,12 @@
"b": 200 "b": 200
} }
}, },
"topCover": {
"position": {
"x": 75,
"y": 18
}
},
"gridIcon": { "gridIcon": {
"blendColor": { "blendColor": {
"r": 200, "r": 200,

View File

@@ -30,6 +30,7 @@
#include "ExitMode.h" #include "ExitMode.h"
#include "Arm7State.h" #include "Arm7State.h"
#include "mmc/tmio.h" #include "mmc/tmio.h"
#include "touchScreen.h"
static NocashOutputStream sNocashOutputStream; static NocashOutputStream sNocashOutputStream;
static PlainLogger sPlainLogger = PlainLogger(LogLevel::All, std::unique_ptr<IOutputStream>(&sNocashOutputStream)); static PlainLogger sPlainLogger = PlainLogger(LogLevel::All, std::unique_ptr<IOutputStream>(&sNocashOutputStream));
@@ -42,19 +43,14 @@ static RtcIpcService sRtcIpcService;
ILogger* gLogger = &sThreadSafeLogger; ILogger* gLogger = &sThreadSafeLogger;
static rtos_event_t sVBlankEvent; static rtos_event_t sVCountEvent;
static ExitMode sExitMode; static ExitMode sExitMode;
static Arm7State sState; static Arm7State sState;
static volatile u8 sMcuIrqFlag = false; static volatile u8 sMcuIrqFlag = false;
static void vblankIrq(u32 irqMask)
{
rtos_signalEvent(&sVBlankEvent);
}
static void vcountIrq(u32 irqMask) static void vcountIrq(u32 irqMask)
{ {
SHARED_KEY_XY = REG_RCNT0_H; rtos_signalEvent(&sVCountEvent);
} }
static void mcuIrq(u32 irq2Mask) static void mcuIrq(u32 irq2Mask)
@@ -88,12 +84,13 @@ static void checkMcuIrq(void)
} }
} }
static void initializeVBlankIrq() static void initializeVCountIrq()
{ {
rtos_createEvent(&sVBlankEvent); rtos_createEvent(&sVCountEvent);
rtos_setIrqFunc(RTOS_IRQ_VBLANK, vblankIrq); gfx_setVCountMatchLine(96);
rtos_enableIrqMask(RTOS_IRQ_VBLANK); rtos_setIrqFunc(RTOS_IRQ_VCOUNT, vcountIrq);
gfx_setVBlankIrqEnabled(true); rtos_enableIrqMask(RTOS_IRQ_VCOUNT);
gfx_setVCountMatchIrqEnabled(true);
} }
static void clearSoundRegisters() static void clearSoundRegisters()
@@ -145,12 +142,7 @@ static void initializeArm7()
sSoundIpcService.Start(); sSoundIpcService.Start();
sRtcIpcService.Start(); sRtcIpcService.Start();
gfx_setVCountMatchLine(96); initializeVCountIrq();
rtos_setIrqFunc(RTOS_IRQ_VCOUNT, vcountIrq);
rtos_enableIrqMask(RTOS_IRQ_VCOUNT);
gfx_setVCountMatchIrqEnabled(true);
initializeVBlankIrq();
if (isDSiMode()) if (isDSiMode())
{ {
@@ -158,6 +150,8 @@ static void initializeArm7()
rtos_enableIrq2Mask(RTOS_IRQ2_MCU); rtos_enableIrq2Mask(RTOS_IRQ2_MCU);
} }
touch_init();
ipc_setArm7SyncBits(7); ipc_setArm7SyncBits(7);
} }
@@ -233,7 +227,16 @@ int main()
while (true) while (true)
{ {
rtos_waitEvent(&sVBlankEvent, true, true); rtos_waitEvent(&sVCountEvent, true, true);
u16 keys = REG_RCNT0_H | RCNT0_H_DATA_PEN;
touchPosition touchPos;
if (touch_update(touchPos))
{
keys &= ~RCNT0_H_DATA_PEN; // pen down
SHARED_TOUCH_X = touchPos.px;
SHARED_TOUCH_Y = touchPos.py;
}
SHARED_KEY_XY = keys;
updateArm7(); updateArm7();
} }

146
arm7/source/touchScreen.cpp Normal file
View File

@@ -0,0 +1,146 @@
#include "common.h"
#include <nds/input.h>
#include <nds/arm7/touch.h>
// See: https://github.com/blocksds/libnds/blob/master/source/arm7/input.c
// === Touchscreen filter configuration ===
// Replace Z1/Z2 values with X/Y noisiness measurements.
// #define TOUCH_DEBUG_NOISINESS
// The number of frames to debounce/hold pen presses for.
// Set to 0 to disable.
#define PEN_DOWN_DEBOUNCE 1
// The shift (1 << N) used for the IIR filter to average noisy samples across
// time. Set to 0 to disable.
#define TOUCH_MAX_NOISE_PEN_UP_IIR_SHIFT 5
// The maximum value of noisiness for pressing a pen down (measurement now valid).
#define TOUCH_MAX_NOISE_PEN_DOWN 38
// The minimum value of noisiness for lifting a pen up (measurement no longer valid).
#define TOUCH_MAX_NOISE_PEN_UP 50
// === Touchscreen filter ===
// IIR filter constants.
#define TOUCH_MAX_NOISE_PEN_UP_IIR_RATIO (1 << TOUCH_MAX_NOISE_PEN_UP_IIR_SHIFT)
#define TOUCH_MAX_NOISE_PEN_UP_IIR_MIN (TOUCH_MAX_NOISE_PEN_UP - TOUCH_MAX_NOISE_PEN_UP_IIR_RATIO)
typedef struct {
u16 value; // 1..4095, 0 if invalid
u16 noisiness; // 0..4095, ~15-16 = 1 pixel
} libnds_touchMeasurementFilterResult;
/**
* @brief Perform filtering on the raw touch samples provided to return one
* averaged sample and an estimate of how noisy it is, while skipping outliers.
*
* Internal. See touchFilter.c for more information.
*/
extern "C" libnds_touchMeasurementFilterResult libnds_touchMeasurementFilter(u16 values[5]);
void touch_init()
{
touchInit();
}
bool touch_update(touchPosition& touchPos)
{
#if PEN_DOWN_DEBOUNCE > 0
static touchPosition lastTouchPosition;
static bool lastPenDown = false;
static u8 penDownDebounce = 0;
#else
touchPosition lastTouchPosition;
bool lastPenDown = false;
#endif
bool penDown = touchPenDown();
if (penDown)
{
// Set penDown to false for later fallthroughs to noPenDown.
// It will be set to true if all the touch filtering ensures the readout is valid.
penDown = false;
// Measure new touch position.
touchRawArray data;
if (!touchReadData(&data))
goto noPenDown;
libnds_touchMeasurementFilterResult rawXresult = libnds_touchMeasurementFilter(data.rawX);
if (!rawXresult.value)
goto noPenDown;
libnds_touchMeasurementFilterResult rawYresult = libnds_touchMeasurementFilter(data.rawY);
if (!rawYresult.value)
goto noPenDown;
// Valid sample read.
u16 noisiness = rawXresult.noisiness > rawYresult.noisiness ? rawXresult.noisiness : rawYresult.noisiness;
if (noisiness <= (lastPenDown ? TOUCH_MAX_NOISE_PEN_UP : TOUCH_MAX_NOISE_PEN_DOWN))
{
lastTouchPosition.z1 = libnds_touchMeasurementFilter(data.z1).value;
lastTouchPosition.z2 = libnds_touchMeasurementFilter(data.z2).value;
#if TOUCH_MAX_NOISE_PEN_UP_IIR_SHIFT > 0
// Apply an IIR filter on noisy X/Y samples.
// Skip the IIR filter if the pen was just pressed.
int n = (noisiness - TOUCH_MAX_NOISE_PEN_UP_IIR_MIN);
if (noisiness <= 0 || !lastPenDown)
{
lastTouchPosition.rawx = rawXresult.value;
lastTouchPosition.rawy = rawYresult.value;
}
else if (noisiness <= TOUCH_MAX_NOISE_PEN_UP_IIR_RATIO)
{
lastTouchPosition.rawx =
((rawXresult.value * (TOUCH_MAX_NOISE_PEN_UP_IIR_RATIO - n))
+ (lastTouchPosition.rawx * n)) >> TOUCH_MAX_NOISE_PEN_UP_IIR_SHIFT;
lastTouchPosition.rawy =
((rawYresult.value * (TOUCH_MAX_NOISE_PEN_UP_IIR_RATIO - n))
+ (lastTouchPosition.rawy * n)) >> TOUCH_MAX_NOISE_PEN_UP_IIR_SHIFT;
}
#else
lastTouchPosition.rawx = rawXresult.value;
lastTouchPosition.rawy = rawYresult.value;
#endif
touchApplyCalibration(lastTouchPosition.rawx, lastTouchPosition.rawy, &lastTouchPosition.px, &lastTouchPosition.py);
penDown = true;
}
#ifdef TOUCH_DEBUG_NOISINESS
lastTouchPosition.z1 = rawXresult.noisiness;
lastTouchPosition.z2 = rawYresult.noisiness;
#endif
}
noPenDown:
#if PEN_DOWN_DEBOUNCE > 0
// Perform simple debouncing.
// Hold new presses for PEN_DOWN_DEBOUNCE frames.
if (!penDownDebounce)
{
if (lastPenDown != penDown)
{
lastPenDown = penDown;
if (penDown)
penDownDebounce = PEN_DOWN_DEBOUNCE;
}
}
else
{
penDownDebounce--;
}
#else
lastPenDown = penDown;
#endif
// Return the touch position and pen down.
if (lastPenDown)
{
touchPos = lastTouchPosition;
}
return lastPenDown;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include <nds/touch.h>
void touch_init();
bool touch_update(touchPosition& touchPos);

7
arm9/gfx/upIcon.grit Normal file
View File

@@ -0,0 +1,7 @@
# tile format
-gt
# graphics bit depth is 4 (16 color)
-gB4
-p!

BIN
arm9/gfx/upIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

View File

@@ -43,7 +43,7 @@ App::App(IAppSettingsService& appSettingsService, IBgmService& bgmService)
, _subVramContext(nullptr, &_subObjVram, nullptr, nullptr) , _subVramContext(nullptr, &_subObjVram, nullptr, nullptr)
, _appSettingsService(appSettingsService) , _appSettingsService(appSettingsService)
, _bgmService(bgmService) , _bgmService(bgmService)
, _inputProvider(&_inputSource) , _inputProvider(&_keyInputSource, &_touchInputSource)
, _inputRepeater(&_inputProvider, , _inputRepeater(&_inputProvider,
InputKey::DpadLeft | InputKey::DpadRight | InputKey::DpadUp | InputKey::DpadDown | InputKey::L | InputKey::R, InputKey::DpadLeft | InputKey::DpadRight | InputKey::DpadUp | InputKey::DpadDown | InputKey::L | InputKey::R,
25, 8) 25, 8)
@@ -134,7 +134,7 @@ void App::Run()
StoreVramState(_vramStateBeforeMakeBottomScreenView); StoreVramState(_vramStateBeforeMakeBottomScreenView);
_romBrowserBottomScreenView = std::make_unique<RomBrowserBottomScreenView>( _romBrowserBottomScreenView = RomBrowserBottomScreenView::CreateShared(
&_romBrowserBottomScreenViewModel, &_romBrowserBottomScreenViewModel,
RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode( RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode(
_romBrowserController.GetRomBrowserDisplaySettings().layout), _romBrowserController.GetRomBrowserDisplaySettings().layout),
@@ -301,8 +301,8 @@ void App::HandleShowGameInfoTrigger()
// gameInfoDialog->SetGraphics(_chipViewVram); // gameInfoDialog->SetGraphics(_chipViewVram);
// _dialogPresenter.ShowDialog(std::move(gameInfoDialog)); // _dialogPresenter.ShowDialog(std::move(gameInfoDialog));
auto cheatsViewModel = std::make_unique<CheatsViewModel>(_romBrowserController.GetTriggerFileInfo(), &_romBrowserController); auto cheatsViewModel = SharedPtr<CheatsViewModel>::MakeShared(_romBrowserController.GetTriggerFileInfo(), &_romBrowserController);
auto cheatsDialog = std::make_unique<CheatsBottomSheetView>( auto cheatsDialog = CheatsBottomSheetView::CreateShared(
std::move(cheatsViewModel), &_theme->GetMaterialColorScheme(), _theme->GetFontRepository(), &_focusManager); std::move(cheatsViewModel), &_theme->GetMaterialColorScheme(), _theme->GetFontRepository(), &_focusManager);
_dialogPresenter.ShowDialog(std::move(cheatsDialog)); _dialogPresenter.ShowDialog(std::move(cheatsDialog));
} }
@@ -316,7 +316,7 @@ void App::HandleHideGameInfoTrigger()
void App::HandleShowDisplaySettingsTrigger() void App::HandleShowDisplaySettingsTrigger()
{ {
auto displaySettingsDialog = std::make_unique<DisplaySettingsBottomSheetView>( auto displaySettingsDialog = DisplaySettingsBottomSheetView::CreateShared(
&_displaySettingsBottomSheetViewModel, &_theme->GetMaterialColorScheme(), _theme->GetFontRepository()); &_displaySettingsBottomSheetViewModel, &_theme->GetMaterialColorScheme(), _theme->GetFontRepository());
displaySettingsDialog->SetGraphics(_iconButtonViewVram); displaySettingsDialog->SetGraphics(_iconButtonViewVram);
_dialogPresenter.ShowDialog(std::move(displaySettingsDialog)); _dialogPresenter.ShowDialog(std::move(displaySettingsDialog));
@@ -337,11 +337,11 @@ void App::HandleNavigateTrigger()
void App::HandleFolderLoadDoneTrigger() void App::HandleFolderLoadDoneTrigger()
{ {
_romBrowserTopScreenView.reset(); _romBrowserTopScreenView.Reset();
RestoreVramState(_vramStateAfterMakeBottomScreenView); RestoreVramState(_vramStateAfterMakeBottomScreenView);
auto displayMode = RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode( auto displayMode = RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode(
_romBrowserController.GetRomBrowserDisplaySettings().layout); _romBrowserController.GetRomBrowserDisplaySettings().layout);
_romBrowserTopScreenView = std::make_unique<RomBrowserTopScreenView>( _romBrowserTopScreenView = RomBrowserTopScreenView::CreateShared(
_romBrowserController.GetRomBrowserViewModel(), _romBrowserController.GetRomBrowserViewModel(),
displayMode, displayMode,
_materialThemeFileIconFactory.get(), _materialThemeFileIconFactory.get(),
@@ -358,7 +358,7 @@ void App::HandleChangeDisplayModeTrigger(RomBrowserState newState)
RestoreVramState(_vramStateBeforeMakeBottomScreenView); RestoreVramState(_vramStateBeforeMakeBottomScreenView);
auto displayMode = RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode( auto displayMode = RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode(
_romBrowserController.GetRomBrowserDisplaySettings().layout); _romBrowserController.GetRomBrowserDisplaySettings().layout);
_romBrowserBottomScreenView = std::make_unique<RomBrowserBottomScreenView>( _romBrowserBottomScreenView = RomBrowserBottomScreenView::CreateShared(
&_romBrowserBottomScreenViewModel, &_romBrowserBottomScreenViewModel,
displayMode, displayMode,
_materialThemeFileIconFactory.get(), _materialThemeFileIconFactory.get(),
@@ -366,7 +366,7 @@ void App::HandleChangeDisplayModeTrigger(RomBrowserState newState)
&_vblankTextureLoader); &_vblankTextureLoader);
_romBrowserBottomScreenView->InitVram(_mainVramContext); _romBrowserBottomScreenView->InitVram(_mainVramContext);
StoreVramState(_vramStateAfterMakeBottomScreenView); StoreVramState(_vramStateAfterMakeBottomScreenView);
_romBrowserTopScreenView = std::make_unique<RomBrowserTopScreenView>( _romBrowserTopScreenView = RomBrowserTopScreenView::CreateShared(
_romBrowserController.GetRomBrowserViewModel(), _romBrowserController.GetRomBrowserViewModel(),
displayMode, displayMode,
_materialThemeFileIconFactory.get(), _materialThemeFileIconFactory.get(),
@@ -405,7 +405,7 @@ void App::Update()
bool isRomBrowserVisible = IsRomBrowserVisible(); bool isRomBrowserVisible = IsRomBrowserVisible();
if (isRomBrowserVisible && !_exit && curState != RomBrowserState::Launching) if (isRomBrowserVisible && !_exit && curState != RomBrowserState::Launching)
{ {
_focusManager.Update(_inputRepeater); HandleInput();
} }
if (_topBackground) if (_topBackground)
@@ -523,3 +523,49 @@ void App::RestoreVramState(const VramState& vramState)
_texturePaletteVram.SetState(vramState._texPlttVramState); _texturePaletteVram.SetState(vramState._texPlttVramState);
_subObjVram.SetState(vramState._subObjVramState); _subObjVram.SetState(vramState._subObjVramState);
} }
void App::HandleInput()
{
_focusManager.Update(_inputRepeater);
Point touchPoint;
if (_inputRepeater.Triggered(InputKey::Touch) &&
_inputRepeater.GetCurrentTouchPoint(touchPoint))
{
// pen down
if (_dialogPresenter.IsBottomSheetVisible())
{
_dialogPresenter.HandlePenDown(touchPoint, _focusManager);
}
else
{
_romBrowserBottomScreenView->HandlePenDown(touchPoint, _focusManager);
}
_lastTouchPoint = touchPoint;
}
else if (_inputRepeater.Released(InputKey::Touch))
{
// pen up
if (_dialogPresenter.IsBottomSheetVisible())
{
_dialogPresenter.HandlePenUp(_lastTouchPoint, _focusManager);
}
else
{
_romBrowserBottomScreenView->HandlePenUp(_lastTouchPoint, _focusManager);
}
}
else if (_inputRepeater.Current(InputKey::Touch)
&& _inputRepeater.GetCurrentTouchPoint(touchPoint))
{
// pen move
if (_dialogPresenter.IsBottomSheetVisible())
{
_dialogPresenter.HandlePenMove(touchPoint, _focusManager);
}
else
{
_romBrowserBottomScreenView->HandlePenMove(touchPoint, _focusManager);
}
_lastTouchPoint = touchPoint;
}
}

View File

@@ -12,6 +12,7 @@
#include "gui/DescendingStackVramManager.h" #include "gui/DescendingStackVramManager.h"
#include "material/scheme/scheme.h" #include "material/scheme/scheme.h"
#include "gui/input/PadInputSource.h" #include "gui/input/PadInputSource.h"
#include "gui/input/TouchInputSource.h"
#include "gui/input/SampledInputProvider.h" #include "gui/input/SampledInputProvider.h"
#include "gui/input/InputRepeater.h" #include "gui/input/InputRepeater.h"
#include "gui/VBlankTextureLoader.h" #include "gui/VBlankTextureLoader.h"
@@ -28,7 +29,6 @@
#include "romBrowser/RomBrowserController.h" #include "romBrowser/RomBrowserController.h"
#include "DialogPresenter.h" #include "DialogPresenter.h"
#include "themes/ITheme.h" #include "themes/ITheme.h"
#include "core/SharedPtr.h"
#include "animation/Animator.h" #include "animation/Animator.h"
class alignas(32) App : public IProcess class alignas(32) App : public IProcess
@@ -63,9 +63,9 @@ private:
Rgb6Palette _rgb6Palette; Rgb6Palette _rgb6Palette;
Animator<int> _fadeAnimator; Animator<int> _fadeAnimator;
TaskQueue<32, 32> _ioTaskQueue; TaskQueue<32, sizeof(TaskBase) + 32> _ioTaskQueue;
u32 _ioTaskThreadStack[2048 / 4]; u32 _ioTaskThreadStack[2048 / 4];
TaskQueue<32, 32> _bgTaskQueue; TaskQueue<32, sizeof(TaskBase) + 32> _bgTaskQueue;
u32 _bgTaskThreadStack[2048 / 4]; u32 _bgTaskThreadStack[2048 / 4];
std::unique_ptr<ITheme> _theme; std::unique_ptr<ITheme> _theme;
@@ -76,12 +76,13 @@ private:
IBgmService& _bgmService; IBgmService& _bgmService;
volatile bool _exit = false; volatile bool _exit = false;
PadInputSource _inputSource; PadInputSource _keyInputSource;
TouchInputSource _touchInputSource;
SampledInputProvider _inputProvider; SampledInputProvider _inputProvider;
InputRepeater _inputRepeater; InputRepeater _inputRepeater;
std::unique_ptr<RomBrowserBottomScreenView> _romBrowserBottomScreenView; SharedPtr<RomBrowserBottomScreenView> _romBrowserBottomScreenView;
std::unique_ptr<RomBrowserTopScreenView> _romBrowserTopScreenView; SharedPtr<RomBrowserTopScreenView> _romBrowserTopScreenView;
RomBrowserController _romBrowserController; RomBrowserController _romBrowserController;
@@ -104,10 +105,13 @@ private:
bool _vcountIrqStarted = false; bool _vcountIrqStarted = false;
Point _lastTouchPoint = Point(0, 0);
void InitVramMapping() const; void InitVramMapping() const;
void DisplaySplashScreen() const; void DisplaySplashScreen() const;
void LoadTheme(); void LoadTheme();
void VCountIrq(); void VCountIrq();
void HandleInput();
void HandleTrigger(RomBrowserStateTrigger trigger, RomBrowserState newState); void HandleTrigger(RomBrowserStateTrigger trigger, RomBrowserState newState);
void HandleShowGameInfoTrigger(); void HandleShowGameInfoTrigger();
void HandleHideGameInfoTrigger(); void HandleHideGameInfoTrigger();

View File

@@ -16,10 +16,12 @@ DialogPresenter::DialogPresenter(FocusManager* focusManager, StackVramManager* v
_baseVramState = _vramManager->GetState(); _baseVramState = _vramManager->GetState();
} }
void DialogPresenter::ShowDialog(std::unique_ptr<DialogView> dialog) void DialogPresenter::ShowDialog(SharedPtr<DialogView> dialog)
{ {
if (!_nextDialog) if (!_nextDialog)
{
_nextDialog = std::move(dialog); _nextDialog = std::move(dialog);
}
} }
void DialogPresenter::CloseDialog() void DialogPresenter::CloseDialog()
@@ -93,7 +95,7 @@ void DialogPresenter::Update()
else else
{ {
_newState = State::Idle; _newState = State::Idle;
_currentDialog.reset(); _currentDialog.Reset();
} }
break; break;
} }
@@ -152,4 +154,28 @@ void DialogPresenter::InitVram()
REG_BLDCNT = 0x3944; REG_BLDCNT = 0x3944;
REG_BLDALPHA = (16 << 8) | 0; REG_BLDALPHA = (16 << 8) | 0;
} }
void DialogPresenter::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
if (_curState == State::BottomSheetVisible && _currentDialog)
{
_currentDialog->HandlePenDown(touchPoint, focusManager);
}
}
void DialogPresenter::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
if (_curState == State::BottomSheetVisible && _currentDialog)
{
_currentDialog->HandlePenMove(touchPoint, focusManager);
}
}
void DialogPresenter::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
if (_curState == State::BottomSheetVisible && _currentDialog)
{
_currentDialog->HandlePenUp(lastTouchPoint, focusManager);
}
}

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include "core/SharedPtr.h"
#include "animation/Animator.h" #include "animation/Animator.h"
#include "gui/views/DialogView.h" #include "gui/views/DialogView.h"
@@ -14,7 +15,7 @@ public:
/// @brief Requests to show the given dialog. /// @brief Requests to show the given dialog.
/// @param dialog The dialog to show. /// @param dialog The dialog to show.
void ShowDialog(std::unique_ptr<DialogView> dialog); void ShowDialog(SharedPtr<DialogView> dialog);
/// @brief Closes the current dialog. /// @brief Closes the current dialog.
void CloseDialog(); void CloseDialog();
@@ -41,6 +42,21 @@ public:
/// @brief Initializes vram that is needed for showing dialogs. /// @brief Initializes vram that is needed for showing dialogs.
void InitVram(); void InitVram();
/// @brief Handles a pen down event.
/// @param touchPoint The touch point.
/// @param focusManager The focus manager.
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager);
/// @brief Handles a pen move event.
/// @param touchPoint The touch point.
/// @param focusManager The focus manager.
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager);
/// @brief Handles a pen up event.
/// @param lastTouchPoint The last touch point.
/// @param focusManager The focus manager.
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager);
/// @brief Clears the focus that was stored when a dialog was opened. /// @brief Clears the focus that was stored when a dialog was opened.
void ClearOldFocus() void ClearOldFocus()
{ {
@@ -49,11 +65,16 @@ public:
/// @brief Gets the focus that was stored when a dialog was opened. /// @brief Gets the focus that was stored when a dialog was opened.
/// @return The view that was focused when the current dialog was opened. /// @return The view that was focused when the current dialog was opened.
constexpr View* GetOldFocus() const constexpr SharedPtr<View> GetOldFocus() const
{ {
return _oldFocus; return _oldFocus;
} }
bool IsBottomSheetVisible() const
{
return _curState != State::Idle;
}
private: private:
enum class State enum class State
{ {
@@ -65,10 +86,10 @@ private:
FocusManager* _focusManager; FocusManager* _focusManager;
StackVramManager* _vramManager; StackVramManager* _vramManager;
u32 _baseVramState; u32 _baseVramState;
std::unique_ptr<DialogView> _currentDialog; SharedPtr<DialogView> _currentDialog;
std::unique_ptr<DialogView> _nextDialog; SharedPtr<DialogView> _nextDialog;
bool _initVram = false; bool _initVram = false;
View* _oldFocus = nullptr; SharedPtr<View> _oldFocus = nullptr;
Animator<int> _scrimAnimator; Animator<int> _scrimAnimator;
Animator<int> _yAnimator; Animator<int> _yAnimator;
State _curState = State::Idle; State _curState = State::Idle;

View File

@@ -0,0 +1,35 @@
#include "common.h"
#include <libtwl/rtos/rtosIrq.h>
#include "AtomicSharedPtr.h"
void AtomicSharedPtrBase::Reset(void* newObject, RefCount* newRefCount, bool increaseNewRefCount)
{
u32 irq = rtos_disableIrqs(); // 1
auto refCount = _refCount;
_object = newObject;
_refCount = newRefCount;
if (increaseNewRefCount && _refCount)
{
_refCount->refCount++;
}
if (refCount && --refCount->refCount == 0) [[gnu::unlikely]]
{
refCount->weakRefCount++; // ensure the ref count is not destructed elsewhere
rtos_restoreIrqs(irq); // 1
refCount->DestructObject();
irq = rtos_disableIrqs(); // 2
if (--refCount->weakRefCount == 0) [[gnu::unlikely]]
{
rtos_restoreIrqs(irq); // 2
delete refCount;
}
else
{
rtos_restoreIrqs(irq); // 2
}
}
else
{
rtos_restoreIrqs(irq); // 1
}
}

View File

@@ -0,0 +1,134 @@
#pragma once
#include <type_traits>
#include <libtwl/rtos/rtosIrq.h>
#include "SharedPtr.h"
class AtomicSharedPtrBase
{
public:
void Reset()
{
Reset(nullptr, nullptr, false);
}
protected:
void* volatile _object;
RefCount* volatile _refCount;
AtomicSharedPtrBase()
: _object(nullptr), _refCount(nullptr) { }
AtomicSharedPtrBase(void* object, RefCount* refCount)
: _object(object), _refCount(refCount) { }
~AtomicSharedPtrBase()
{
Reset(nullptr, nullptr, false);
}
void Reset(void* newObject, RefCount* newRefCount, bool increaseNewRefCount);
};
template <class T>
class AtomicSharedPtr : public AtomicSharedPtrBase
{
public:
AtomicSharedPtr() { }
AtomicSharedPtr(std::nullptr_t) { }
AtomicSharedPtr(const SharedPtr<T>& sharedPtr)
: AtomicSharedPtrBase(sharedPtr._object, sharedPtr._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
template <class Y> requires std::assignable_from<T*&, Y*>
AtomicSharedPtr(const SharedPtr<Y>& sharedPtr)
: AtomicSharedPtrBase(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
template <class Y>
explicit AtomicSharedPtr(const SharedPtr<Y>& sharedPtr)
: AtomicSharedPtrBase(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
AtomicSharedPtr(SharedPtr<T>&& sharedPtr)
: AtomicSharedPtrBase(sharedPtr._object, sharedPtr._refCount)
{
sharedPtr._object = nullptr;
sharedPtr._refCount = nullptr;
}
template <class Y> requires std::assignable_from<T*&, Y*>
AtomicSharedPtr(SharedPtr<Y>&& sharedPtr)
: AtomicSharedPtrBase(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount)
{
sharedPtr._object = nullptr;
sharedPtr._refCount = nullptr;
}
template <class Y>
explicit AtomicSharedPtr(SharedPtr<Y>&& sharedPtr)
: AtomicSharedPtrBase(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount)
{
sharedPtr._object = nullptr;
sharedPtr._refCount = nullptr;
}
AtomicSharedPtr& operator=(const SharedPtr<T>& sharedPtr)
{
Reset(sharedPtr._object, sharedPtr._refCount, true);
return *this;
}
template <class Y> requires std::assignable_from<T*&, Y*>
AtomicSharedPtr<T>& operator=(const SharedPtr<Y>& sharedPtr)
{
Reset(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount, true);
return *this;
}
AtomicSharedPtr& operator=(SharedPtr<T>&& sharedPtr)
{
Reset(sharedPtr._object, sharedPtr._refCount, false);
sharedPtr._object = nullptr;
sharedPtr._refCount = nullptr;
return *this;
}
template <class Y> requires std::assignable_from<T*&, Y*>
AtomicSharedPtr<T>& operator=(SharedPtr<Y>&& sharedPtr)
{
Reset(static_cast<T*>(sharedPtr.GetPointer()), sharedPtr._refCount, false);
sharedPtr._object = nullptr;
sharedPtr._refCount = nullptr;
return *this;
}
SharedPtr<T> Lock() const
{
u32 irq = rtos_disableIrqs();
auto object = static_cast<T*>(_object);
auto refCount = _refCount;
if (refCount)
{
refCount->refCount++;
}
rtos_restoreIrqs(irq);
return SharedPtr<T>(object, refCount);
}
};

View File

@@ -0,0 +1,42 @@
#pragma once
#include "SharedPtr.h"
#include "WeakPtr.h"
class EnableSharedFromThisBase
{
template <class Y>
friend class SharedPtr;
template <class Y>
friend class EnableSharedFromThis;
private:
EnableSharedFromThisBase() = default;
};
template <class T>
class EnableSharedFromThis : public EnableSharedFromThisBase
{
template <class Y>
friend class SharedPtr;
public:
SharedPtr<T> SharedFromThis()
{
return __sharedFromThisWeakPtr.Lock();
}
WeakPtr<T> WeakFromThis()
{
return __sharedFromThisWeakPtr;
}
private:
WeakPtr<T> __sharedFromThisWeakPtr;
template <class Y>
void __SetSharedFromThisWeakPtr(const SharedPtr<Y>& sharedPtr)
{
__sharedFromThisWeakPtr = WeakPtr<Y>(sharedPtr.GetPointer(), sharedPtr._refCount);
}
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include <array>
extern "C" void shared_ptr_increase_ref_count(vu32& refCount);
class RefCount
{
public:
vu32 refCount;
vu32 weakRefCount;
virtual ~RefCount() = default;
virtual void DestructObject() = 0;
protected:
explicit RefCount()
: refCount(1), weakRefCount(0) { }
};
template <class T>
class StandaloneRefCount : public RefCount
{
public:
explicit StandaloneRefCount(T* object)
: _object(object) { }
void DestructObject() final
{
delete _object;
}
private:
T* _object;
};
template <class T>
class alignas(T) MakeSharedRefCount : public RefCount
{
public:
explicit MakeSharedRefCount(auto&&... args)
{
new (_object.data()) T(std::forward<decltype(args)>(args)...);
}
T* GetObject()
{
return reinterpret_cast<T*>(_object.data());
}
void DestructObject() final
{
reinterpret_cast<T*>(_object.data())->~T();
}
private:
std::array<u8, sizeof(T)> _object alignas(T);
};

View File

@@ -0,0 +1,31 @@
#include "common.h"
#include <libtwl/rtos/rtosIrq.h>
#include "SharedPtr.h"
void SharedPtrBase::ResetIntern()
{
auto refCount = _refCount;
_object = nullptr;
_refCount = nullptr;
u32 irq = rtos_disableIrqs(); // 1
if (--refCount->refCount == 0) [[gnu::unlikely]]
{
refCount->weakRefCount++; // ensure the ref count is not destructed elsewhere
rtos_restoreIrqs(irq); // 1
refCount->DestructObject();
irq = rtos_disableIrqs(); // 2
if (--refCount->weakRefCount == 0) [[gnu::unlikely]]
{
rtos_restoreIrqs(irq); // 2
delete refCount;
}
else
{
rtos_restoreIrqs(irq); // 2
}
}
else
{
rtos_restoreIrqs(irq); // 1
}
}

View File

@@ -1,163 +1,216 @@
#pragma once #pragma once
#include <type_traits>
#include "RefCount.h"
static inline u32 arm_getCpsr() class EnableSharedFromThisBase;
{
u32 cpsr;
asm volatile("mrs %0, cpsr" : "=r" (cpsr));
return cpsr;
}
static inline void arm_setCpsrControl(u32 cpsrControl)
{
asm volatile("msr cpsr_c, %0" :: "r" (cpsrControl) : "cc");
}
static inline u32 arm_disableIrqs(void)
{
u32 oldCpsr = arm_getCpsr();
arm_setCpsrControl(oldCpsr | 0x80);
return oldCpsr;
}
static inline void arm_restoreIrqs(u32 oldCpsr)
{
arm_setCpsrControl(oldCpsr);
}
template <class T> template <class T>
class SharedPtr class EnableSharedFromThis;
class SharedPtrBase
{ {
T* _pointer;
vu32* _refCount;
public: public:
SharedPtr() void Reset()
: _pointer(nullptr), _refCount(nullptr) { (void)sizeof(T); }
explicit SharedPtr(T* pointer)
: _pointer(pointer), _refCount(pointer ? new u32(1) : nullptr) { (void)sizeof(T); }
SharedPtr(const SharedPtr& other)
{ {
u32 irq = arm_disableIrqs(); if (_refCount != nullptr)
_pointer = other._pointer;
_refCount = other._refCount;
if (_pointer)
{ {
(*_refCount)++; ResetIntern();
} }
arm_restoreIrqs(irq);
} }
SharedPtr(SharedPtr&& other) protected:
: _pointer(other._pointer), _refCount(other._refCount) void* _object;
{ RefCount* _refCount;
other._pointer = nullptr;
other._refCount = nullptr;
}
~SharedPtr() SharedPtrBase()
: _object(nullptr), _refCount(nullptr) { }
SharedPtrBase(void* object, RefCount* refCount)
: _object(object), _refCount(refCount) { }
SharedPtrBase(const void* object, RefCount* refCount)
: _object((void*)object), _refCount(refCount) { }
~SharedPtrBase()
{ {
Reset(); Reset();
} }
[[gnu::noinline]] void ResetIntern();
};
template <class T>
class SharedPtr : public SharedPtrBase
{
template <class Y> friend class WeakPtr;
template <class Y> friend class SharedPtr;
template <class Y> friend class AtomicSharedPtr;
template <class Y> friend class EnableSharedFromThis;
public:
SharedPtr() { }
SharedPtr(std::nullptr_t) { }
explicit SharedPtr(T* object)
: SharedPtrBase(object, object == nullptr ? nullptr : new StandaloneRefCount<T>(object))
{
if (_object != nullptr)
{
if constexpr (std::is_convertible<T*, EnableSharedFromThisBase*>::value)
{
_refCount->weakRefCount = 1;
GetPointer()->__SetSharedFromThisWeakPtr(*this);
}
}
}
template <class Y> requires std::assignable_from<T*&, Y*>
explicit SharedPtr(Y* object)
: SharedPtrBase(static_cast<T*>(object), object == nullptr ? nullptr : new StandaloneRefCount<Y>(object))
{
if (object != nullptr)
{
if constexpr (std::is_convertible<Y*, EnableSharedFromThisBase*>::value)
{
_refCount->weakRefCount = 1;
GetPointer()->__SetSharedFromThisWeakPtr(*this);
}
}
}
SharedPtr(const SharedPtr& other)
: SharedPtrBase(other._object, other._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
template <class Y> requires std::assignable_from<T*&, Y*>
SharedPtr(const SharedPtr<Y>& other)
: SharedPtrBase(static_cast<T*>(other.GetPointer()), other._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
template <class Y>
explicit SharedPtr(const SharedPtr<Y>& other)
: SharedPtrBase(static_cast<T*>(other.GetPointer()), other._refCount)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->refCount);
}
}
SharedPtr(SharedPtr&& other)
: SharedPtrBase(other._object, other._refCount)
{
other._object = nullptr;
other._refCount = nullptr;
}
template <class Y> requires std::assignable_from<T*&, Y*>
SharedPtr(SharedPtr<Y>&& other)
: SharedPtrBase(static_cast<T*>(other.GetPointer()), other._refCount)
{
other._object = nullptr;
other._refCount = nullptr;
}
template <class Y>
explicit SharedPtr(SharedPtr<Y>&& other)
: SharedPtrBase(static_cast<T*>(other.GetPointer()), other._refCount)
{
other._object = nullptr;
other._refCount = nullptr;
}
static SharedPtr<T> MakeShared(auto&&... args)
{
auto refCount = new MakeSharedRefCount<T>(std::forward<decltype(args)>(args)...);
return SharedPtr<T>(refCount->GetObject(), refCount, true);
}
SharedPtr& operator=(const SharedPtr& other) SharedPtr& operator=(const SharedPtr& other)
{ {
u32 irq = arm_disableIrqs(); Reset();
T* pointer = _pointer; _object = other._object;
if (pointer) _refCount = other._refCount;
if (_refCount)
{ {
vu32* refCount = _refCount; shared_ptr_increase_ref_count(_refCount->refCount);
u32 newValue = *refCount - 1; }
*refCount = newValue; return *this;
_pointer = other._pointer; }
_refCount = other._refCount;
if (_pointer) template <class Y> requires std::assignable_from<T*&, Y*>
{ SharedPtr<T>& operator=(const SharedPtr<Y>& other)
(*_refCount)++; {
} Reset();
arm_restoreIrqs(irq); _object = static_cast<T*>(other.GetPointer());
if (newValue == 0) _refCount = other._refCount;
{ if (_refCount)
delete pointer; {
delete refCount; shared_ptr_increase_ref_count(_refCount->refCount);
}
}
else
{
_pointer = other._pointer;
_refCount = other._refCount;
if (_pointer)
{
(*_refCount)++;
}
arm_restoreIrqs(irq);
} }
return *this; return *this;
} }
[[gnu::noinline]]
SharedPtr& operator=(SharedPtr&& other) SharedPtr& operator=(SharedPtr&& other)
{ {
u32 irq = arm_disableIrqs(); Reset();
T* pointer = _pointer; _object = other._object;
if (pointer) _refCount = other._refCount;
{ other._object = nullptr;
vu32* refCount = _refCount; other._refCount = nullptr;
u32 newValue = *refCount - 1;
*refCount = newValue;
_pointer = other._pointer;
_refCount = other._refCount;
other._pointer = nullptr;
other._refCount = nullptr;
arm_restoreIrqs(irq);
if (newValue == 0)
{
delete pointer;
delete refCount;
}
}
else
{
_pointer = other._pointer;
_refCount = other._refCount;
other._pointer = nullptr;
other._refCount = nullptr;
arm_restoreIrqs(irq);
}
return *this; return *this;
} }
[[gnu::noinline]] template <class Y> requires std::assignable_from<T*&, Y*>
void Reset() SharedPtr<T>& operator=(SharedPtr<Y>&& other)
{ {
u32 irq = arm_disableIrqs(); Reset();
T* pointer = _pointer; _object = static_cast<T*>(other.GetPointer());
if (pointer) _refCount = other._refCount;
{ other._object = nullptr;
vu32* refCount = _refCount; other._refCount = nullptr;
u32 newValue = *refCount - 1; return *this;
*refCount = newValue;
_pointer = nullptr;
_refCount = nullptr;
arm_restoreIrqs(irq);
if (newValue == 0)
{
delete pointer;
delete refCount;
}
}
else
{
arm_restoreIrqs(irq);
}
} }
constexpr T& operator*() const { return *_pointer; } T& operator*() const { return *static_cast<T*>(_object); }
constexpr T* operator->() const { return _pointer; } T* operator->() const { return static_cast<T*>(_object); }
T* GetPointer() const { return static_cast<T*>(_object); }
constexpr T* GetPointer() const { return _pointer; } bool IsValid() const { return _object != nullptr; }
constexpr u32 GetRefCount() const { return _refCount ? *_refCount : 0; } operator bool() const { return _object != nullptr; }
constexpr bool IsValid() const { return _pointer; }
private:
SharedPtr(T* object, RefCount* refCount)
: SharedPtrBase(object, refCount) { }
SharedPtr(T* object, RefCount* refCount, bool doSharedFromThis)
: SharedPtrBase(object, refCount)
{
if (doSharedFromThis)
{
if constexpr (std::is_convertible<T*, EnableSharedFromThisBase*>::value)
{
_refCount->weakRefCount = 1;
GetPointer()->__SetSharedFromThisWeakPtr(*this);
}
}
}
}; };
#define SHARED_ONLY(className) \
friend class MakeSharedRefCount<className>; \
public: \
static SharedPtr<className> CreateShared(auto&&... args) \
{ return SharedPtr<className>::MakeShared(std::forward<decltype(args)>(args)...); } \
private:

View File

@@ -0,0 +1,15 @@
.section .itcm
.arm
// r0 = &refCount
.global shared_ptr_increase_ref_count
.type shared_ptr_increase_ref_count, %function
shared_ptr_increase_ref_count:
mrs r2, cpsr
orr r1, r2, #0x80
msr cpsr_c, r1
ldr r12, [r0]
add r12, r12, #1
str r12, [r0]
msr cpsr_c, r2
bx lr

View File

@@ -0,0 +1,35 @@
#include "common.h"
#include <libtwl/rtos/rtosIrq.h>
#include "WeakPtr.h"
void WeakPtrBase::ResetIntern()
{
u32 irq = rtos_disableIrqs();
auto refCount = _refCount;
if (--refCount->weakRefCount == 0)
{
_refCount = nullptr;
rtos_restoreIrqs(irq);
delete refCount;
}
else
{
rtos_restoreIrqs(irq);
}
}
bool WeakPtrBase::LockIntern() const
{
u32 irq = rtos_disableIrqs();
if (_refCount->refCount != 0)
{
_refCount->refCount++;
rtos_restoreIrqs(irq);
return true;
}
else
{
rtos_restoreIrqs(irq);
return false;
}
}

158
arm9/source/core/WeakPtr.h Normal file
View File

@@ -0,0 +1,158 @@
#pragma once
#include <type_traits>
#include "RefCount.h"
#include "SharedPtr.h"
class WeakPtrBase
{
public:
~WeakPtrBase()
{
Reset();
}
void Reset()
{
if (_refCount)
{
Reset();
}
}
protected:
RefCount* _refCount;
WeakPtrBase()
: _refCount(nullptr) { }
explicit WeakPtrBase(RefCount* refCount)
: _refCount(refCount) { }
void ResetIntern();
bool LockIntern() const;
};
template <class T>
class WeakPtr : public WeakPtrBase
{
template <class Y> friend class WeakPtr;
template <class Y> friend class EnableSharedFromThis;
public:
WeakPtr() { }
WeakPtr(std::nullptr_t) { }
WeakPtr(const WeakPtr& other)
: WeakPtrBase(other._refCount), _object(other._object)
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
}
WeakPtr(WeakPtr&& other)
: WeakPtrBase(other._refCount), _object(other._object)
{
other._refCount = nullptr;
other._object = nullptr;
}
template <class Y> requires std::assignable_from<T*&, Y*>
WeakPtr(const SharedPtr<Y>& sharedPtr)
: WeakPtrBase(sharedPtr._refCount), _object(static_cast<T*>(sharedPtr.GetPointer()))
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
}
template <class Y>
explicit WeakPtr(const SharedPtr<Y>& sharedPtr)
: WeakPtrBase(sharedPtr._refCount), _object(static_cast<T*>(sharedPtr.GetPointer()))
{
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
}
WeakPtr& operator=(const WeakPtr& other)
{
Reset();
_object = other._object;
_refCount = other._refCount;
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
return *this;
}
template <class Y> requires std::assignable_from<T*&, Y*>
WeakPtr<T>& operator=(const WeakPtr<Y>& other)
{
Reset();
_object = static_cast<T*>(static_cast<Y*>(other._object));
_refCount = other._refCount;
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
return *this;
}
template <class Y> requires std::assignable_from<T*&, Y*>
WeakPtr<T>& operator=(const SharedPtr<Y>& sharedPtr)
{
Reset();
_object = static_cast<T*>(sharedPtr.GetPointer());
_refCount = sharedPtr._refCount;
if (_refCount)
{
shared_ptr_increase_ref_count(_refCount->weakRefCount);
}
return *this;
}
WeakPtr& operator=(WeakPtr&& other)
{
Reset();
_object = other._object;
_refCount = other._refCount;
other._object = nullptr;
other._refCount = nullptr;
return *this;
}
template <class Y> requires std::assignable_from<T*&, Y*>
WeakPtr<T>& operator=(WeakPtr<Y>&& other)
{
Reset();
_object = static_cast<T*>(static_cast<Y*>(other._object));
_refCount = other._refCount;
other._object = nullptr;
other._refCount = nullptr;
return *this;
}
SharedPtr<T> Lock() const
{
if (_refCount && LockIntern())
{
return SharedPtr<T>(_object, _refCount);
}
else
{
return SharedPtr<T>();
}
}
private:
T* _object;
WeakPtr(T* object, RefCount* refCount)
: WeakPtrBase(refCount), _object(object) { }
};

View File

@@ -46,7 +46,7 @@ public:
constexpr fixed(long double value) constexpr fixed(long double value)
: _value(std::round(value * (1 << FractionBits))) { } : _value(std::round(value * (1 << FractionBits))) { }
constexpr T Int() const constexpr T Int() const
{ {
return _value >> FractionBits; return _value >> FractionBits;
@@ -161,11 +161,27 @@ public:
return FromRawValue(this->_value >> rhs); return FromRawValue(this->_value >> rhs);
} }
constexpr fix16 abs() const constexpr fix16 Abs() const
{ {
return FromRawValue(std::abs(this->_value)); return FromRawValue(std::abs(this->_value));
} }
constexpr fix16 Clamp(fix16 min, fix16 max) const
{
if (this->_value < min._value)
{
return min;
}
else if (this->_value > max._value)
{
return max;
}
else
{
return *this;
}
}
template <u32 OtherFractionBits> template <u32 OtherFractionBits>
constexpr fix32<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const constexpr fix32<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const
{ {
@@ -265,21 +281,45 @@ public:
return this->_value < other._value; return this->_value < other._value;
} }
template <typename TLhs>
constexpr friend bool operator<(TLhs lhs, const fix32& rhs)
{
return fix32(lhs)._value < rhs._value;
}
constexpr bool operator<=(const fix32& other) const constexpr bool operator<=(const fix32& other) const
{ {
return this->_value <= other._value; return this->_value <= other._value;
} }
template <typename TLhs>
constexpr friend bool operator<=(TLhs lhs, const fix32& rhs)
{
return fix32(lhs)._value <= rhs._value;
}
constexpr bool operator>(const fix32& other) const constexpr bool operator>(const fix32& other) const
{ {
return this->_value > other._value; return this->_value > other._value;
} }
template <typename TLhs>
constexpr friend bool operator>(TLhs lhs, const fix32& rhs)
{
return fix32(lhs)._value > rhs._value;
}
constexpr bool operator>=(const fix32& other) const constexpr bool operator>=(const fix32& other) const
{ {
return this->_value >= other._value; return this->_value >= other._value;
} }
template <typename TLhs>
constexpr friend bool operator>=(TLhs lhs, const fix32& rhs)
{
return fix32(lhs)._value >= rhs._value;
}
constexpr fix32 operator-() const constexpr fix32 operator-() const
{ {
return FromRawValue(-this->_value); return FromRawValue(-this->_value);
@@ -337,6 +377,22 @@ public:
return FromRawValue(std::abs(this->_value)); return FromRawValue(std::abs(this->_value));
} }
constexpr fix32 Clamp(fix32 min, fix32 max) const
{
if (this->_value < min._value)
{
return min;
}
else if (this->_value > max._value)
{
return max;
}
else
{
return *this;
}
}
template <u32 OtherFractionBits> template <u32 OtherFractionBits>
constexpr fix64<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const constexpr fix64<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const
{ {
@@ -354,6 +410,11 @@ public:
return fix64<FractionBits>::FromRawValue((s64)this->_value * other); return fix64<FractionBits>::FromRawValue((s64)this->_value * other);
} }
constexpr fix64<FractionBits> LongMul(double other) const
{
return LongMul(fix32(other));
}
template <u32 OtherFractionBits> template <u32 OtherFractionBits>
constexpr fix32 operator*(const fix16<OtherFractionBits>& other) const constexpr fix32 operator*(const fix16<OtherFractionBits>& other) const
{ {
@@ -371,6 +432,11 @@ public:
return FromRawValue(this->_value * other); return FromRawValue(this->_value * other);
} }
constexpr fix32 operator*(double other) const
{
return fix32(LongMul(fix32(other)));
}
constexpr friend fix32 operator*(int lhs, const fix32& rhs) constexpr friend fix32 operator*(int lhs, const fix32& rhs)
{ {
return FromRawValue(lhs * rhs.GetRawValue()); return FromRawValue(lhs * rhs.GetRawValue());

View File

@@ -1,9 +1,20 @@
#include "common.h" #include "common.h"
#include "Task.h" #include "Task.h"
void TaskBase::Execute() void TaskBase::RequestCancel()
{ {
u32 irqs = rtos_disableIrqs(); u32 irqs = rtos_disableIrqs();
_cancelRequested = true;
if (_state == TaskState::NotStarted)
{
_state = TaskState::Canceled;
rtos_wakeupQueue(&_threadQueue);
}
rtos_restoreIrqs(irqs);
}
void TaskBase::Execute(u32 irqs)
{
if (_state == TaskState::NotStarted) if (_state == TaskState::NotStarted)
{ {
_state = TaskState::Running; _state = TaskState::Running;
@@ -12,7 +23,9 @@ void TaskBase::Execute()
SetFinalState(finalState); SetFinalState(finalState);
} }
else else
{
rtos_restoreIrqs(irqs); rtos_restoreIrqs(irqs);
}
} }
void TaskBase::SetFinalState(TaskState finalState) void TaskBase::SetFinalState(TaskState finalState)

View File

@@ -3,14 +3,17 @@
#include <memory> #include <memory>
#include <libtwl/rtos/rtosIrq.h> #include <libtwl/rtos/rtosIrq.h>
#include <libtwl/rtos/rtosThread.h> #include <libtwl/rtos/rtosThread.h>
#include "core/LinkedListLink.h"
#include "TaskResult.h" #include "TaskResult.h"
class TaskBase class TaskBase
{ {
public: public:
LinkedListLink link;
virtual ~TaskBase() { } virtual ~TaskBase() { }
void Execute(); void Execute(u32 irqs);
TaskState GetState() const { return _state; } TaskState GetState() const { return _state; }
@@ -24,7 +27,7 @@ public:
bool GetDestroyWhenComplete() const { return _destroyWhenComplete; } bool GetDestroyWhenComplete() const { return _destroyWhenComplete; }
void SetDestroyWhenComplete() { _destroyWhenComplete = true; } void SetDestroyWhenComplete() { _destroyWhenComplete = true; }
void RequestCancel() { _cancelRequested = true; } void RequestCancel();
bool IsCancelRequested() const { return _cancelRequested; } bool IsCancelRequested() const { return _cancelRequested; }
protected: protected:

View File

@@ -1,23 +1,22 @@
#include "common.h" #include "common.h"
#include "TaskQueue.h" #include "TaskQueue.h"
void TaskQueueBase::ThreadMain(TaskBase** queue, u32 queueLength) void TaskQueueBase::ThreadMain()
{ {
while (true) while (true)
{ {
_idle = false; _idle = false;
u32 readPtr = _queueReadPtr; while (true)
while (readPtr != _queueWritePtr)
{ {
TaskBase* task = queue[readPtr]; u32 irqs = rtos_disableIrqs();
if (readPtr == queueLength - 1) auto task = _taskList.GetHead();
readPtr = 0;
else
readPtr++;
_queueReadPtr = readPtr;
if (!task) if (!task)
continue; {
task->Execute(); rtos_restoreIrqs(irqs);
break;
}
_taskList.Remove(task);
task->Execute(irqs);
if (task->GetDestroyWhenComplete()) if (task->GetDestroyWhenComplete())
{ {
// this will destroy the task // this will destroy the task

View File

@@ -4,6 +4,7 @@
#include <libtwl/rtos/rtosEvent.h> #include <libtwl/rtos/rtosEvent.h>
#include <libtwl/rtos/rtosThread.h> #include <libtwl/rtos/rtosThread.h>
#include "core/BitVector.h" #include "core/BitVector.h"
#include "core/LinkedList.h"
#include "Task.h" #include "Task.h"
class TaskQueueBase; class TaskQueueBase;
@@ -11,25 +12,13 @@ class TaskQueueBase;
class QueueTaskBase class QueueTaskBase
{ {
public: public:
// forbid copies
QueueTaskBase(const QueueTaskBase&) = delete;
QueueTaskBase& operator=(const QueueTaskBase&) = delete;
// move assignment
QueueTaskBase& operator=(QueueTaskBase&& other)
{
_taskQueue = other._taskQueue;
_task = other._task;
other._taskQueue = nullptr;
other._task = nullptr;
return *this;
}
~QueueTaskBase() ~QueueTaskBase()
{ {
// extra check here for optimizing out the dispose call after move assignment // extra check here for optimizing out the dispose call after move assignment
if (_task) if (_task)
{
Dispose(); Dispose();
}
} }
void Dispose(); void Dispose();
@@ -47,12 +36,10 @@ public:
protected: protected:
TaskBase* _task; TaskBase* _task;
TaskQueueBase* _taskQueue;
QueueTaskBase(TaskBase* task, TaskQueueBase* taskQueue) QueueTaskBase(TaskBase* task, TaskQueueBase* taskQueue)
: _task(task), _taskQueue(taskQueue) { } : _task(task), _taskQueue(taskQueue) { }
private:
TaskQueueBase* _taskQueue;
}; };
template <typename T> template <typename T>
@@ -62,6 +49,26 @@ public:
QueueTask() QueueTask()
: QueueTaskBase(nullptr, nullptr) { } : QueueTaskBase(nullptr, nullptr) { }
QueueTask(const QueueTask&) = delete;
QueueTask& operator=(const QueueTask&) = delete;
QueueTask(QueueTask&& other)
: QueueTaskBase(other._task, other._taskQueue)
{
other._task = nullptr;
other._taskQueue = nullptr;
}
QueueTask& operator=(QueueTask&& other)
{
Dispose();
_taskQueue = other._taskQueue;
_task = other._task;
other._taskQueue = nullptr;
other._task = nullptr;
return *this;
}
QueueTask(Task<T>* task, TaskQueueBase* taskQueue) QueueTask(Task<T>* task, TaskQueueBase* taskQueue)
: QueueTaskBase(task, taskQueue) { } : QueueTaskBase(task, taskQueue) { }
@@ -91,12 +98,11 @@ public:
protected: protected:
rtos_event_t _event; rtos_event_t _event;
vu32 _queueReadPtr = 0; LinkedList<TaskBase, &TaskBase::link> _taskList;
vu32 _queueWritePtr = 0;
volatile bool _endThreadWhenDone = false; volatile bool _endThreadWhenDone = false;
volatile bool _idle = true; volatile bool _idle = true;
void ThreadMain(TaskBase** queue, u32 queueLength); void ThreadMain();
TaskQueueBase() TaskQueueBase()
{ {
@@ -124,6 +130,10 @@ public:
u32 irqs = rtos_disableIrqs(); u32 irqs = rtos_disableIrqs();
if (task->IsCompleted()) if (task->IsCompleted())
{ {
if (task->link.prev != nullptr || task->link.next != nullptr)
{
_taskList.Remove(task);
}
task->~TaskBase(); task->~TaskBase();
u32 slot = ((u32)task - (u32)_taskPool) / ((MaxTaskSize + 3) & ~3); u32 slot = ((u32)task - (u32)_taskPool) / ((MaxTaskSize + 3) & ~3);
_poolOccupation.Set(slot, 0); _poolOccupation.Set(slot, 0);
@@ -159,13 +169,12 @@ public:
bool IsIdle() const bool IsIdle() const
{ {
return _queueReadPtr == _queueWritePtr && _idle; return _taskList.GetHead() == nullptr && _idle;
} }
private: private:
u32 _taskPool[QueueLength][(MaxTaskSize + 3) / 4]; u32 _taskPool[QueueLength][(MaxTaskSize + 3) / 4];
BitVector<QueueLength> _poolOccupation; BitVector<QueueLength> _poolOccupation;
TaskBase* _queue[QueueLength];
rtos_thread_t _thread; rtos_thread_t _thread;
bool _threadStarted = false; bool _threadStarted = false;
@@ -191,12 +200,11 @@ private:
[[gnu::noinline]] [[gnu::noinline]]
void Enqueue(TaskBase* task) override void Enqueue(TaskBase* task) override
{ {
u32 writePtr = _queueWritePtr; u32 irqs = rtos_disableIrqs();
_queue[writePtr] = task; {
if (writePtr == QueueLength - 1) _taskList.InsertTail(task);
_queueWritePtr = 0; }
else rtos_restoreIrqs(irqs);
_queueWritePtr = writePtr + 1;
rtos_signalEvent(&_event); rtos_signalEvent(&_event);
} }
@@ -207,6 +215,6 @@ private:
void ThreadMain() void ThreadMain()
{ {
TaskQueueBase::ThreadMain(&_queue[0], QueueLength); TaskQueueBase::ThreadMain();
} }
}; };

View File

@@ -3,7 +3,7 @@
#include "input/InputProvider.h" #include "input/InputProvider.h"
#include "FocusManager.h" #include "FocusManager.h"
void FocusManager::Focus(View* newFocus) void FocusManager::Focus(const SharedPtr<View>& newFocus)
{ {
if (!newFocus) if (!newFocus)
{ {
@@ -11,48 +11,71 @@ void FocusManager::Focus(View* newFocus)
return; return;
} }
if (_currentFocus) if (auto currentFocus = _currentFocus.Lock())
_currentFocus->SetFocused(false); {
currentFocus->SetFocused(false);
}
newFocus->SetFocused(true); newFocus->SetFocused(true);
_currentFocus = newFocus; _currentFocus = newFocus;
} }
void FocusManager::Unfocus() void FocusManager::Unfocus()
{ {
if (_currentFocus) if (auto currentFocus = _currentFocus.Lock())
_currentFocus->SetFocused(false); {
_currentFocus = nullptr; currentFocus->SetFocused(false);
}
_currentFocus.Reset();
} }
void FocusManager::Update(const InputProvider& inputProvider) void FocusManager::Update(const InputProvider& inputProvider)
{ {
if (!_currentFocus || !_currentFocus->GetParent()) auto currentFocus = _currentFocus.Lock();
if (!currentFocus || !currentFocus->GetParent())
return; // todo return; // todo
View* newFocus = nullptr; SharedPtr<View> newFocus;
if (inputProvider.Triggered(InputKey::DpadUp)) if (inputProvider.Triggered(InputKey::DpadUp))
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Up, _currentFocus); {
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Up, currentFocus.GetPointer());
}
else if (inputProvider.Triggered(InputKey::DpadDown)) else if (inputProvider.Triggered(InputKey::DpadDown))
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Down, _currentFocus); {
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Down, currentFocus.GetPointer());
}
else if (inputProvider.Triggered(InputKey::DpadLeft)) else if (inputProvider.Triggered(InputKey::DpadLeft))
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Left, _currentFocus); {
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Left, currentFocus.GetPointer());
}
else if (inputProvider.Triggered(InputKey::DpadRight)) else if (inputProvider.Triggered(InputKey::DpadRight))
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Right, _currentFocus); {
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Right, currentFocus.GetPointer());
}
else else
_currentFocus->HandleInput(inputProvider, *this); {
currentFocus->HandleInput(inputProvider, *this);
}
if (newFocus) if (newFocus)
{
Focus(newFocus); Focus(newFocus);
}
} }
bool FocusManager::IsFocusInside(const View* view) const bool FocusManager::IsFocusInside(const View* view) const
{ {
auto focusView = _currentFocus; if (auto currentFocus = _currentFocus.Lock())
while (focusView)
{ {
if (view == focusView) auto focusView = currentFocus.GetPointer();
return true; while (focusView)
focusView = focusView->GetParent(); {
if (view == focusView)
{
return true;
}
focusView = focusView->GetParent();
}
} }
return false; return false;
} }

View File

@@ -1,4 +1,6 @@
#pragma once #pragma once
#include <core/SharedPtr.h>
#include <core/WeakPtr.h>
class View; class View;
class InputProvider; class InputProvider;
@@ -9,7 +11,7 @@ class FocusManager
public: public:
/// @brief Focuses the given view. /// @brief Focuses the given view.
/// @param newFocus The view to focus. /// @param newFocus The view to focus.
void Focus(View* newFocus); void Focus(const SharedPtr<View>& newFocus);
/// @brief Clears the current focus. /// @brief Clears the current focus.
void Unfocus(); void Unfocus();
@@ -20,7 +22,7 @@ public:
/// @brief Gets the currently focused view. /// @brief Gets the currently focused view.
/// @return A pointer to the view that is currently focused, or null if none. /// @return A pointer to the view that is currently focused, or null if none.
constexpr View* GetCurrentFocus() const { return _currentFocus; } constexpr SharedPtr<View> GetCurrentFocus() const { return _currentFocus.Lock(); }
/// @brief Checks whether the current focus lies inside the given view. /// @brief Checks whether the current focus lies inside the given view.
/// @param view The view to check for. /// @param view The view to check for.
@@ -28,5 +30,5 @@ public:
bool IsFocusInside(const View* view) const; bool IsFocusInside(const View* view) const;
private: private:
View* _currentFocus = nullptr; WeakPtr<View> _currentFocus;
}; };

View File

@@ -2,10 +2,10 @@
#include "InputKey.h" #include "InputKey.h"
/// @brief Interface for a source of key input. /// @brief Interface for a source of key input.
class IInputSource class IKeyInputSource
{ {
public: public:
virtual ~IInputSource() { } virtual ~IKeyInputSource() { }
virtual InputKey Sample() const = 0; virtual InputKey Sample() const = 0;
}; };

View File

@@ -0,0 +1,14 @@
#pragma once
#include "core/math/Point.h"
/// @brief Interface for a source of touch input.
class ITouchInputSource
{
public:
virtual ~ITouchInputSource() { }
/// @brief Samples the touch input.
/// @param touchPosition When the pen is down, the current touch position.
/// @return \c true when the pen is down, or \c false otherwise.
virtual bool Sample(Point& touchPosition) const = 0;
};

View File

@@ -15,7 +15,9 @@ enum class InputKey : u16
L = 1 << 9, L = 1 << 9,
X = 1 << 10, X = 1 << 10,
Y = 1 << 11, Y = 1 << 11,
Debug = 1 << 13 Debug = 1 << 13,
Touch = 1 << 14,
Lid = 1 << 15
}; };
inline InputKey operator&(InputKey lhs, InputKey rhs) inline InputKey operator&(InputKey lhs, InputKey rhs)

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "core/math/Point.h"
#include "InputKey.h" #include "InputKey.h"
class InputProvider class InputProvider
@@ -14,6 +14,23 @@ public:
/// @return \c true if any of the keys in the \p mask is being held, or \c false otherwise. /// @return \c true if any of the keys in the \p mask is being held, or \c false otherwise.
bool Current(InputKey mask) const { return static_cast<bool>(_currentKeys & mask); } bool Current(InputKey mask) const { return static_cast<bool>(_currentKeys & mask); }
/// @brief Returns the current touch point if the screen is being touched.
/// @param touchPoint The current touch point if the screen is being touched.
/// @return \c true if the screen is being touched, or \c false otherwise.
bool GetCurrentTouchPoint(Point& touchPoint)
{
if (Current(InputKey::Touch))
{
touchPoint = _currentTouchPoint;
return true;
}
else
{
touchPoint = Point(0, 0);
return false;
}
}
/// @brief Returns a bitmask of the keys that went from unpressed to pressed in the latest update. /// @brief Returns a bitmask of the keys that went from unpressed to pressed in the latest update.
/// @return A bitmask of the keys that went from unpressed to pressed in the latest update. /// @return A bitmask of the keys that went from unpressed to pressed in the latest update.
InputKey GetTriggeredKeys() const InputKey GetTriggeredKeys() const
@@ -46,13 +63,16 @@ public:
_currentKeys = InputKey::None; _currentKeys = InputKey::None;
_triggeredKeys = InputKey::None; _triggeredKeys = InputKey::None;
_releasedKeys = InputKey::None; _releasedKeys = InputKey::None;
_currentTouchPoint = Point(0, 0);
} }
protected: protected:
InputKey _currentKeys; InputKey _currentKeys;
InputKey _triggeredKeys; InputKey _triggeredKeys;
InputKey _releasedKeys; InputKey _releasedKeys;
Point _currentTouchPoint;
InputProvider() InputProvider()
: _currentKeys(InputKey::None), _triggeredKeys(InputKey::None), _releasedKeys(InputKey::None) { } : _currentKeys(InputKey::None), _triggeredKeys(InputKey::None), _releasedKeys(InputKey::None)
, _currentTouchPoint(0, 0) { }
}; };

View File

@@ -27,7 +27,9 @@ void InputRepeater::Update()
} }
} }
else else
{
_state = State::Idle; _state = State::Idle;
}
} }
else if (_state == State::NextRepeat) else if (_state == State::NextRepeat)
{ {
@@ -40,13 +42,24 @@ void InputRepeater::Update()
} }
} }
else else
{
_state = State::Idle; _state = State::Idle;
}
} }
InputKey lastRepKeys = _currentKeys & _repeatMask; InputKey lastRepKeys = _currentKeys & _repeatMask;
_currentKeys = curKeys | repKeys; _currentKeys = curKeys | repKeys;
_triggeredKeys = _inputProvider->GetTriggeredKeys() | repKeys; _triggeredKeys = _inputProvider->GetTriggeredKeys() | repKeys;
_releasedKeys = _inputProvider->GetReleasedKeys() | (lastRepKeys & (lastRepKeys ^ repKeys)); _releasedKeys = _inputProvider->GetReleasedKeys() | (lastRepKeys & (lastRepKeys ^ repKeys));
Point touchPoint;
if (_inputProvider->GetCurrentTouchPoint(touchPoint))
{
_currentTouchPoint = touchPoint;
}
else
{
_currentTouchPoint = Point(0, 0);
}
} }
void InputRepeater::Reset() void InputRepeater::Reset()

View File

@@ -7,7 +7,7 @@ class InputRepeater : public InputProvider
public: public:
InputRepeater(InputProvider* inputProvider, InputKey repeatMask, u16 firstRepeatDelay, u16 nextRepeatDelay) InputRepeater(InputProvider* inputProvider, InputKey repeatMask, u16 firstRepeatDelay, u16 nextRepeatDelay)
: _inputProvider(inputProvider), _state(State::Idle) : _inputProvider(inputProvider), _state(State::Idle)
, _frameCounter(0), _repeatMask(repeatMask) , _frameCounter(0), _repeatMask(repeatMask & ~InputKey::Touch)
, _firstRepeatDelayFrames(firstRepeatDelay) , _firstRepeatDelayFrames(firstRepeatDelay)
, _nextRepeatDelayFrames(nextRepeatDelay) { } , _nextRepeatDelayFrames(nextRepeatDelay) { }

View File

@@ -1,17 +1,18 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include <nds/input.h> #include <nds/input.h>
#include "IInputSource.h" #include "IKeyInputSource.h"
#include "sharedMemory.h" #include "sharedMemory.h"
/// @brief Input source from the physical DS buttons. /// @brief Input source from the physical DS buttons.
class PadInputSource : public IInputSource class PadInputSource : public IKeyInputSource
{ {
public: public:
InputKey Sample() const override InputKey Sample() const override
{ {
u16 arm9Mask = (~REG_KEYINPUT & 0x3FF); u16 arm9Mask = (~REG_KEYINPUT & 0x3FF);
u16 arm7Mask = (~SHARED_KEY_XY & 0xB); u16 arm7Mask = (~SHARED_KEY_XY & 0xCB);
arm7Mask = (arm7Mask & 0xB) | ((arm7Mask & 0xC0) >> 2);
return static_cast<InputKey>((arm9Mask | (arm7Mask << 10))); return static_cast<InputKey>((arm9Mask | (arm7Mask << 10)));
} }
}; };

View File

@@ -7,16 +7,44 @@ void SampledInputProvider::Update()
InputKey trig = InputKey::None; InputKey trig = InputKey::None;
InputKey rel = InputKey::None; InputKey rel = InputKey::None;
Point touchPoint(0, 0);
int touchPointCount = 0;
while (_inputBufferReadPtr != _inputBufferWritePtr) while (_inputBufferReadPtr != _inputBufferWritePtr)
{ {
InputKey nextKeys = _inputBuffer[_inputBufferReadPtr]; InputKey nextKeys = _keyInputBuffer[_inputBufferReadPtr];
trig |= (nextKeys ^ curKeys) & nextKeys; trig |= (nextKeys ^ curKeys) & nextKeys;
rel |= (nextKeys ^ curKeys) & curKeys; rel |= (nextKeys ^ curKeys) & curKeys;
curKeys = nextKeys; curKeys = nextKeys;
if ((nextKeys & InputKey::Touch) != InputKey::None)
{
touchPoint.x += _touchInputBuffer[_inputBufferReadPtr].x;
touchPoint.y += _touchInputBuffer[_inputBufferReadPtr].y;
touchPointCount++;
}
else
{
touchPoint = Point(0, 0);
touchPointCount = 0;
}
_inputBufferReadPtr = (_inputBufferReadPtr + 1) & 3; _inputBufferReadPtr = (_inputBufferReadPtr + 1) & 3;
} }
_triggeredKeys = trig; _triggeredKeys = trig;
_releasedKeys = rel; _releasedKeys = rel;
_currentKeys = curKeys; _currentKeys = curKeys;
if (touchPointCount == 0)
{
if ((_triggeredKeys & InputKey::Touch) != InputKey::None ||
(_currentKeys & InputKey::Touch) != InputKey::None)
{
_releasedKeys = _releasedKeys | InputKey::Touch;
}
_triggeredKeys = _triggeredKeys & ~InputKey::Touch;
_currentKeys = _currentKeys & ~InputKey::Touch;
}
else
{
_currentTouchPoint.x = touchPoint.x / touchPointCount;
_currentTouchPoint.y = touchPoint.y / touchPointCount;
}
} }

View File

@@ -1,20 +1,23 @@
#pragma once #pragma once
#include "InputProvider.h" #include "InputProvider.h"
#include "IInputSource.h" #include "IKeyInputSource.h"
#include "ITouchInputSource.h"
/// @brief Input provider providing input from an \see IInputSource. /// @brief Input provider providing input from an \see IKeyInputSource.
class SampledInputProvider : public InputProvider class SampledInputProvider : public InputProvider
{ {
public: public:
explicit SampledInputProvider(const IInputSource* inputSource) explicit SampledInputProvider(const IKeyInputSource* keyInputSource, const ITouchInputSource* touchInputSource)
: _inputSource(inputSource), _inputBufferReadPtr(0), _inputBufferWritePtr(0) { } : _keyInputSource(keyInputSource), _touchInputSource(touchInputSource)
, _inputBufferReadPtr(0), _inputBufferWritePtr(0) { }
void Update() override; void Update() override;
/// @brief Samples the input source. /// @brief Samples the input source.
void Sample() void Sample()
{ {
_inputBuffer[_inputBufferWritePtr] = _inputSource->Sample(); _keyInputBuffer[_inputBufferWritePtr] = _keyInputSource->Sample();
_touchInputSource->Sample(_touchInputBuffer[_inputBufferWritePtr]);
_inputBufferWritePtr = (_inputBufferWritePtr + 1) & 3; _inputBufferWritePtr = (_inputBufferWritePtr + 1) & 3;
} }
@@ -26,9 +29,11 @@ public:
} }
private: private:
const IInputSource* _inputSource; const IKeyInputSource* _keyInputSource;
const ITouchInputSource* _touchInputSource;
InputKey _inputBuffer[4]; InputKey _keyInputBuffer[4];
Point _touchInputBuffer[4];
u8 _inputBufferReadPtr; u8 _inputBufferReadPtr;
u8 _inputBufferWritePtr; u8 _inputBufferWritePtr;
}; };

View File

@@ -0,0 +1,24 @@
#pragma once
#include "common.h"
#include <nds/input.h>
#include "ITouchInputSource.h"
#include "sharedMemory.h"
/// @brief Input source from the physical DS touch screen.
class TouchInputSource : public ITouchInputSource
{
public:
bool Sample(Point& touchPosition) const override
{
if (SHARED_KEY_XY & (1 << 6))
{
touchPosition = Point(0, 0);
return false;
}
else
{
touchPosition = Point(SHARED_TOUCH_X, SHARED_TOUCH_Y);
return true;
}
}
};

View File

@@ -3,15 +3,17 @@
class Label2DView : public LabelView class Label2DView : public LabelView
{ {
public: SHARED_ONLY(Label2DView)
Label2DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font)
: LabelView(width, height, maxStringLength, font, false) { }
public:
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
void VBlank() override; void VBlank() override;
private: private:
Label2DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font)
: LabelView(width, height, maxStringLength, font, false) { }
void UpdateTileBuffer() override; void UpdateTileBuffer() override;
bool _tileBufferUpdated = false; bool _tileBufferUpdated = false;

View File

@@ -12,6 +12,11 @@ Label3DView::Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_
: LabelView(width, height, maxStringLength, font, true) : LabelView(width, height, maxStringLength, font, true)
, _vblankTextureLoader(vblankTextureLoader) { } , _vblankTextureLoader(vblankTextureLoader) { }
Label3DView::~Label3DView()
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
void Label3DView::InitVram(const VramContext& vramContext) void Label3DView::InitVram(const VramContext& vramContext)
{ {
const auto texVramManager = vramContext.GetTexVramManager(); const auto texVramManager = vramContext.GetTexVramManager();

View File

@@ -4,17 +4,21 @@
class alignas(32) Label3DView : public LabelView class alignas(32) Label3DView : public LabelView
{ {
SHARED_ONLY(Label3DView)
public: public:
Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font, ~Label3DView() override;
VBlankTextureLoader* vblankTextureLoader);
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
private: private:
Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font,
VBlankTextureLoader* vblankTextureLoader);
void UpdateTileBuffer() override; void UpdateTileBuffer() override;
u32 _texVramOffset = 0; u32 _texVramOffset = 0;
VBlankTextureLoader* _vblankTextureLoader; VBlankTextureLoader* _vblankTextureLoader;
VBlankTextureLoadRequest _textureLoadRequest; VBlankTextureLoadRequest _textureLoadRequest;
}; };

View File

@@ -20,19 +20,15 @@ public:
/// @brief Creates and returns a view for this adapter. /// @brief Creates and returns a view for this adapter.
/// @return The created view. /// @return The created view.
virtual View* CreateView() const = 0; virtual SharedPtr<View> CreateView() const = 0;
/// @brief Destroys a \p view for this adapter that was previously created with CreateView.
/// @param view The view to destroy.
virtual void DestroyView(View* view) const = 0;
/// @brief Binds the given \p view to the item at the given \p index. /// @brief Binds the given \p view to the item at the given \p index.
/// @param view The view to bind. /// @param view The view to bind.
/// @param index The item index to bind to. /// @param index The item index to bind to.
virtual void BindView(View* view, int index) const = 0; virtual void BindView(SharedPtr<View> view, int index) const = 0;
/// @brief Releases a \p view that was previously bound with BindView, such that it can be reused. /// @brief Releases a \p view that was previously bound with BindView, such that it can be reused.
/// @param view The view to release. /// @param view The view to release.
/// @param index The item index that was bound to the view. /// @param index The item index that was bound to the view.
virtual void ReleaseView(View* view, int index) const = 0; virtual void ReleaseView(SharedPtr<View> view, int index) const = 0;
}; };

View File

@@ -20,21 +20,21 @@ RecyclerView::~RecyclerView()
{ {
if (_adapter) if (_adapter)
{ {
for (u32 i = 0; i < _viewPoolTotalCount; i++) for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{ {
_adapter->DestroyView(_viewPool[i].view); _adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
} }
} }
} }
void RecyclerView::SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex) void RecyclerView::SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex)
{ {
if (_adapter) if (_adapter)
{ {
_selectedItem = nullptr; _selectedItem = nullptr;
for (u32 i = 0; i < _viewPoolTotalCount; i++) for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{ {
_adapter->DestroyView(_viewPool[i].view); _adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
} }
_viewPool.reset(); _viewPool.reset();
_viewPoolFreeCount = 0; _viewPoolFreeCount = 0;
@@ -44,7 +44,7 @@ void RecyclerView::SetAdapter(const RecyclerAdapter* adapter, int initialSelecte
_curRangeStart = 0; _curRangeStart = 0;
_curRangeLength = 0; _curRangeLength = 0;
} }
_adapter = adapter; _adapter = std::move(adapter);
_adapter->GetViewSize(_itemWidth, _itemHeight); _adapter->GetViewSize(_itemWidth, _itemHeight);
_itemCount = _adapter->GetItemCount(); _itemCount = _adapter->GetItemCount();
if (_mode == Mode::HorizontalList || _mode == Mode::HorizontalGrid) if (_mode == Mode::HorizontalList || _mode == Mode::HorizontalGrid)
@@ -178,7 +178,7 @@ void RecyclerView::VBlank()
} }
} }
View* RecyclerView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) SharedPtr<View> RecyclerView::MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
{ {
if (_itemCount == 0) if (_itemCount == 0)
{ {
@@ -195,9 +195,9 @@ View* RecyclerView::MoveFocus(View* currentFocus, FocusMoveDirection direction,
} }
} }
View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection direction, View* source) SharedPtr<View> RecyclerView::MoveFocusHorizontal(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
{ {
if (!_selectedItem || currentFocus != _selectedItem->view) if (!_selectedItem || currentFocus.GetPointer() != _selectedItem->view.GetPointer())
{ {
// incoming focus // incoming focus
if (direction != FocusMoveDirection::Down) if (direction != FocusMoveDirection::Down)
@@ -207,7 +207,7 @@ View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection d
int idx = (-_xOffset + currentFocus->GetPosition().x - _xPadding + ((_xSpacing + _itemWidth) >> 1)) / (_xSpacing + _itemWidth) * _rows; int idx = (-_xOffset + currentFocus->GetPosition().x - _xPadding + ((_xSpacing + _itemWidth) >> 1)) / (_xSpacing + _itemWidth) * _rows;
SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _rows * _rows)); SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _rows * _rows));
return _selectedItem != nullptr ? _selectedItem->view : this; return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
} }
int row = _selectedItem->itemIdx % _rows; int row = _selectedItem->itemIdx % _rows;
@@ -248,22 +248,28 @@ View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection d
SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1)); SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1));
} }
return _selectedItem != nullptr ? _selectedItem->view : this; return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
} }
View* RecyclerView::MoveFocusVertical(View* currentFocus, FocusMoveDirection direction, View* source) SharedPtr<View> RecyclerView::MoveFocusVertical(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
{ {
if (!_selectedItem || currentFocus != _selectedItem->view) if (!_selectedItem || currentFocus.GetPointer() != _selectedItem->view.GetPointer())
{ {
// incoming focus // incoming focus
if (direction != FocusMoveDirection::Right) if (direction == FocusMoveDirection::Right)
{ {
return nullptr; int idx = (-_yOffset + currentFocus->GetPosition().y - _yPadding + ((_ySpacing + _itemHeight) >> 1)) / (_ySpacing + _itemHeight) * _columns;
SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _columns * _columns));
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
}
else if (direction == FocusMoveDirection::Down)
{
int idx = (-_xOffset + currentFocus->GetPosition().x - _xPadding + ((_xSpacing + _itemWidth) >> 1)) / (_xSpacing + _itemWidth);
SetSelectedItem(std::clamp(idx, 0, _columns - 1));
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
} }
int idx = (-_yOffset + currentFocus->GetPosition().y - _yPadding + ((_ySpacing + _itemHeight) >> 1)) / (_ySpacing + _itemHeight) * _columns; return nullptr;
SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _columns * _columns));
return _selectedItem != nullptr ? _selectedItem->view : this;
} }
int column = _selectedItem->itemIdx % _columns; int column = _selectedItem->itemIdx % _columns;
@@ -304,7 +310,7 @@ View* RecyclerView::MoveFocusVertical(View* currentFocus, FocusMoveDirection dir
SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1)); SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1));
} }
return _selectedItem != nullptr ? _selectedItem->view : this; return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
} }
bool RecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) bool RecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
@@ -341,6 +347,117 @@ bool RecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager&
return View::HandleInput(inputProvider, focusManager); return View::HandleInput(inputProvider, focusManager);
} }
void RecyclerView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
if (GetBounds().Contains(touchPoint))
{
_penDown = true;
_penDownPosition = touchPoint;
_hasScrollStarted = false;
_penDownScrollOffset = _scrollOffsetAnimator.GetValue();
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{
_viewPool[i].view->HandlePenDown(touchPoint, focusManager);
}
}
}
void RecyclerView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
if (!_penDown)
{
return;
}
if (!_hasScrollStarted)
{
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{
_viewPool[i].view->HandlePenMove(touchPoint, focusManager);
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
{
SetSelectedItem(_viewPool[i].itemIdx);
}
}
int dx = touchPoint.x - _penDownPosition.x;
int dy = touchPoint.y - _penDownPosition.y;
if (dx * dx + dy * dy > 7 * 7)
{
bool shouldScrollStart = (_mode == Mode::HorizontalGrid || _mode == Mode::HorizontalList)
? (std::abs(touchPoint.x - _penDownPosition.x) > std::abs(touchPoint.y - _penDownPosition.y))
: (std::abs(touchPoint.x - _penDownPosition.x) < std::abs(touchPoint.y - _penDownPosition.y));
if (shouldScrollStart)
{
_hasScrollStarted = true;
}
else
{
_penDown = false; //wrong direction drag, so cancel it
}
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{
_viewPool[i].view->HandlePenUp(Point(-1, -1), focusManager);
}
}
}
else
{
int newScrollOffset;
if (_mode == Mode::HorizontalGrid || _mode == Mode::HorizontalList)
{
newScrollOffset = _penDownScrollOffset + touchPoint.x - _penDownPosition.x;
if (-newScrollOffset < 0)
{
newScrollOffset = 0;
_penDownScrollOffset = 0;
_penDownPosition.x = touchPoint.x;
}
else if (newScrollOffset < GetMaxScrollOffset())
{
newScrollOffset = GetMaxScrollOffset();
_penDownScrollOffset = newScrollOffset;
_penDownPosition.x = touchPoint.x;
}
}
else
{
newScrollOffset = _penDownScrollOffset + touchPoint.y - _penDownPosition.y;
if (-newScrollOffset < 0)
{
newScrollOffset = 0;
_penDownScrollOffset = 0;
_penDownPosition.y = touchPoint.y;
}
else if (newScrollOffset < GetMaxScrollOffset())
{
newScrollOffset = GetMaxScrollOffset();
_penDownScrollOffset = newScrollOffset;
_penDownPosition.y = touchPoint.y;
}
}
SetScrollOffset(newScrollOffset, false);
}
}
void RecyclerView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
{
_viewPool[i].view->HandlePenUp(lastTouchPoint, focusManager);
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
{
SetSelectedItem(_viewPool[i].itemIdx);
}
}
_penDown = false;
}
Point RecyclerView::GetItemPosition(int itemIdx) Point RecyclerView::GetItemPosition(int itemIdx)
{ {
int x = 0; int x = 0;

View File

@@ -8,6 +8,8 @@
class RecyclerView : public RecyclerViewBase class RecyclerView : public RecyclerViewBase
{ {
SHARED_ONLY(RecyclerView)
public: public:
enum class Mode enum class Mode
{ {
@@ -21,10 +23,9 @@ public:
VerticalGrid VerticalGrid
}; };
RecyclerView(int x, int y, int width, int height, Mode mode);
~RecyclerView(); ~RecyclerView();
void SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex = 0) override; void SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex = 0) override;
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
void Update() override; void Update() override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
@@ -35,16 +36,23 @@ public:
return Rectangle(_position, _width, _height); return Rectangle(_position, _width, _height);
} }
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override; SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override; bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
void Focus(FocusManager& focusManager) override void Focus(FocusManager& focusManager) override
{ {
if (_selectedItem) if (_selectedItem)
{
focusManager.Focus(_selectedItem->view); focusManager.Focus(_selectedItem->view);
}
else else
focusManager.Focus(this); {
focusManager.Focus(SharedFromThis());
}
} }
int GetSelectedItem() const override int GetSelectedItem() const override
@@ -69,7 +77,7 @@ public:
private: private:
struct ViewPoolEntry struct ViewPoolEntry
{ {
View* view; SharedPtr<View> view;
int itemIdx; int itemIdx;
}; };
@@ -94,6 +102,12 @@ private:
int _curRangeStart; int _curRangeStart;
int _curRangeLength; int _curRangeLength;
Animator<int> _scrollOffsetAnimator; Animator<int> _scrollOffsetAnimator;
bool _penDown = false;
Point _penDownPosition = Point(0, 0);
bool _hasScrollStarted = false;
int _penDownScrollOffset = 0;
RecyclerView(int x, int y, int width, int height, Mode mode);
void UpdatePosition(ViewPoolEntry& viewPoolEntry); void UpdatePosition(ViewPoolEntry& viewPoolEntry);
ViewPoolEntry* GetViewPoolEntryByItemIndex(int itemIdx); ViewPoolEntry* GetViewPoolEntryByItemIndex(int itemIdx);
@@ -107,6 +121,6 @@ private:
void EnsureVisible(int itemIdx, bool animate); void EnsureVisible(int itemIdx, bool animate);
Point GetItemPosition(int itemIdx); Point GetItemPosition(int itemIdx);
View* MoveFocusHorizontal(View* currentFocus, FocusMoveDirection direction, View* source); SharedPtr<View> MoveFocusHorizontal(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source);
View* MoveFocusVertical(View* currentFocus, FocusMoveDirection direction, View* source); SharedPtr<View> MoveFocusVertical(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source);
}; };

View File

@@ -2,16 +2,17 @@
#include "View.h" #include "View.h"
#include "RecyclerAdapter.h" #include "RecyclerAdapter.h"
#include "gui/FocusManager.h" #include "gui/FocusManager.h"
#include "core/SharedPtr.h"
/// @brief Abstract base class for a recycler view that displays a possibly large collection of items /// @brief Abstract base class for a recycler view that displays a possibly large collection of items
/// provided by an adapter in an efficient way. /// provided by an adapter in an efficient way.
class RecyclerViewBase : public View class RecyclerViewBase : public View
{ {
public: public:
virtual void SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex = 0) = 0; virtual void SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex = 0) = 0;
virtual void Focus(FocusManager& focusManager) = 0; virtual void Focus(FocusManager& focusManager) = 0;
virtual int GetSelectedItem() const = 0; virtual int GetSelectedItem() const = 0;
protected: protected:
const RecyclerAdapter* _adapter = nullptr; SharedPtr<const RecyclerAdapter> _adapter;
}; };

View File

@@ -2,6 +2,8 @@
#include "core/LinkedListLink.h" #include "core/LinkedListLink.h"
#include "core/math/Point.h" #include "core/math/Point.h"
#include "core/math/Rectangle.h" #include "core/math/Rectangle.h"
#include "core/SharedPtr.h"
#include "core/EnableSharedFromThis.h"
#include "../FocusManager.h" #include "../FocusManager.h"
#include "../FocusMoveDirection.h" #include "../FocusMoveDirection.h"
@@ -10,7 +12,7 @@ class VramContext;
class InputProvider; class InputProvider;
/// @brief Base class for views. /// @brief Base class for views.
class View class View : public EnableSharedFromThis<View>
{ {
public: public:
/// @brief Link used for views that contain other views. /// @brief Link used for views that contain other views.
@@ -37,7 +39,7 @@ public:
/// @param direction The direction to move the focus in. /// @param direction The direction to move the focus in.
/// @param source The view that requested this view to move focus. /// @param source The view that requested this view to move focus.
/// @return The newly focused view, or null if the focus didn't change. /// @return The newly focused view, or null if the focus didn't change.
virtual View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) virtual SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
{ {
if (_parent && _parent != source) if (_parent && _parent != source)
return _parent->MoveFocus(currentFocus, direction, this); return _parent->MoveFocus(currentFocus, direction, this);
@@ -57,6 +59,21 @@ public:
return false; return false;
} }
/// @brief Handles a pen down event.
/// @param touchPoint The touch point.
/// @param focusManager The focus manager.
virtual void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) { }
/// @brief Handles a pen move event.
/// @param touchPoint The touch point.
/// @param focusManager The focus manager.
virtual void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) { }
/// @brief Handles a pen up event.
/// @param lastTouchPoint The last touch point.
/// @param focusManager The focus manager.
virtual void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) { }
/// @brief Gets the bounds of the view. /// @brief Gets the bounds of the view.
/// @return The bounds of the view. /// @return The bounds of the view.
virtual Rectangle GetBounds() const = 0; virtual Rectangle GetBounds() const = 0;

View File

@@ -0,0 +1,58 @@
#include "common.h"
#include "ViewContainer.h"
void ViewContainer::InitVram(const VramContext& vramContext)
{
for (auto& view : _children)
{
view.InitVram(vramContext);
}
}
void ViewContainer::Update()
{
for (auto& view : _children)
{
view.Update();
}
}
void ViewContainer::Draw(GraphicsContext& graphicsContext)
{
for (auto& view : _children)
{
view.Draw(graphicsContext);
}
}
void ViewContainer::VBlank()
{
for (auto& view : _children)
{
view.VBlank();
}
}
void ViewContainer::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
for (auto& view : _children)
{
view.HandlePenDown(touchPoint, focusManager);
}
}
void ViewContainer::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
for (auto& view : _children)
{
view.HandlePenMove(touchPoint, focusManager);
}
}
void ViewContainer::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
for (auto& view : _children)
{
view.HandlePenUp(lastTouchPoint, focusManager);
}
}

View File

@@ -6,37 +6,13 @@
class ViewContainer : public View class ViewContainer : public View
{ {
public: public:
void InitVram(const VramContext& vramContext) override void InitVram(const VramContext& vramContext) override;
{ void Update() override;
for (auto& view : _children) void Draw(GraphicsContext& graphicsContext) override;
{ void VBlank() override;
view.InitVram(vramContext); void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
} void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
} void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
void Update() override
{
for (auto& view : _children)
{
view.Update();
}
}
void Draw(GraphicsContext& graphicsContext) override
{
for (auto& view : _children)
{
view.Draw(graphicsContext);
}
}
void VBlank() override
{
for (auto& view : _children)
{
view.VBlank();
}
}
protected: protected:
/// @brief Adds a child to the head of the list. /// @brief Adds a child to the head of the list.
@@ -55,6 +31,14 @@ protected:
view->SetParent(this); view->SetParent(this);
} }
/// @brief Removes a child from the list.
/// @param view The child to remove.
void RemoveChild(View* view)
{
_children.Remove(view);
view->SetParent(nullptr);
}
private: private:
LinkedList<View, &View::listLink> _children; LinkedList<View, &View::listLink> _children;
}; };

View File

@@ -3,6 +3,7 @@
#include "core/task/TaskQueue.h" #include "core/task/TaskQueue.h"
#include "../views/BannerListItemView.h" #include "../views/BannerListItemView.h"
#include "../Theme/IRomBrowserViewFactory.h" #include "../Theme/IRomBrowserViewFactory.h"
#include "romBrowser/viewModels/RomBrowserItemViewModel.h"
#include "BannerListFileRecyclerAdapter.h" #include "BannerListFileRecyclerAdapter.h"
void BannerListFileRecyclerAdapter::GetViewSize(int& width, int& height) const void BannerListFileRecyclerAdapter::GetViewSize(int& width, int& height) const
@@ -11,27 +12,24 @@ void BannerListFileRecyclerAdapter::GetViewSize(int& width, int& height) const
height = 44; height = 44;
} }
View* BannerListFileRecyclerAdapter::CreateView() const SharedPtr<View> BannerListFileRecyclerAdapter::CreateView() const
{ {
return _romBrowserViewFactory->CreateBannerListItemView(_vblankTextureLoader); return _romBrowserViewFactory->CreateBannerListItemView(
std::make_unique<RomBrowserItemViewModel>(_romBrowserController), _vblankTextureLoader);
} }
void BannerListFileRecyclerAdapter::DestroyView(View* view) const void BannerListFileRecyclerAdapter::BindView(SharedPtr<View> view, int index) const
{ {
delete static_cast<BannerListItemView*>(view); auto listItemView = static_cast<BannerListItemView*>(view.GetPointer());
}
void BannerListFileRecyclerAdapter::BindView(View* view, int index) const
{
auto listItemView = static_cast<BannerListItemView*>(view);
listItemView->SetGraphics(_bannerListItemViewGraphics); listItemView->SetGraphics(_bannerListItemViewGraphics);
FileRecyclerAdapter::BindView(view, index); FileRecyclerAdapter::BindView(view, index);
} }
TaskResult<void> BannerListFileRecyclerAdapter::BindView(View* view, int index, TaskResult<void> BannerListFileRecyclerAdapter::BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
{ {
auto listItemView = static_cast<BannerListItemView*>(view); auto listItemView = static_cast<BannerListItemView*>(view.GetPointer());
listItemView->GetViewModel().SetIndex(index);
const auto& fileInfo = _fileInfoManager->GetItem(index); const auto& fileInfo = _fileInfoManager->GetItem(index);
bool fileNameAsTitle = true; bool fileNameAsTitle = true;
if (internalFileInfo) if (internalFileInfo)
@@ -70,12 +68,20 @@ TaskResult<void> BannerListFileRecyclerAdapter::BindView(View* view, int index,
return TaskResult<void>::Completed(); return TaskResult<void>::Completed();
} }
void BannerListFileRecyclerAdapter::ReleaseView(View* view, int index) const void BannerListFileRecyclerAdapter::SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const
{
auto listItemView = static_cast<BannerListItemView*>(view.GetPointer());
listItemView->GetViewModel().SetQueueTask(std::move(queueTask));
}
void BannerListFileRecyclerAdapter::ReleaseView(SharedPtr<View> view, int index) const
{ {
LOG_DEBUG("Releasing %d\n", index); LOG_DEBUG("Releasing %d\n", index);
auto listItemView = static_cast<BannerListItemView*>(view); auto listItemView = static_cast<BannerListItemView*>(view.GetPointer());
listItemView->SetIcon(nullptr); listItemView->SetIcon(nullptr);
listItemView->SetGameTitle(u""); listItemView->SetGameTitle(u"");
listItemView->GetViewModel().SetIndex(-1);
listItemView->GetViewModel().CancelQueueTask();
_fileInfoManager->ReleaseFileInfo(index); _fileInfoManager->ReleaseFileInfo(index);
} }

View File

@@ -8,19 +8,18 @@ class IRomBrowserViewFactory;
class BannerListFileRecyclerAdapter : public FileRecyclerAdapter class BannerListFileRecyclerAdapter : public FileRecyclerAdapter
{ {
public: public:
BannerListFileRecyclerAdapter(FileInfoManager* fileInfoManager, BannerListFileRecyclerAdapter(IRomBrowserController* romBrowserController, FileInfoManager* fileInfoManager,
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory, TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader) VBlankTextureLoader* vblankTextureLoader)
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory) : FileRecyclerAdapter(romBrowserController, fileInfoManager, taskQueue, themeFileIconFactory)
, _romBrowserViewFactory(romBrowserViewFactory) , _romBrowserViewFactory(romBrowserViewFactory)
, _vblankTextureLoader(vblankTextureLoader) { } , _vblankTextureLoader(vblankTextureLoader) { }
void GetViewSize(int& width, int& height) const override; void GetViewSize(int& width, int& height) const override;
View* CreateView() const override; SharedPtr<View> CreateView() const override;
void DestroyView(View* view) const override; void BindView(SharedPtr<View> view, int index) const override;
void BindView(View* view, int index) const override; void ReleaseView(SharedPtr<View> view, int index) const override;
void ReleaseView(View* view, int index) const override;
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
@@ -29,6 +28,7 @@ private:
BannerListItemView::VramToken _bannerListItemViewGraphics; BannerListItemView::VramToken _bannerListItemViewGraphics;
VBlankTextureLoader* _vblankTextureLoader; VBlankTextureLoader* _vblankTextureLoader;
TaskResult<void> BindView(View* view, int index, TaskResult<void> BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override; const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
void SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const override;
}; };

View File

@@ -13,21 +13,17 @@ void CoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height) const
height = 44; height = 44;
} }
View* CoverFlowFileRecyclerAdapter::CreateView() const SharedPtr<View> CoverFlowFileRecyclerAdapter::CreateView() const
{ {
return new CoverView(_vblankTextureLoader); return CoverView::CreateShared(
std::make_unique<RomBrowserItemViewModel>(_romBrowserController), _vblankTextureLoader);
} }
void CoverFlowFileRecyclerAdapter::DestroyView(View* view) const TaskResult<void> CoverFlowFileRecyclerAdapter::BindView(SharedPtr<View> view, int index,
{
auto coverView = static_cast<CoverView*>(view);
delete coverView;
}
TaskResult<void> CoverFlowFileRecyclerAdapter::BindView(View* view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
{ {
auto coverView = static_cast<CoverView*>(view); auto coverView = static_cast<CoverView*>(view.GetPointer());
coverView->GetViewModel().SetIndex(index);
auto cover = _fileInfoManager->GetFileCover(index); auto cover = _fileInfoManager->GetFileCover(index);
if (cancelRequested) if (cancelRequested)
{ {
@@ -45,11 +41,19 @@ TaskResult<void> CoverFlowFileRecyclerAdapter::BindView(View* view, int index,
return TaskResult<void>::Completed(); return TaskResult<void>::Completed();
} }
void CoverFlowFileRecyclerAdapter::ReleaseView(View* view, int index) const void CoverFlowFileRecyclerAdapter::SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const
{
auto coverView = static_cast<CoverView*>(view.GetPointer());
coverView->GetViewModel().SetQueueTask(std::move(queueTask));
}
void CoverFlowFileRecyclerAdapter::ReleaseView(SharedPtr<View> view, int index) const
{ {
LOG_DEBUG("Releasing %d\n", index); LOG_DEBUG("Releasing %d\n", index);
auto coverView = static_cast<CoverView*>(view); auto coverView = static_cast<CoverView*>(view.GetPointer());
coverView->ClearCover(); coverView->ClearCover();
coverView->GetViewModel().SetIndex(-1);
coverView->GetViewModel().CancelQueueTask();
_fileInfoManager->ReleaseFileInfo(index); _fileInfoManager->ReleaseFileInfo(index);
} }

View File

@@ -8,20 +8,19 @@ class ICoverRepository;
class CoverFlowFileRecyclerAdapter : public FileRecyclerAdapter class CoverFlowFileRecyclerAdapter : public FileRecyclerAdapter
{ {
public: public:
CoverFlowFileRecyclerAdapter(FileInfoManager* fileInfoManager, CoverFlowFileRecyclerAdapter(IRomBrowserController* romBrowserController, FileInfoManager* fileInfoManager,
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory, TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader, VBlankTextureLoader* vblankTextureLoader,
const ICoverRepository* coverRepository) const ICoverRepository* coverRepository)
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory) : FileRecyclerAdapter(romBrowserController, fileInfoManager, taskQueue, themeFileIconFactory)
, _romBrowserViewFactory(romBrowserViewFactory) , _romBrowserViewFactory(romBrowserViewFactory)
, _vblankTextureLoader(vblankTextureLoader) , _vblankTextureLoader(vblankTextureLoader)
, _coverRepository(coverRepository) { } , _coverRepository(coverRepository) { }
void GetViewSize(int& width, int& height) const override; void GetViewSize(int& width, int& height) const override;
View* CreateView() const override; SharedPtr<View> CreateView() const override;
void DestroyView(View* view) const override; void ReleaseView(SharedPtr<View> view, int index) const override;
void ReleaseView(View* view, int index) const override;
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
@@ -30,6 +29,7 @@ private:
VBlankTextureLoader* _vblankTextureLoader; VBlankTextureLoader* _vblankTextureLoader;
const ICoverRepository* _coverRepository; const ICoverRepository* _coverRepository;
TaskResult<void> BindView(View* view, int index, TaskResult<void> BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override; const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
void SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const override;
}; };

View File

@@ -3,6 +3,7 @@
#include "core/task/TaskQueue.h" #include "core/task/TaskQueue.h"
#include "../views/IconGridItemView.h" #include "../views/IconGridItemView.h"
#include "../Theme/IRomBrowserViewFactory.h" #include "../Theme/IRomBrowserViewFactory.h"
#include "romBrowser/viewModels/RomBrowserItemViewModel.h"
#include "IconGridFileRecyclerAdapter.h" #include "IconGridFileRecyclerAdapter.h"
void IconGridFileRecyclerAdapter::GetViewSize(int& width, int& height) const void IconGridFileRecyclerAdapter::GetViewSize(int& width, int& height) const
@@ -11,27 +12,23 @@ void IconGridFileRecyclerAdapter::GetViewSize(int& width, int& height) const
height = 44; height = 44;
} }
View* IconGridFileRecyclerAdapter::CreateView() const SharedPtr<View> IconGridFileRecyclerAdapter::CreateView() const
{ {
return _romBrowserViewFactory->CreateIconGridItemView(); return _romBrowserViewFactory->CreateIconGridItemView(std::make_unique<RomBrowserItemViewModel>(_romBrowserController));
} }
void IconGridFileRecyclerAdapter::DestroyView(View* view) const void IconGridFileRecyclerAdapter::BindView(SharedPtr<View> view, int index) const
{ {
delete static_cast<IconGridItemView*>(view); auto iconGridItemView = static_cast<IconGridItemView*>(view.GetPointer());
}
void IconGridFileRecyclerAdapter::BindView(View* view, int index) const
{
auto iconGridItemView = static_cast<IconGridItemView*>(view);
iconGridItemView->SetGraphics(_iconGridItemViewGraphics); iconGridItemView->SetGraphics(_iconGridItemViewGraphics);
FileRecyclerAdapter::BindView(view, index); FileRecyclerAdapter::BindView(view, index);
} }
TaskResult<void> IconGridFileRecyclerAdapter::BindView(View* view, int index, TaskResult<void> IconGridFileRecyclerAdapter::BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
{ {
auto iconGridItemView = static_cast<IconGridItemView*>(view); auto iconGridItemView = static_cast<IconGridItemView*>(view.GetPointer());
iconGridItemView->GetViewModel().SetIndex(index);
auto icon = internalFileInfo ? internalFileInfo->CreateGameIcon() : nullptr; auto icon = internalFileInfo ? internalFileInfo->CreateGameIcon() : nullptr;
if (!icon) if (!icon)
{ {
@@ -59,11 +56,19 @@ TaskResult<void> IconGridFileRecyclerAdapter::BindView(View* view, int index,
return TaskResult<void>::Completed(); return TaskResult<void>::Completed();
} }
void IconGridFileRecyclerAdapter::ReleaseView(View* view, int index) const void IconGridFileRecyclerAdapter::SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const
{
auto iconGridItemView = static_cast<IconGridItemView*>(view.GetPointer());
iconGridItemView->GetViewModel().SetQueueTask(std::move(queueTask));
}
void IconGridFileRecyclerAdapter::ReleaseView(SharedPtr<View> view, int index) const
{ {
LOG_DEBUG("Releasing %d\n", index); LOG_DEBUG("Releasing %d\n", index);
auto iconGridItemView = static_cast<IconGridItemView*>(view); auto iconGridItemView = static_cast<IconGridItemView*>(view.GetPointer());
iconGridItemView->SetIcon(nullptr); iconGridItemView->SetIcon(nullptr);
iconGridItemView->GetViewModel().SetIndex(-1);
iconGridItemView->GetViewModel().CancelQueueTask();
_fileInfoManager->ReleaseFileInfo(index); _fileInfoManager->ReleaseFileInfo(index);
} }

View File

@@ -7,17 +7,16 @@ class IRomBrowserViewFactory;
class IconGridFileRecyclerAdapter : public FileRecyclerAdapter class IconGridFileRecyclerAdapter : public FileRecyclerAdapter
{ {
public: public:
IconGridFileRecyclerAdapter(FileInfoManager* fileInfoManager, IconGridFileRecyclerAdapter(IRomBrowserController* romBrowserController, FileInfoManager* fileInfoManager,
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory, TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory) const IRomBrowserViewFactory* romBrowserViewFactory)
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory) : FileRecyclerAdapter(romBrowserController, fileInfoManager, taskQueue, themeFileIconFactory)
, _romBrowserViewFactory(romBrowserViewFactory) { } , _romBrowserViewFactory(romBrowserViewFactory) { }
void GetViewSize(int& width, int& height) const override; void GetViewSize(int& width, int& height) const override;
View* CreateView() const override; SharedPtr<View> CreateView() const override;
void DestroyView(View* view) const override; void BindView(SharedPtr<View> view, int index) const override;
void BindView(View* view, int index) const override; void ReleaseView(SharedPtr<View> view, int index) const override;
void ReleaseView(View* view, int index) const override;
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
@@ -25,6 +24,7 @@ private:
const IRomBrowserViewFactory* _romBrowserViewFactory; const IRomBrowserViewFactory* _romBrowserViewFactory;
IconGridItemView::VramToken _iconGridItemViewGraphics; IconGridItemView::VramToken _iconGridItemViewGraphics;
TaskResult<void> BindView(View* view, int index, TaskResult<void> BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override; const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
void SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const override;
}; };

View File

@@ -10,26 +10,26 @@ public:
bool IsVertical() const override { return true; } bool IsVertical() const override { return true; }
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory, SharedPtr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return romBrowserViewFactory->CreateAppBarView(0, 0, return romBrowserViewFactory->CreateAppBarView(0, 0,
AppBarView::Orientation::Vertical, startButtonCount, endButtonCount); AppBarView::Orientation::Vertical, startButtonCount, endButtonCount);
} }
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override SharedPtr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
{ {
auto recyclerView = std::make_unique<RecyclerView>(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalList); auto recyclerView = RecyclerView::CreateShared(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalList);
recyclerView->SetPadding(0, 3); recyclerView->SetPadding(0, 3);
recyclerView->SetItemSpacing(0, 3); recyclerView->SetItemSpacing(0, 3);
return recyclerView; return recyclerView;
} }
FileRecyclerAdapter* CreateRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new BannerListFileRecyclerAdapter( return SharedPtr<BannerListFileRecyclerAdapter>::MakeShared(viewModel->GetRomBrowserController(),
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), themeFileIconFactory, &viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), themeFileIconFactory,
romBrowserViewFactory, vblankTextureLoader); romBrowserViewFactory, vblankTextureLoader);
} }

View File

@@ -14,10 +14,10 @@ class RomBrowserDisplayMode
public: public:
virtual bool IsVertical() const = 0; virtual bool IsVertical() const = 0;
virtual bool ShowCoverOnTopScreen() const { return true; } virtual bool ShowCoverOnTopScreen() const { return true; }
virtual std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory, virtual SharedPtr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
int startButtonCount, int endButtonCount) const = 0; int startButtonCount, int endButtonCount) const = 0;
virtual std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const = 0; virtual SharedPtr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const = 0;
virtual FileRecyclerAdapter* CreateRecyclerAdapter( virtual SharedPtr<FileRecyclerAdapter> CreateRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const = 0; const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const = 0;
}; };

View File

@@ -9,19 +9,19 @@ public:
bool IsVertical() const override { return false; } bool IsVertical() const override { return false; }
bool ShowCoverOnTopScreen() const override { return false; } bool ShowCoverOnTopScreen() const override { return false; }
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory, SharedPtr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return romBrowserViewFactory->CreateAppBarView(0, 0, return romBrowserViewFactory->CreateAppBarView(0, 0,
AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount); AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount);
} }
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override SharedPtr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
{ {
return romBrowserViewFactory->CreateCoverFlowRecyclerView(); return romBrowserViewFactory->CreateCoverFlowRecyclerView();
} }
FileRecyclerAdapter* CreateRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
{ {

View File

@@ -10,26 +10,26 @@ public:
bool IsVertical() const override { return false; } bool IsVertical() const override { return false; }
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory, SharedPtr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return romBrowserViewFactory->CreateAppBarView(0, 0, return romBrowserViewFactory->CreateAppBarView(0, 0,
AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount); AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount);
} }
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override SharedPtr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
{ {
auto recyclerView = std::make_unique<RecyclerView>(0, 42, 256, 192 - 42, RecyclerView::Mode::HorizontalGrid); auto recyclerView = RecyclerView::CreateShared(0, 42, 256, 192 - 42, RecyclerView::Mode::HorizontalGrid);
recyclerView->SetPadding(10, 0); recyclerView->SetPadding(10, 0);
recyclerView->SetItemSpacing(4, 4); recyclerView->SetItemSpacing(4, 4);
return recyclerView; return recyclerView;
} }
FileRecyclerAdapter* CreateRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new IconGridFileRecyclerAdapter( return SharedPtr<IconGridFileRecyclerAdapter>::MakeShared(viewModel->GetRomBrowserController(),
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), &viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
themeFileIconFactory, romBrowserViewFactory); themeFileIconFactory, romBrowserViewFactory);
} }

View File

@@ -10,26 +10,26 @@ public:
bool IsVertical() const override { return true; } bool IsVertical() const override { return true; }
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory, SharedPtr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return romBrowserViewFactory->CreateAppBarView(0, 0, return romBrowserViewFactory->CreateAppBarView(0, 0,
AppBarView::Orientation::Vertical, startButtonCount, endButtonCount); AppBarView::Orientation::Vertical, startButtonCount, endButtonCount);
} }
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override SharedPtr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
{ {
auto recyclerView = std::make_unique<RecyclerView>(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalGrid); auto recyclerView = RecyclerView::CreateShared(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalGrid);
recyclerView->SetPadding(0, 3); recyclerView->SetPadding(0, 3);
recyclerView->SetItemSpacing(9, 3); recyclerView->SetItemSpacing(9, 3);
return recyclerView; return recyclerView;
} }
FileRecyclerAdapter* CreateRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new IconGridFileRecyclerAdapter( return SharedPtr<IconGridFileRecyclerAdapter>::MakeShared(viewModel->GetRomBrowserController(),
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), &viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
themeFileIconFactory, romBrowserViewFactory); themeFileIconFactory, romBrowserViewFactory);
} }

View File

@@ -15,6 +15,34 @@ FileInfoManager::~FileInfoManager()
} }
} }
void FileInfoManager::LoadFileInfo(int index)
{
auto internalFileInfo = _extraFileInfo[index].internalFileInfo;
if (!internalFileInfo)
{
internalFileInfo = _items[index]->CreateInternalFileInfo();
}
if (!_extraFileInfo[index].fileCover.Lock())
{
_extraFileInfo[index].fileCover = SharedPtr(_coverRepository.GetCoverForFile(*_items[index], internalFileInfo));
}
_extraFileInfo[index].internalFileInfo = internalFileInfo;
}
void FileInfoManager::ReleaseFileInfo(int index)
{
auto internalFileInfo = _extraFileInfo[index].internalFileInfo;
if (internalFileInfo)
{
_extraFileInfo[index].internalFileInfo = nullptr;
delete internalFileInfo;
}
_extraFileInfo[index].fileCover.Reset();
}
int FileInfoManager::GetItemIndex(const char* fileName) int FileInfoManager::GetItemIndex(const char* fileName)
{ {
if (fileName == nullptr) if (fileName == nullptr)
@@ -23,10 +51,10 @@ int FileInfoManager::GetItemIndex(const char* fileName)
} }
for (u32 i = 0; i < _itemCount; i++) for (u32 i = 0; i < _itemCount; i++)
{ {
if (strcmp(fileName, _items[i]->GetFileName()) == 0) if (strcmp(fileName, _items[i]->GetFileName()) == 0)
{ {
return i; return i;
} }
} }
return -1; return -1;
} }

View File

@@ -4,7 +4,7 @@
#include "FileInfo.h" #include "FileInfo.h"
#include "FileType/FileCover.h" #include "FileType/FileCover.h"
#include "ICoverRepository.h" #include "ICoverRepository.h"
#include "core/SharedPtr.h" #include "core/AtomicSharedPtr.h"
#include "FileType/InternalFileInfo.h" #include "FileType/InternalFileInfo.h"
class FileInfoManager class FileInfoManager
@@ -20,36 +20,12 @@ public:
SharedPtr<FileCover> GetFileCover(int index) SharedPtr<FileCover> GetFileCover(int index)
{ {
return _extraFileInfo[index].fileCover; return _extraFileInfo[index].fileCover.Lock();
} }
void LoadFileInfo(int index) void LoadFileInfo(int index);
{
auto internalFileInfo = GetInternalFileInfo(index);
if (!internalFileInfo)
{
internalFileInfo = _items[index]->CreateInternalFileInfo();
}
if (!_extraFileInfo[index].fileCover.IsValid()) void ReleaseFileInfo(int index);
{
_extraFileInfo[index].fileCover = SharedPtr(_coverRepository.GetCoverForFile(*_items[index], internalFileInfo));
}
_extraFileInfo[index].internalFileInfo = internalFileInfo;
}
void ReleaseFileInfo(int index)
{
auto internalFileInfo = GetInternalFileInfo(index);
if (internalFileInfo)
{
delete internalFileInfo;
_extraFileInfo[index].internalFileInfo = nullptr;
}
_extraFileInfo[index].fileCover.Reset();
}
int GetItemIndex(const char* fileName); int GetItemIndex(const char* fileName);
@@ -60,7 +36,7 @@ private:
struct ExtraFileInfo struct ExtraFileInfo
{ {
const InternalFileInfo* internalFileInfo; const InternalFileInfo* internalFileInfo;
SharedPtr<FileCover> fileCover; AtomicSharedPtr<FileCover> fileCover;
}; };
std::unique_ptr<const FileInfo*[]> _items; std::unique_ptr<const FileInfo*[]> _items;

View File

@@ -8,11 +8,17 @@ u32 FileRecyclerAdapter::GetItemCount() const
return _fileInfoManager->GetItemCount(); return _fileInfoManager->GetItemCount();
} }
void FileRecyclerAdapter::BindView(View* view, int index) const void FileRecyclerAdapter::BindView(SharedPtr<View> view, int index) const
{ {
LOG_DEBUG("Binding %d\n", index); LOG_DEBUG("Binding %d\n", index);
_taskQueue->Enqueue([=, this] (const vu8& cancelRequested) auto queueTask = _taskQueue->Enqueue([=, this] (const vu8& cancelRequested)
{ {
if (cancelRequested)
{
LOG_DEBUG("Task to load %d was canceled\n", index);
return TaskResult<void>::Canceled();
}
LOG_DEBUG("Started task to load %d\n", index); LOG_DEBUG("Started task to load %d\n", index);
_fileInfoManager->LoadFileInfo(index); _fileInfoManager->LoadFileInfo(index);
auto internalFileInfo = _fileInfoManager->GetInternalFileInfo(index); auto internalFileInfo = _fileInfoManager->GetInternalFileInfo(index);
@@ -23,4 +29,5 @@ void FileRecyclerAdapter::BindView(View* view, int index) const
} }
return BindView(view, index, internalFileInfo, cancelRequested); return BindView(view, index, internalFileInfo, cancelRequested);
}); });
SetQueueTask(view, std::move(queueTask));
} }

View File

@@ -7,12 +7,13 @@ class IVramManager;
class InternalFileInfo; class InternalFileInfo;
class IThemeFileIconFactory; class IThemeFileIconFactory;
class VramContext; class VramContext;
class IRomBrowserController;
class FileRecyclerAdapter : public RecyclerAdapter class FileRecyclerAdapter : public RecyclerAdapter
{ {
public: public:
u32 GetItemCount() const override; u32 GetItemCount() const override;
void BindView(View* view, int index) const override; void BindView(SharedPtr<View> view, int index) const override;
void SetIconFrameCounter(u32 iconFrameCounter) void SetIconFrameCounter(u32 iconFrameCounter)
{ {
@@ -22,16 +23,18 @@ public:
virtual void InitVram(const VramContext& vramContext) { } virtual void InitVram(const VramContext& vramContext) { }
protected: protected:
IRomBrowserController* _romBrowserController;
FileInfoManager* _fileInfoManager; FileInfoManager* _fileInfoManager;
TaskQueueBase* _taskQueue; TaskQueueBase* _taskQueue;
u32 _iconFrameCounter; u32 _iconFrameCounter;
const IThemeFileIconFactory* _themeFileIconFactory; const IThemeFileIconFactory* _themeFileIconFactory;
FileRecyclerAdapter(FileInfoManager* fileInfoManager, TaskQueueBase* taskQueue, FileRecyclerAdapter(IRomBrowserController* romBrowserController, FileInfoManager* fileInfoManager,
const IThemeFileIconFactory* themeFileIconFactory) TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory)
: _fileInfoManager(fileInfoManager), _taskQueue(taskQueue) : _romBrowserController(romBrowserController), _fileInfoManager(fileInfoManager), _taskQueue(taskQueue)
, _iconFrameCounter(0), _themeFileIconFactory(themeFileIconFactory) { } , _iconFrameCounter(0), _themeFileIconFactory(themeFileIconFactory) { }
virtual TaskResult<void> BindView(View* view, int index, virtual TaskResult<void> BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const = 0; const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const = 0;
virtual void SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const = 0;
}; };

View File

@@ -182,7 +182,7 @@ void RomBrowserController::HandleFolderLoadDoneTrigger()
LOG_DEBUG("RomBrowserStateTrigger::FolderLoadDone\n"); LOG_DEBUG("RomBrowserStateTrigger::FolderLoadDone\n");
_romBrowserViewModel.Reset(); _romBrowserViewModel.Reset();
_sdFolder = std::move(_newSdFolder); _sdFolder = std::move(_newSdFolder);
_romBrowserViewModel = SharedPtr(new RomBrowserViewModel(this, _navigateFileName)); _romBrowserViewModel = SharedPtr<RomBrowserViewModel>::MakeShared(this, _navigateFileName);
} }
void RomBrowserController::HandleLaunchTrigger() void RomBrowserController::HandleLaunchTrigger()
@@ -200,7 +200,7 @@ void RomBrowserController::HandleLaunchTrigger()
void RomBrowserController::HandleChangeDisplayModeTrigger() void RomBrowserController::HandleChangeDisplayModeTrigger()
{ {
LOG_DEBUG("RomBrowserStateTrigger::ChangeDisplayMode\n"); LOG_DEBUG("RomBrowserStateTrigger::ChangeDisplayMode\n");
_romBrowserViewModel = SharedPtr(new RomBrowserViewModel(this)); _romBrowserViewModel = SharedPtr<RomBrowserViewModel>::MakeShared(this);
} }
void RomBrowserController::UpdateLastUsedFilepath() void RomBrowserController::UpdateLastUsedFilepath()

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include "core/SharedPtr.h"
#include "../views/IconGridItemView.h" #include "../views/IconGridItemView.h"
#include "../views/BannerListItemView.h" #include "../views/BannerListItemView.h"
#include "../views/AppBarView.h" #include "../views/AppBarView.h"
@@ -11,30 +12,34 @@ class VBlankTextureLoader;
class RomBrowserViewModel; class RomBrowserViewModel;
class IThemeFileIconFactory; class IThemeFileIconFactory;
class FileRecyclerAdapter; class FileRecyclerAdapter;
class RomBrowserItemViewModel;
class IRomBrowserViewFactory class IRomBrowserViewFactory
{ {
public: public:
virtual ~IRomBrowserViewFactory() = 0; virtual ~IRomBrowserViewFactory() = 0;
virtual IconGridItemView* CreateIconGridItemView() const = 0; virtual SharedPtr<IconGridItemView> CreateIconGridItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel) const = 0;
virtual IconGridItemView::VramToken UploadIconGridItemViewGraphics( virtual IconGridItemView::VramToken UploadIconGridItemViewGraphics(
const VramContext& vramContext) const { return IconGridItemView::VramToken(0); } const VramContext& vramContext) const { return IconGridItemView::VramToken(0); }
virtual BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const = 0; virtual SharedPtr<BannerListItemView> CreateBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
VBlankTextureLoader* vblankTextureLoader) const = 0;
virtual BannerListItemView::VramToken UploadBannerListItemViewGraphics( virtual BannerListItemView::VramToken UploadBannerListItemViewGraphics(
const VramContext& vramContext) const { return BannerListItemView::VramToken(0); } const VramContext& vramContext) const { return BannerListItemView::VramToken(0); }
virtual std::unique_ptr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation, virtual SharedPtr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation,
int startButtonCount, int endButtonCount) const = 0; int startButtonCount, int endButtonCount) const = 0;
virtual std::unique_ptr<BannerView> CreateFileInfoView() const = 0; virtual SharedPtr<BannerView> CreateFileInfoView() const = 0;
virtual std::unique_ptr<RecyclerViewBase> CreateCoverFlowRecyclerView() const = 0; virtual SharedPtr<RecyclerViewBase> CreateCoverFlowRecyclerView() const = 0;
virtual FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter( virtual SharedPtr<FileRecyclerAdapter> CreateCoverFlowRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
VBlankTextureLoader* vblankTextureLoader) const = 0; VBlankTextureLoader* vblankTextureLoader) const = 0;
virtual Point GetTopCoverPosition() const = 0;
}; };
inline IRomBrowserViewFactory::~IRomBrowserViewFactory() { } inline IRomBrowserViewFactory::~IRomBrowserViewFactory() { }

View File

@@ -10,6 +10,8 @@
#include "romBrowser/FileType/FileCover.h" #include "romBrowser/FileType/FileCover.h"
#include "core/math/SinTable.h" #include "core/math/SinTable.h"
#include "carouselMask.h" #include "carouselMask.h"
#include "animation/Interpolator.h"
#include "gui/input/InputProvider.h"
#include "CarouselRecyclerView.h" #include "CarouselRecyclerView.h"
#define COVER_SPACING 4 #define COVER_SPACING 4
@@ -41,8 +43,10 @@ void CarouselRecyclerView::Update()
return; return;
} }
int rangeStartIndex = GetSelectedItem() - 4; _scrollAnimator.Update();
int rangeEndIndex = GetSelectedItem() + 1 + 4;
int rangeStartIndex = _scrollAnimator.GetValue().Int() - 4;
int rangeEndIndex = _scrollAnimator.GetValue().Int() + 1 + 4;
rangeStartIndex = std::clamp(rangeStartIndex, 0, (int)_itemCount - 1); rangeStartIndex = std::clamp(rangeStartIndex, 0, (int)_itemCount - 1);
rangeEndIndex = std::clamp(rangeEndIndex, 0, (int)_itemCount); rangeEndIndex = std::clamp(rangeEndIndex, 0, (int)_itemCount);
@@ -66,8 +70,7 @@ void CarouselRecyclerView::Update()
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++) for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{ {
_viewPoolEx[i].xPositionAnimator.Update(); UpdateItemPosition(i);
_viewPoolEx[i].widthAnimator.Update();
_viewPool[i].view->Update(); _viewPool[i].view->Update();
} }
} }
@@ -76,8 +79,8 @@ void CarouselRecyclerView::Draw(GraphicsContext& graphicsContext)
{ {
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++) for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{ {
fix32<12> x = (_viewPoolEx[i].xPositionAnimator.GetValue() + 0.5).Int(); fix32<12> x = (_viewPoolEx[i].xPosition + 0.5).Int();
fix32<12> width = (_viewPoolEx[i].widthAnimator.GetValue() + 0.5).Int(); fix32<12> width = (_viewPoolEx[i].width + 0.5).Int();
fix32<12> left = x; fix32<12> left = x;
if (left < HORIZONTAL_PADDING) if (left < HORIZONTAL_PADDING)
{ {
@@ -180,48 +183,179 @@ void CarouselRecyclerView::RenderRoundedCorners(GraphicsContext& graphicsContext
Gx::End(); Gx::End();
} }
void CarouselRecyclerView::UpdateItemPosition(int viewPoolIndex, bool initial) bool CarouselRecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{ {
ViewPoolEntry* item = &_viewPool[viewPoolIndex]; if (_itemCount != 0 && inputProvider.Triggered(InputKey::L | InputKey::R))
ViewPoolEntryEx* itemEx = &_viewPoolEx[viewPoolIndex];
int selectedIndex = GetSelectedItem();
if (selectedIndex == -1)
{ {
selectedIndex = 0; int direction = inputProvider.Triggered(InputKey::L) ? -1 : 1;
int selected = std::clamp(_selectedItem->itemIdx + 10 * direction, 0, (int)_itemCount - 1);
focusManager.Unfocus();
SetSelectedItem(selected, false);
focusManager.Focus(_selectedItem->view);
return true;
} }
int itemIndex = item->itemIdx;
fix32<12> x; return View::HandleInput(inputProvider, focusManager);
fix32<12> width; }
if (itemIndex < selectedIndex)
void CarouselRecyclerView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
if (GetBounds().Contains(touchPoint))
{ {
x = SELECTED_COVER_X + (SMALL_COVER_WIDTH + COVER_SPACING) * (itemIndex - selectedIndex); _penDown = true;
width = SMALL_COVER_WIDTH; _penDownPosition = touchPoint;
_hasScrollStarted = false;
_penDownScrollOffset = _scrollAnimator.GetValue();
if (_itemCount > 0)
{
_selectedItem->view->HandlePenDown(touchPoint, focusManager);
}
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
auto bounds = _viewPool[i].view->GetBounds();
bounds = Rectangle(_viewPoolEx[i].xPosition.Int(), bounds.GetTop(), _viewPoolEx[i].width.Int(), bounds.GetHeight());
if (bounds.Contains(touchPoint))
{
_viewPool[i].view->HandlePenDown(touchPoint, focusManager);
}
}
} }
else if (itemIndex == selectedIndex + 1) }
void CarouselRecyclerView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
if (!_penDown)
{ {
x = NEXT_COVER_X; return;
width = NEXT_COVER_WIDTH;
} }
else if (itemIndex > selectedIndex + 1)
if (!_hasScrollStarted)
{ {
x = NEXT_COVER_X + NEXT_COVER_WIDTH + COVER_SPACING for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
+ (SMALL_COVER_WIDTH + COVER_SPACING) * (itemIndex - selectedIndex - 2); {
width = SMALL_COVER_WIDTH; _viewPool[i].view->HandlePenMove(touchPoint, focusManager);
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
{
SetSelectedItem(_viewPool[i].itemIdx, false);
}
}
int dx = touchPoint.x - _penDownPosition.x;
int dy = touchPoint.y - _penDownPosition.y;
if (dx * dx + dy * dy > 7 * 7)
{
bool shouldScrollStart = std::abs(touchPoint.x - _penDownPosition.x) > std::abs(touchPoint.y - _penDownPosition.y);
if (shouldScrollStart)
{
_hasScrollStarted = true;
}
else
{
_penDown = false; //wrong direction drag, so cancel it
}
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
_viewPool[i].view->HandlePenUp(Point(-1, -1), focusManager);
}
}
} }
else else
{ {
x = SELECTED_COVER_X; fix32<12> newScrollOffset = _penDownScrollOffset + fix32<12>(_penDownPosition.x - touchPoint.x) * (2.5 / COVER_WIDTH);
width = SELECTED_COVER_WIDTH; if (newScrollOffset < 0)
{
newScrollOffset = 0;
_penDownScrollOffset = 0;
_penDownPosition.x = touchPoint.x;
}
else if (newScrollOffset > (int)_itemCount - 1)
{
newScrollOffset = (int)_itemCount - 1;
_penDownScrollOffset = newScrollOffset;
_penDownPosition.x = touchPoint.x;
}
_scrollAnimator = Animator<fix32<12>>(newScrollOffset);
}
}
void CarouselRecyclerView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
if (_hasScrollStarted)
{
SetSelectedItem((_scrollAnimator.GetValue() + 0.5).Int(), false);
focusManager.Focus(_selectedItem->view);
}
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
{
_viewPool[i].view->HandlePenUp(lastTouchPoint, focusManager);
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
{
SetSelectedItem(_viewPool[i].itemIdx, false);
}
}
_penDown = false;
}
void CarouselRecyclerView::SetSelectedItem(int itemIdx, bool initial)
{
CoverFlowRecyclerViewBase::SetSelectedItem(itemIdx, initial);
if (itemIdx < 0 || itemIdx >= (int)_itemCount)
{
return;
} }
if (initial) if (initial)
{ {
itemEx->xPositionAnimator = Animator(x); _scrollAnimator = Animator<fix32<12>>(itemIdx);
itemEx->widthAnimator = Animator(width);
} }
else else
{ {
itemEx->xPositionAnimator.Goto(x, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard); _scrollAnimator.Goto(itemIdx, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
itemEx->widthAnimator.Goto(width, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
} }
} }
void CarouselRecyclerView::UpdateItemPosition(int viewPoolIndex)
{
auto& item = _viewPool[viewPoolIndex];
auto& itemEx = _viewPoolEx[viewPoolIndex];
int itemIndex = item.itemIdx;
fix32<12> absOffsetFromCenter = (itemIndex - _scrollAnimator.GetValue()).Abs();
fix32<12> initialOffsetFromCenter = absOffsetFromCenter.Clamp(0, 1);
fix32<12> initialOffsetFromNext = (absOffsetFromCenter - 1).Clamp(0, 1);
fix32<12> x;
fix32<12> width;
if (itemIndex < _scrollAnimator.GetValue())
{
// everything before selected
x = SELECTED_COVER_X - (SMALL_COVER_WIDTH + COVER_SPACING) * absOffsetFromCenter;
width = Interpolator::InterpolateLinear<fix32<12>>(SELECTED_COVER_WIDTH, SMALL_COVER_WIDTH, initialOffsetFromCenter);
}
else if (initialOffsetFromCenter < 1)
{
// from selected to next
x = Interpolator::InterpolateLinear<fix32<12>>(SELECTED_COVER_X, NEXT_COVER_X, initialOffsetFromCenter);
width = Interpolator::InterpolateLinear<fix32<12>>(SELECTED_COVER_WIDTH, NEXT_COVER_WIDTH, initialOffsetFromCenter);
}
else
{
// everything after next
x = NEXT_COVER_X
+ Interpolator::InterpolateLinear<fix32<12>>(0, NEXT_COVER_WIDTH + COVER_SPACING, initialOffsetFromNext);
if (absOffsetFromCenter - 2 > 0)
{
x = x + (SMALL_COVER_WIDTH + COVER_SPACING) * (absOffsetFromCenter - 2);
}
width = Interpolator::InterpolateLinear<fix32<12>>(NEXT_COVER_WIDTH, SMALL_COVER_WIDTH, initialOffsetFromNext);
}
itemEx.xPosition = x;
itemEx.width = width;
}

View File

@@ -7,31 +7,44 @@ class MaterialColorScheme;
class CarouselRecyclerView : public CoverFlowRecyclerViewBase class CarouselRecyclerView : public CoverFlowRecyclerViewBase
{ {
public: SHARED_ONLY(CarouselRecyclerView)
explicit CarouselRecyclerView(const MaterialColorScheme* materialColorScheme)
: _materialColorScheme(materialColorScheme) { }
public:
static void UploadGraphics(const VramContext& vramContext); static void UploadGraphics(const VramContext& vramContext);
void Update() override; void Update() override;
void Draw(GraphicsContext &graphicsContext) override; void Draw(GraphicsContext &graphicsContext) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
private: private:
struct ViewPoolEntryEx struct ViewPoolEntryEx
{ {
Animator<fix32<12>> xPositionAnimator; fix32<12> xPosition;
Animator<fix32<12>> widthAnimator; fix32<12> width;
}; };
std::array<ViewPoolEntryEx, 10> _viewPoolEx; std::array<ViewPoolEntryEx, 10> _viewPoolEx;
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
Animator<fix32<12>> _scrollAnimator = Animator<fix32<12>>(0);
bool _penDown = false;
Point _penDownPosition = Point(0, 0);
bool _hasScrollStarted = false;
fix32<12> _penDownScrollOffset = 0;
static u32 sMaskTextureVramOffset; static u32 sMaskTextureVramOffset;
CarouselRecyclerView(const MaterialColorScheme* materialColorScheme)
: _materialColorScheme(materialColorScheme) { }
void RenderCoverMask(GraphicsContext& graphicsContext, fix32<12> left, fix32<12> right) const; void RenderCoverMask(GraphicsContext& graphicsContext, fix32<12> left, fix32<12> right) const;
void RenderRoundedCorners(GraphicsContext& graphicsContext, fix32<12> x, fix32<12> width) const; void RenderRoundedCorners(GraphicsContext& graphicsContext, fix32<12> x, fix32<12> width) const;
void UpdateItemPosition(int viewPoolIndex, bool initial) override; void SetSelectedItem(int itemIdx, bool initial) override;
void UpdateItemPosition(int viewPoolIndex);
void SwapViewPoolEntry(int indexA, int indexB) override void SwapViewPoolEntry(int indexA, int indexB) override
{ {

View File

@@ -9,12 +9,12 @@ MaterialAppBarView::MaterialAppBarView(int x, int y, Orientation orientation,
{ {
for (int i = 0; i < _startButtonCount + _endButtonCount; i++) for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{ {
_buttons[i] = new IconButton2DView( _buttons[i] = IconButton2DView::CreateShared(
IconButtonView::Type::Standard, IconButtonView::Type::Standard,
IconButtonView::State::NoToggle, IconButtonView::State::NoToggle,
md::sys::color::inverseOnSurface, md::sys::color::inverseOnSurface,
materialColorScheme); materialColorScheme);
AddChildTail(_buttons[i]); AddChildTail(_buttons[i].GetPointer());
} }
} }
@@ -26,7 +26,7 @@ void MaterialAppBarView::InitVram(const VramContext& vramContext)
auto iconButtonVramToken = IconButton2DView::UploadGraphics(*objVramManager); auto iconButtonVramToken = IconButton2DView::UploadGraphics(*objVramManager);
for (int i = 0; i < _startButtonCount + _endButtonCount; i++) for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{ {
static_cast<IconButton2DView*>(_buttons[i])->SetGraphics(iconButtonVramToken); static_cast<IconButton2DView*>(_buttons[i].GetPointer())->SetGraphics(iconButtonVramToken);
} }
} }
} }

View File

@@ -3,9 +3,12 @@
class MaterialAppBarView : public AppBarView class MaterialAppBarView : public AppBarView
{ {
SHARED_ONLY(MaterialAppBarView)
public: public:
void InitVram(const VramContext& vramContext) override;
private:
MaterialAppBarView(int x, int y, Orientation orientation, MaterialAppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme); int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme);
void InitVram(const VramContext& vramContext) override;
}; };

View File

@@ -18,12 +18,12 @@
#include "gui/views/Label2DView.h" #include "gui/views/Label2DView.h"
#include "MaterialBannerListItemView.h" #include "MaterialBannerListItemView.h"
MaterialBannerListItemView::MaterialBannerListItemView(const MaterialColorScheme* materialColorScheme, MaterialBannerListItemView::MaterialBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
const IFontRepository* fontRepository) const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository)
: BannerListItemView( : BannerListItemView(std::move(viewModel),
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Medium10)), Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Medium10)),
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Regular10)), Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Regular10)),
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Regular10))) Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Regular10)))
, _materialColorScheme(materialColorScheme) { } , _materialColorScheme(materialColorScheme) { }
void MaterialBannerListItemView::Draw(GraphicsContext& graphicsContext) void MaterialBannerListItemView::Draw(GraphicsContext& graphicsContext)

View File

@@ -7,10 +7,9 @@ class IFontRepository;
class MaterialBannerListItemView : public BannerListItemView class MaterialBannerListItemView : public BannerListItemView
{ {
public: SHARED_ONLY(MaterialBannerListItemView)
MaterialBannerListItemView(const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository);
public:
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -28,4 +27,7 @@ public:
private: private:
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
u32 _bgVramOffset; u32 _bgVramOffset;
MaterialBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository);
}; };

View File

@@ -13,21 +13,17 @@ void MaterialCoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height)
height = COVER_HEIGHT; height = COVER_HEIGHT;
} }
View* MaterialCoverFlowFileRecyclerAdapter::CreateView() const SharedPtr<View> MaterialCoverFlowFileRecyclerAdapter::CreateView() const
{ {
return new MaterialCoverView(_vblankTextureLoader); return MaterialCoverView::CreateShared(
std::make_unique<RomBrowserItemViewModel>(_romBrowserController), _vblankTextureLoader);
} }
void MaterialCoverFlowFileRecyclerAdapter::DestroyView(View* view) const TaskResult<void> MaterialCoverFlowFileRecyclerAdapter::BindView(SharedPtr<View> view, int index,
{
auto coverView = static_cast<MaterialCoverView*>(view);
delete coverView;
}
TaskResult<void> MaterialCoverFlowFileRecyclerAdapter::BindView(View* view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
{ {
auto coverView = static_cast<MaterialCoverView*>(view); auto coverView = static_cast<MaterialCoverView*>(view.GetPointer());
coverView->GetViewModel().SetIndex(index);
auto cover = _fileInfoManager->GetFileCover(index); auto cover = _fileInfoManager->GetFileCover(index);
if (cancelRequested) if (cancelRequested)
{ {
@@ -45,10 +41,18 @@ TaskResult<void> MaterialCoverFlowFileRecyclerAdapter::BindView(View* view, int
return TaskResult<void>::Completed(); return TaskResult<void>::Completed();
} }
void MaterialCoverFlowFileRecyclerAdapter::ReleaseView(View* view, int index) const void MaterialCoverFlowFileRecyclerAdapter::SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const
{
auto coverView = static_cast<MaterialCoverView*>(view.GetPointer());
coverView->GetViewModel().SetQueueTask(std::move(queueTask));
}
void MaterialCoverFlowFileRecyclerAdapter::ReleaseView(SharedPtr<View> view, int index) const
{ {
LOG_DEBUG("Releasing %d\n", index); LOG_DEBUG("Releasing %d\n", index);
auto coverView = static_cast<MaterialCoverView*>(view); auto coverView = static_cast<MaterialCoverView*>(view.GetPointer());
coverView->ClearCover(); coverView->ClearCover();
coverView->GetViewModel().SetIndex(-1);
coverView->GetViewModel().CancelQueueTask();
_fileInfoManager->ReleaseFileInfo(index); _fileInfoManager->ReleaseFileInfo(index);
} }

View File

@@ -8,26 +8,26 @@ class ICoverRepository;
class MaterialCoverFlowFileRecyclerAdapter : public FileRecyclerAdapter class MaterialCoverFlowFileRecyclerAdapter : public FileRecyclerAdapter
{ {
public: public:
MaterialCoverFlowFileRecyclerAdapter(FileInfoManager* fileInfoManager, MaterialCoverFlowFileRecyclerAdapter(IRomBrowserController* romBrowserController, FileInfoManager* fileInfoManager,
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory, TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
const IRomBrowserViewFactory* romBrowserViewFactory, const IRomBrowserViewFactory* romBrowserViewFactory,
VBlankTextureLoader* vblankTextureLoader, VBlankTextureLoader* vblankTextureLoader,
const ICoverRepository* coverRepository) const ICoverRepository* coverRepository)
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory) : FileRecyclerAdapter(romBrowserController, fileInfoManager, taskQueue, themeFileIconFactory)
, _romBrowserViewFactory(romBrowserViewFactory) , _romBrowserViewFactory(romBrowserViewFactory)
, _vblankTextureLoader(vblankTextureLoader) , _vblankTextureLoader(vblankTextureLoader)
, _coverRepository(coverRepository) { } , _coverRepository(coverRepository) { }
void GetViewSize(int& width, int& height) const override; void GetViewSize(int& width, int& height) const override;
View* CreateView() const override; SharedPtr<View> CreateView() const override;
void DestroyView(View* view) const override; void ReleaseView(SharedPtr<View> view, int index) const override;
void ReleaseView(View* view, int index) const override;
private: private:
const IRomBrowserViewFactory* _romBrowserViewFactory; const IRomBrowserViewFactory* _romBrowserViewFactory;
VBlankTextureLoader* _vblankTextureLoader; VBlankTextureLoader* _vblankTextureLoader;
const ICoverRepository* _coverRepository; const ICoverRepository* _coverRepository;
TaskResult<void> BindView(View* view, int index, TaskResult<void> BindView(SharedPtr<View> view, int index,
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override; const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
void SetQueueTask(const SharedPtr<View>& view, QueueTask<void> queueTask) const override;
}; };

View File

@@ -4,6 +4,7 @@
#include "gui/Gx.h" #include "gui/Gx.h"
#include "gui/materialDesign.h" #include "gui/materialDesign.h"
#include "gui/GraphicsContext.h" #include "gui/GraphicsContext.h"
#include "gui/input/InputProvider.h"
#include "MaterialCoverView.h" #include "MaterialCoverView.h"
void MaterialCoverView::InitVram(const VramContext& vramContext) void MaterialCoverView::InitVram(const VramContext& vramContext)
@@ -17,9 +18,14 @@ void MaterialCoverView::InitVram(const VramContext& vramContext)
} }
} }
void MaterialCoverView::Update()
{
_viewModel->DisposeQueueTaskWhenComplete();
}
void MaterialCoverView::Draw(GraphicsContext& graphicsContext) void MaterialCoverView::Draw(GraphicsContext& graphicsContext)
{ {
if (_cover.IsValid() && _textureLoadRequest.GetState() == VBlankTextureLoadRequestState::LoadComplete) if (_cover.Lock() && _textureLoadRequest.GetState() == VBlankTextureLoadRequestState::LoadComplete)
{ {
Gx::TexImageParam(_texVramOffset >> 3, false, true, false, true, GX_TEXSIZE_128, Gx::TexImageParam(_texVramOffset >> 3, false, true, false, true, GX_TEXSIZE_128,
GX_TEXSIZE_128, GX_TEXFMT_PLTT256, false, GX_TEXGEN_NONE); GX_TEXSIZE_128, GX_TEXFMT_PLTT256, false, GX_TEXGEN_NONE);
@@ -44,13 +50,34 @@ void MaterialCoverView::Draw(GraphicsContext& graphicsContext)
} }
} }
bool MaterialCoverView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
return _inputHandler.HandleInput(inputProvider, focusManager)
|| View::HandleInput(inputProvider, focusManager);
}
void MaterialCoverView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenDown(touchPoint, focusManager);
}
void MaterialCoverView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenMove(touchPoint, focusManager);
}
void MaterialCoverView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenUp(lastTouchPoint, focusManager);
}
void MaterialCoverView::UploadCoverGraphics() void MaterialCoverView::UploadCoverGraphics()
{ {
if (_cover.IsValid()) if (auto cover = _cover.Lock())
{ {
_cover->SetTexVramOffset(_texVramOffset, _plttVramOffset); cover->SetTexVramOffset(_texVramOffset, _plttVramOffset);
_vblankTextureLoader->CancelLoad(_textureLoadRequest); _vblankTextureLoader->CancelLoad(_textureLoadRequest);
_textureLoadRequest = _cover->CreateTextureLoadRequest(); _textureLoadRequest = cover->CreateTextureLoadRequest();
_vblankTextureLoader->RequestLoad(_textureLoadRequest); _vblankTextureLoader->RequestLoad(_textureLoadRequest);
} }
} }

View File

@@ -1,16 +1,16 @@
#pragma once #pragma once
#include <memory> #include "core/AtomicSharedPtr.h"
#include "core/SharedPtr.h"
#include "gui/views/View.h" #include "gui/views/View.h"
#include "romBrowser/FileType/FileCover.h" #include "romBrowser/FileType/FileCover.h"
#include "gui/VBlankTextureLoader.h" #include "gui/VBlankTextureLoader.h"
#include "romBrowser/viewModels/RomBrowserItemViewModel.h"
#include "romBrowser/views/RomBrowserItemInputHandler.h"
class MaterialCoverView : public View class MaterialCoverView : public View
{ {
public: SHARED_ONLY(MaterialCoverView)
explicit MaterialCoverView(VBlankTextureLoader* vblankTextureLoader)
: _vblankTextureLoader(vblankTextureLoader) { }
public:
~MaterialCoverView() override ~MaterialCoverView() override
{ {
_vblankTextureLoader->CancelLoad(_textureLoadRequest); _vblankTextureLoader->CancelLoad(_textureLoadRequest);
@@ -18,37 +18,48 @@ public:
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
Rectangle GetBounds() const override Rectangle GetBounds() const override
{ {
return Rectangle(_position.x - (COVER_WIDTH / 2), _position.y - (COVER_HEIGHT / 2), COVER_WIDTH, COVER_HEIGHT); return Rectangle(_position.x, _position.y, COVER_WIDTH, COVER_HEIGHT);
} }
void SetCover(SharedPtr<FileCover> cover) void SetCover(SharedPtr<FileCover> cover)
{ {
if (_cover.IsValid()) _vblankTextureLoader->CancelLoad(_textureLoadRequest);
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
_cover = std::move(cover); _cover = std::move(cover);
} }
void ClearCover() void ClearCover()
{ {
if (_cover.IsValid()) _vblankTextureLoader->CancelLoad(_textureLoadRequest);
{
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
}
_cover.Reset(); _cover.Reset();
} }
void UploadCoverGraphics(); void UploadCoverGraphics();
RomBrowserItemViewModel& GetViewModel() const
{
return *_viewModel;
}
private: private:
std::unique_ptr<RomBrowserItemViewModel> _viewModel;
VBlankTextureLoader* _vblankTextureLoader; VBlankTextureLoader* _vblankTextureLoader;
SharedPtr<FileCover> _cover; AtomicSharedPtr<FileCover> _cover;
VBlankTextureLoadRequest _textureLoadRequest; VBlankTextureLoadRequest _textureLoadRequest;
u32 _texVramOffset = 0; u32 _texVramOffset = 0;
u32 _plttVramOffset = 0; u32 _plttVramOffset = 0;
RomBrowserItemInputHandler _inputHandler;
MaterialCoverView(std::unique_ptr<RomBrowserItemViewModel> viewModel, VBlankTextureLoader* vblankTextureLoader)
: _viewModel(std::move(viewModel)), _vblankTextureLoader(vblankTextureLoader)
, _inputHandler(this, _viewModel.get()) { }
}; };

View File

@@ -13,17 +13,17 @@
MaterialFileInfoCardView::MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme, MaterialFileInfoCardView::MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository) const IFontRepository* fontRepository)
: _firstLine(176, 16, 50, fontRepository->GetFont(FontType::Medium11)) : _firstLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Medium11)))
, _secondLine(176, 16, 50, fontRepository->GetFont(FontType::Regular10)) , _secondLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Regular10)))
, _thirdLine(176, 16, 50, fontRepository->GetFont(FontType::Regular10)) , _thirdLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Regular10)))
, _filenameLabelView(220, 16, 200, fontRepository->GetFont(FontType::Medium7_5)) , _filenameLabelView(Label2DView::CreateShared(220, 16, 200, fontRepository->GetFont(FontType::Medium7_5)))
, _materialColorScheme(materialColorScheme) , _materialColorScheme(materialColorScheme)
{ {
AddChildTail(&_firstLine); AddChildTail(_firstLine.GetPointer());
AddChildTail(&_secondLine); AddChildTail(_secondLine.GetPointer());
AddChildTail(&_thirdLine); AddChildTail(_thirdLine.GetPointer());
_filenameLabelView.SetEllipsisStyle(LabelView::EllipsisStyle::Marquee); _filenameLabelView->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee);
AddChildTail(&_filenameLabelView); AddChildTail(_filenameLabelView.GetPointer());
} }
void MaterialFileInfoCardView::InitVram(const VramContext& vramContext) void MaterialFileInfoCardView::InitVram(const VramContext& vramContext)
@@ -41,10 +41,10 @@ void MaterialFileInfoCardView::InitVram(const VramContext& vramContext)
void MaterialFileInfoCardView::Update() void MaterialFileInfoCardView::Update()
{ {
BannerView::Update(); BannerView::Update();
_firstLine.SetPosition(_position.x + 70, _position.y + 130 - 8); _firstLine->SetPosition(_position.x + 70, _position.y + 130 - 8);
_secondLine.SetPosition(_position.x + 70, _position.y + 145 - 8); _secondLine->SetPosition(_position.x + 70, _position.y + 145 - 8);
_thirdLine.SetPosition(_position.x + 70, _position.y + 159 - 8); _thirdLine->SetPosition(_position.x + 70, _position.y + 159 - 8);
_filenameLabelView.SetPosition(_position.x + 18, _position.y + 168); _filenameLabelView->SetPosition(_position.x + 18, _position.y + 168);
if (_icon) if (_icon)
{ {
_icon->SetPosition(_position.x + 24, _position.y + 136 - 8); _icon->SetPosition(_position.x + 24, _position.y + 136 - 8);
@@ -54,14 +54,14 @@ void MaterialFileInfoCardView::Update()
void MaterialFileInfoCardView::Draw(GraphicsContext& graphicsContext) void MaterialFileInfoCardView::Draw(GraphicsContext& graphicsContext)
{ {
_firstLine.SetBackgroundColor(_materialColorScheme->secondaryContainer); _firstLine->SetBackgroundColor(_materialColorScheme->secondaryContainer);
_firstLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer); _firstLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
_secondLine.SetBackgroundColor(_materialColorScheme->secondaryContainer); _secondLine->SetBackgroundColor(_materialColorScheme->secondaryContainer);
_secondLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer); _secondLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
_thirdLine.SetBackgroundColor(_materialColorScheme->secondaryContainer); _thirdLine->SetBackgroundColor(_materialColorScheme->secondaryContainer);
_thirdLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer); _thirdLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
_filenameLabelView.SetBackgroundColor(_materialColorScheme->secondaryContainer); _filenameLabelView->SetBackgroundColor(_materialColorScheme->secondaryContainer);
_filenameLabelView.SetForegroundColor(_materialColorScheme->onSurfaceVariant); _filenameLabelView->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
BannerView::Draw(graphicsContext); BannerView::Draw(graphicsContext);

View File

@@ -9,55 +9,54 @@ class IFontRepository;
class MaterialFileInfoCardView : public BannerView class MaterialFileInfoCardView : public BannerView
{ {
public: SHARED_ONLY(MaterialFileInfoCardView)
MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository);
public:
void InitVram(const VramContext& vramContext) override; void InitVram(const VramContext& vramContext) override;
void Update() override; void Update() override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override
{ {
_firstLine.SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None);
if (taskQueue) if (taskQueue)
_firstLine.SetTextAsync(taskQueue, firstLine); _firstLine->SetTextAsync(taskQueue, firstLine);
else else
_firstLine.SetText(firstLine); _firstLine->SetText(firstLine);
} }
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override
{ {
_firstLine.SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None);
if (taskQueue) if (taskQueue)
_firstLine.SetTextAsync(taskQueue, firstLine, length); _firstLine->SetTextAsync(taskQueue, firstLine, length);
else else
_firstLine.SetText(firstLine, length); _firstLine->SetText(firstLine, length);
} }
void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override
{ {
if (taskQueue) if (taskQueue)
_secondLine.SetTextAsync(taskQueue, secondLine, length); _secondLine->SetTextAsync(taskQueue, secondLine, length);
else else
_secondLine.SetText(secondLine, length); _secondLine->SetText(secondLine, length);
} }
void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override
{ {
if (taskQueue) if (taskQueue)
_thirdLine.SetTextAsync(taskQueue, thirdLine, length); _thirdLine->SetTextAsync(taskQueue, thirdLine, length);
else else
_thirdLine.SetText(thirdLine, length); _thirdLine->SetText(thirdLine, length);
} }
void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle) override void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle) override
{ {
BannerView::SetFileNameAsync(taskQueue, fileName, useAsTitle); BannerView::SetFileNameAsync(taskQueue, fileName, useAsTitle);
if (taskQueue) if (taskQueue)
_filenameLabelView.SetTextAsync(taskQueue, fileName); _filenameLabelView->SetTextAsync(taskQueue, fileName);
else else
_filenameLabelView.SetText(fileName); _filenameLabelView->SetText(fileName);
} }
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -66,10 +65,13 @@ public:
} }
private: private:
Label2DView _firstLine; SharedPtr<Label2DView> _firstLine;
Label2DView _secondLine; SharedPtr<Label2DView> _secondLine;
Label2DView _thirdLine; SharedPtr<Label2DView> _thirdLine;
Label2DView _filenameLabelView; SharedPtr<Label2DView> _filenameLabelView;
u32 _iconCellVramOffset; u32 _iconCellVramOffset;
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository);
}; };

View File

@@ -20,7 +20,7 @@ void MaterialIconGridItemView::Draw(GraphicsContext& graphicsContext)
return; return;
auto backColor = _materialColorScheme->inverseOnSurface; auto backColor = _materialColorScheme->inverseOnSurface;
auto frontColor = _isFocused auto frontColor = (_isFocused || _inputHandler.IsPenDown())
? _materialColorScheme->mainIconBg ? _materialColorScheme->mainIconBg
: _materialColorScheme->surfaceBright; : _materialColorScheme->surfaceBright;
u16 selectedIconCellPltt[16]; u16 selectedIconCellPltt[16];

View File

@@ -5,10 +5,9 @@ class MaterialColorScheme;
class MaterialIconGridItemView : public IconGridItemView class MaterialIconGridItemView : public IconGridItemView
{ {
public: SHARED_ONLY(MaterialIconGridItemView)
explicit MaterialIconGridItemView(const MaterialColorScheme* materialColorScheme)
: _materialColorScheme(materialColorScheme) { }
public:
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -26,4 +25,7 @@ public:
private: private:
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
u32 _bgVramOffset; u32 _bgVramOffset;
};
MaterialIconGridItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel, const MaterialColorScheme* materialColorScheme)
: IconGridItemView(std::move(viewModel)), _materialColorScheme(materialColorScheme) { }
};

View File

@@ -18,9 +18,9 @@ public:
const IFontRepository* fontRepository) const IFontRepository* fontRepository)
: _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } : _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { }
IconGridItemView* CreateIconGridItemView() const override SharedPtr<IconGridItemView> CreateIconGridItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel) const override
{ {
return new MaterialIconGridItemView(_materialColorScheme); return MaterialIconGridItemView::CreateShared(std::move(viewModel), _materialColorScheme);
} }
IconGridItemView::VramToken UploadIconGridItemViewGraphics( IconGridItemView::VramToken UploadIconGridItemViewGraphics(
@@ -29,9 +29,10 @@ public:
return MaterialIconGridItemView::UploadGraphics(vramContext); return MaterialIconGridItemView::UploadGraphics(vramContext);
} }
BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const override SharedPtr<BannerListItemView> CreateBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new MaterialBannerListItemView(_materialColorScheme, _fontRepository); return MaterialBannerListItemView::CreateShared(std::move(viewModel), _materialColorScheme, _fontRepository);
} }
BannerListItemView::VramToken UploadBannerListItemViewGraphics( BannerListItemView::VramToken UploadBannerListItemViewGraphics(
@@ -40,31 +41,36 @@ public:
return MaterialBannerListItemView::UploadGraphics(vramContext); return MaterialBannerListItemView::UploadGraphics(vramContext);
} }
std::unique_ptr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation, SharedPtr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return std::make_unique<MaterialAppBarView>(x, y, orientation, startButtonCount, endButtonCount, _materialColorScheme); return MaterialAppBarView::CreateShared(x, y, orientation, startButtonCount, endButtonCount, _materialColorScheme);
} }
std::unique_ptr<BannerView> CreateFileInfoView() const override SharedPtr<BannerView> CreateFileInfoView() const override
{ {
return std::make_unique<MaterialFileInfoCardView>(_materialColorScheme, _fontRepository); return MaterialFileInfoCardView::CreateShared(_materialColorScheme, _fontRepository);
} }
std::unique_ptr<RecyclerViewBase> CreateCoverFlowRecyclerView() const override SharedPtr<RecyclerViewBase> CreateCoverFlowRecyclerView() const override
{ {
return std::make_unique<CarouselRecyclerView>(_materialColorScheme); return CarouselRecyclerView::CreateShared(_materialColorScheme);
} }
FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateCoverFlowRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
VBlankTextureLoader* vblankTextureLoader) const override VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new MaterialCoverFlowFileRecyclerAdapter( return SharedPtr<MaterialCoverFlowFileRecyclerAdapter>::MakeShared(viewModel->GetRomBrowserController(),
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), &viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository()); themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository());
} }
Point GetTopCoverPosition() const override
{
return Point(75, 18);
}
private: private:
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
const IFontRepository* _fontRepository; const IFontRepository* _fontRepository;

View File

@@ -4,8 +4,6 @@
#include "romBrowser/views/IconButton3DView.h" #include "romBrowser/views/IconButton3DView.h"
#include "CustomAppBarView.h" #include "CustomAppBarView.h"
#define BLOCK_VTX_PACK(x, y, z) (((x)&0x3FF) | ((((y) >> 3) & 0x3FF) << 10) | ((z) << 20))
CustomAppBarView::CustomAppBarView(int x, int y, Orientation orientation, CustomAppBarView::CustomAppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme, int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme,
u32 scrimTexVramOffset, u32 scrimPlttVramOffset) u32 scrimTexVramOffset, u32 scrimPlttVramOffset)
@@ -14,12 +12,12 @@ CustomAppBarView::CustomAppBarView(int x, int y, Orientation orientation,
{ {
for (int i = 0; i < _startButtonCount + _endButtonCount; i++) for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{ {
_buttons[i] = new IconButton3DView( _buttons[i] = IconButton3DView::CreateShared(
IconButtonView::Type::Tonal, IconButtonView::Type::Tonal,
IconButtonView::State::NoToggle, IconButtonView::State::NoToggle,
md::sys::color::inverseOnSurface, md::sys::color::inverseOnSurface,
materialColorScheme); materialColorScheme);
AddChildTail(_buttons[i]); AddChildTail(_buttons[i].GetPointer());
} }
} }

View File

@@ -3,14 +3,16 @@
class CustomAppBarView : public AppBarView class CustomAppBarView : public AppBarView
{ {
public: SHARED_ONLY(CustomAppBarView)
CustomAppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme,
u32 scrimTexVramOffset, u32 scrimPlttVramOffset);
public:
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
private: private:
u32 _scrimTexVramOffset = 0; u32 _scrimTexVramOffset = 0;
u32 _scrimPlttVramOffset = 0; u32 _scrimPlttVramOffset = 0;
CustomAppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme,
u32 scrimTexVramOffset, u32 scrimPlttVramOffset);
}; };

View File

@@ -31,16 +31,17 @@
#define LINE_HEIGHT 16 #define LINE_HEIGHT 16
#define MAX_LINE_STRING_LENGTH 50 #define MAX_LINE_STRING_LENGTH 50
CustomBannerListItemView::CustomBannerListItemView(const CustomThemeInfo* customThemeInfo, CustomBannerListItemView::CustomBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository, const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme,
u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset, const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset,
u32 selectedTexVramOffset, u32 selectedPlttVramOffset,
VBlankTextureLoader* vblankTextureLoader) VBlankTextureLoader* vblankTextureLoader)
: BannerListItemView( : BannerListItemView(std::move(viewModel),
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH, Label3DView::CreateShared(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
fontRepository->GetFont(FontType::Medium10), vblankTextureLoader), fontRepository->GetFont(FontType::Medium10), vblankTextureLoader),
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH, Label3DView::CreateShared(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
fontRepository->GetFont(FontType::Regular10), vblankTextureLoader), fontRepository->GetFont(FontType::Regular10), vblankTextureLoader),
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH, Label3DView::CreateShared(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
fontRepository->GetFont(FontType::Regular10), vblankTextureLoader)) fontRepository->GetFont(FontType::Regular10), vblankTextureLoader))
, _customThemeInfo(customThemeInfo) , _customThemeInfo(customThemeInfo)
, _materialColorScheme(materialColorScheme) , _materialColorScheme(materialColorScheme)

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "gui/views/LabelView.h" #include "gui/views/LabelView.h"
#include "../../views/BannerListItemView.h" #include "romBrowser/views/BannerListItemView.h"
class MaterialColorScheme; class MaterialColorScheme;
class IFontRepository; class IFontRepository;
@@ -8,11 +8,9 @@ class CustomThemeInfo;
class CustomBannerListItemView : public BannerListItemView class CustomBannerListItemView : public BannerListItemView
{ {
public: SHARED_ONLY(CustomBannerListItemView)
CustomBannerListItemView(const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset,
u32 selectedTexVramOffset, u32 selectedPlttVramOffset, VBlankTextureLoader* vblankTextureLoader);
public:
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -27,4 +25,9 @@ private:
u32 _plttVramOffset = 0; u32 _plttVramOffset = 0;
u32 _selectedTexVramOffset = 0; u32 _selectedTexVramOffset = 0;
u32 _selectedPlttVramOffset = 0; u32 _selectedPlttVramOffset = 0;
CustomBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel, const CustomThemeInfo* customThemeInfo,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset,
VBlankTextureLoader* vblankTextureLoader);
}; };

View File

@@ -6,26 +6,30 @@
#include "CustomFileInfoView.h" #include "CustomFileInfoView.h"
CustomFileInfoView::CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository) CustomFileInfoView::CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository)
: _firstLine(customThemeInfo->topBannerTextLine0Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Medium11)) : _firstLine(Label2DView::CreateShared(
, _secondLine(customThemeInfo->topBannerTextLine1Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)) customThemeInfo->topBannerTextLine0Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Medium11)))
, _thirdLine(customThemeInfo->topBannerTextLine2Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)) , _secondLine(Label2DView::CreateShared(
, _filenameLabelView(customThemeInfo->topFileNameTextInfo.GetWidth(), 16, 256, fontRepository->GetFont(FontType::Medium7_5)) customThemeInfo->topBannerTextLine1Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)))
, _thirdLine(Label2DView::CreateShared(
customThemeInfo->topBannerTextLine2Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)))
, _filenameLabelView(Label2DView::CreateShared(
customThemeInfo->topFileNameTextInfo.GetWidth(), 16, 256, fontRepository->GetFont(FontType::Medium7_5)))
, _customThemeInfo(customThemeInfo) , _customThemeInfo(customThemeInfo)
{ {
AddChildTail(&_firstLine); AddChildTail(_firstLine.GetPointer());
AddChildTail(&_secondLine); AddChildTail(_secondLine.GetPointer());
AddChildTail(&_thirdLine); AddChildTail(_thirdLine.GetPointer());
_filenameLabelView.SetEllipsisStyle(LabelView::EllipsisStyle::Marquee); _filenameLabelView->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee);
AddChildTail(&_filenameLabelView); AddChildTail(_filenameLabelView.GetPointer());
} }
void CustomFileInfoView::Update() void CustomFileInfoView::Update()
{ {
BannerView::Update(); BannerView::Update();
_firstLine.SetPosition(_customThemeInfo->topBannerTextLine0Info.GetPosition()); _firstLine->SetPosition(_customThemeInfo->topBannerTextLine0Info.GetPosition());
_secondLine.SetPosition(_customThemeInfo->topBannerTextLine1Info.GetPosition()); _secondLine->SetPosition(_customThemeInfo->topBannerTextLine1Info.GetPosition());
_thirdLine.SetPosition(_customThemeInfo->topBannerTextLine2Info.GetPosition()); _thirdLine->SetPosition(_customThemeInfo->topBannerTextLine2Info.GetPosition());
_filenameLabelView.SetPosition(_customThemeInfo->topFileNameTextInfo.GetPosition()); _filenameLabelView->SetPosition(_customThemeInfo->topFileNameTextInfo.GetPosition());
if (_icon) if (_icon)
{ {
_icon->SetPosition(_customThemeInfo->topIconInfo.GetPosition()); _icon->SetPosition(_customThemeInfo->topIconInfo.GetPosition());
@@ -35,14 +39,14 @@ void CustomFileInfoView::Update()
void CustomFileInfoView::Draw(GraphicsContext& graphicsContext) void CustomFileInfoView::Draw(GraphicsContext& graphicsContext)
{ {
_firstLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine0Info.GetBlendColor()); _firstLine->SetBackgroundColor(_customThemeInfo->topBannerTextLine0Info.GetBlendColor());
_firstLine.SetForegroundColor(_customThemeInfo->topBannerTextLine0Info.GetTextColor()); _firstLine->SetForegroundColor(_customThemeInfo->topBannerTextLine0Info.GetTextColor());
_secondLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine1Info.GetBlendColor()); _secondLine->SetBackgroundColor(_customThemeInfo->topBannerTextLine1Info.GetBlendColor());
_secondLine.SetForegroundColor(_customThemeInfo->topBannerTextLine1Info.GetTextColor()); _secondLine->SetForegroundColor(_customThemeInfo->topBannerTextLine1Info.GetTextColor());
_thirdLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine2Info.GetBlendColor()); _thirdLine->SetBackgroundColor(_customThemeInfo->topBannerTextLine2Info.GetBlendColor());
_thirdLine.SetForegroundColor(_customThemeInfo->topBannerTextLine2Info.GetTextColor()); _thirdLine->SetForegroundColor(_customThemeInfo->topBannerTextLine2Info.GetTextColor());
_filenameLabelView.SetBackgroundColor(_customThemeInfo->topFileNameTextInfo.GetBlendColor()); _filenameLabelView->SetBackgroundColor(_customThemeInfo->topFileNameTextInfo.GetBlendColor());
_filenameLabelView.SetForegroundColor(_customThemeInfo->topFileNameTextInfo.GetTextColor()); _filenameLabelView->SetForegroundColor(_customThemeInfo->topFileNameTextInfo.GetTextColor());
BannerView::Draw(graphicsContext); BannerView::Draw(graphicsContext);

View File

@@ -9,53 +9,53 @@ class CustomThemeInfo;
class CustomFileInfoView : public BannerView class CustomFileInfoView : public BannerView
{ {
public: SHARED_ONLY(CustomFileInfoView)
CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository);
public:
void Update() override; void Update() override;
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override
{ {
_firstLine.SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None);
if (taskQueue) if (taskQueue)
_firstLine.SetTextAsync(taskQueue, firstLine); _firstLine->SetTextAsync(taskQueue, firstLine);
else else
_firstLine.SetText(firstLine); _firstLine->SetText(firstLine);
} }
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override
{ {
_firstLine.SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None);
if (taskQueue) if (taskQueue)
_firstLine.SetTextAsync(taskQueue, firstLine, length); _firstLine->SetTextAsync(taskQueue, firstLine, length);
else else
_firstLine.SetText(firstLine, length); _firstLine->SetText(firstLine, length);
} }
void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override
{ {
if (taskQueue) if (taskQueue)
_secondLine.SetTextAsync(taskQueue, secondLine, length); _secondLine->SetTextAsync(taskQueue, secondLine, length);
else else
_secondLine.SetText(secondLine, length); _secondLine->SetText(secondLine, length);
} }
void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override
{ {
if (taskQueue) if (taskQueue)
_thirdLine.SetTextAsync(taskQueue, thirdLine, length); _thirdLine->SetTextAsync(taskQueue, thirdLine, length);
else else
_thirdLine.SetText(thirdLine, length); _thirdLine->SetText(thirdLine, length);
} }
void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle) override void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle) override
{ {
BannerView::SetFileNameAsync(taskQueue, fileName, useAsTitle); BannerView::SetFileNameAsync(taskQueue, fileName, useAsTitle);
if (taskQueue) if (taskQueue)
_filenameLabelView.SetTextAsync(taskQueue, fileName); _filenameLabelView->SetTextAsync(taskQueue, fileName);
else else
_filenameLabelView.SetText(fileName); _filenameLabelView->SetText(fileName);
} }
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -64,9 +64,11 @@ public:
} }
private: private:
Label2DView _firstLine; SharedPtr<Label2DView> _firstLine;
Label2DView _secondLine; SharedPtr<Label2DView> _secondLine;
Label2DView _thirdLine; SharedPtr<Label2DView> _thirdLine;
Label2DView _filenameLabelView; SharedPtr<Label2DView> _filenameLabelView;
const CustomThemeInfo* _customThemeInfo; const CustomThemeInfo* _customThemeInfo;
CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository);
}; };

View File

@@ -26,8 +26,8 @@ void CustomIconGridItemView::Draw(GraphicsContext& graphicsContext)
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 0); false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 0);
Gx::Color(0x7FFF); Gx::Color(0x7FFF);
u32 tex = _isFocused ? _selectedTexVramOffset : _texVramOffset; u32 tex = (_isFocused || _inputHandler.IsPenDown()) ? _selectedTexVramOffset : _texVramOffset;
u32 pltt = _isFocused ? _selectedPlttVramOffset : _plttVramOffset; u32 pltt = (_isFocused || _inputHandler.IsPenDown()) ? _selectedPlttVramOffset : _plttVramOffset;
Gx::TexImageParam(tex >> 3, false, false, false, false, GX_TEXSIZE_64, Gx::TexImageParam(tex >> 3, false, false, false, false, GX_TEXSIZE_64,
GX_TEXSIZE_64, GX_TEXFMT_A3I5, false, GX_TEXGEN_NONE); GX_TEXSIZE_64, GX_TEXFMT_A3I5, false, GX_TEXGEN_NONE);
Gx::TexPlttBase(pltt >> 4); Gx::TexPlttBase(pltt >> 4);

View File

@@ -5,12 +5,9 @@ class CustomThemeInfo;
class CustomIconGridItemView : public IconGridItemView class CustomIconGridItemView : public IconGridItemView
{ {
public: SHARED_ONLY(CustomIconGridItemView)
CustomIconGridItemView(const CustomThemeInfo* customThemeInfo, u32 texVramOffset, u32 plttVramOffset,
u32 selectedTexVramOffset, u32 selectedPlttVramOffset)
: _customThemeInfo(customThemeInfo), _texVramOffset(texVramOffset), _plttVramOffset(plttVramOffset)
, _selectedTexVramOffset(selectedTexVramOffset), _selectedPlttVramOffset(selectedPlttVramOffset) { }
public:
void Draw(GraphicsContext& graphicsContext) override; void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override Rectangle GetBounds() const override
@@ -24,4 +21,9 @@ private:
u32 _plttVramOffset; u32 _plttVramOffset;
u32 _selectedTexVramOffset; u32 _selectedTexVramOffset;
u32 _selectedPlttVramOffset; u32 _selectedPlttVramOffset;
CustomIconGridItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel, const CustomThemeInfo* customThemeInfo,
u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset)
: IconGridItemView(std::move(viewModel)), _customThemeInfo(customThemeInfo), _texVramOffset(texVramOffset), _plttVramOffset(plttVramOffset)
, _selectedTexVramOffset(selectedTexVramOffset), _selectedPlttVramOffset(selectedPlttVramOffset) { }
}; };

View File

@@ -7,12 +7,12 @@
#include "romBrowser/views/CoverFlowRecyclerView.h" #include "romBrowser/views/CoverFlowRecyclerView.h"
#include "romBrowser/viewModels/RomBrowserViewModel.h" #include "romBrowser/viewModels/RomBrowserViewModel.h"
#include "romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.h" #include "romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.h"
#include "themes/custom/CustomThemeInfo.h"
class MaterialColorScheme; class MaterialColorScheme;
class ITheme; class ITheme;
class VramContext; class VramContext;
class IFontRepository; class IFontRepository;
class CustomThemeInfo;
class CustomRomBrowserViewFactory : public IRomBrowserViewFactory class CustomRomBrowserViewFactory : public IRomBrowserViewFactory
{ {
@@ -21,15 +21,16 @@ public:
const IFontRepository* fontRepository) const IFontRepository* fontRepository)
: _customThemeInfo(customThemeInfo), _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } : _customThemeInfo(customThemeInfo), _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { }
IconGridItemView* CreateIconGridItemView() const override SharedPtr<IconGridItemView> CreateIconGridItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel) const override
{ {
return new CustomIconGridItemView(_customThemeInfo, _gridCellTexVramOffset, _gridCellPlttVramOffset, return CustomIconGridItemView::CreateShared(std::move(viewModel), _customThemeInfo, _gridCellTexVramOffset, _gridCellPlttVramOffset,
_gridCellSelectedTexVramOffset, _gridCellSelectedPlttVramOffset); _gridCellSelectedTexVramOffset, _gridCellSelectedPlttVramOffset);
} }
BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const override SharedPtr<BannerListItemView> CreateBannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new CustomBannerListItemView(_customThemeInfo, _materialColorScheme, _fontRepository, return CustomBannerListItemView::CreateShared(std::move(viewModel), _customThemeInfo, _materialColorScheme, _fontRepository,
_bannerListCellTexVramOffset, _bannerListCellPlttVramOffset, _bannerListCellTexVramOffset, _bannerListCellPlttVramOffset,
_bannerListCellSelectedTexVramOffset, _bannerListCellSelectedPlttVramOffset, vblankTextureLoader); _bannerListCellSelectedTexVramOffset, _bannerListCellSelectedPlttVramOffset, vblankTextureLoader);
} }
@@ -39,32 +40,37 @@ public:
return BannerListItemView::VramToken(0); return BannerListItemView::VramToken(0);
} }
std::unique_ptr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation, SharedPtr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation,
int startButtonCount, int endButtonCount) const override int startButtonCount, int endButtonCount) const override
{ {
return std::make_unique<CustomAppBarView>(x, y, orientation, startButtonCount, endButtonCount, _materialColorScheme, return CustomAppBarView::CreateShared(x, y, orientation, startButtonCount, endButtonCount, _materialColorScheme,
_scrimTexVramOffset, _scrimPlttVramOffset); _scrimTexVramOffset, _scrimPlttVramOffset);
} }
std::unique_ptr<BannerView> CreateFileInfoView() const override SharedPtr<BannerView> CreateFileInfoView() const override
{ {
return std::make_unique<CustomFileInfoView>(_customThemeInfo, _fontRepository); return CustomFileInfoView::CreateShared(_customThemeInfo, _fontRepository);
} }
std::unique_ptr<RecyclerViewBase> CreateCoverFlowRecyclerView() const override SharedPtr<RecyclerViewBase> CreateCoverFlowRecyclerView() const override
{ {
return std::make_unique<CoverFlowRecyclerView>(); return CoverFlowRecyclerView::CreateShared();
} }
FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter( SharedPtr<FileRecyclerAdapter> CreateCoverFlowRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
VBlankTextureLoader* vblankTextureLoader) const override VBlankTextureLoader* vblankTextureLoader) const override
{ {
return new CoverFlowFileRecyclerAdapter( return SharedPtr<CoverFlowFileRecyclerAdapter>::MakeShared(viewModel->GetRomBrowserController(),
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), &viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository()); themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository());
} }
Point GetTopCoverPosition() const override
{
return _customThemeInfo->topCoverInfo.GetPosition();
}
void LoadResources(const ITheme& theme, const VramContext& mainVramContext); void LoadResources(const ITheme& theme, const VramContext& mainVramContext);
private: private:

View File

@@ -24,7 +24,7 @@ CheatsViewModel::CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserControl
}); });
} }
void CheatsViewModel::ActivateSelectedItem() void CheatsViewModel::ActivateItem(int index)
{ {
if (_state != State::DisplayCheats) if (_state != State::DisplayCheats)
{ {
@@ -36,19 +36,19 @@ void CheatsViewModel::ActivateSelectedItem()
u32 numberOfSubEntries = 0; u32 numberOfSubEntries = 0;
auto subEntries = cheatCategory->GetSubEntries(numberOfSubEntries); auto subEntries = cheatCategory->GetSubEntries(numberOfSubEntries);
if (numberOfSubEntries == 0) if (numberOfSubEntries == 0 || index < 0 || index >= (int)numberOfSubEntries)
{ {
// There is nothing to activate // There is nothing to activate
return; return;
} }
auto& entry = subEntries[_selectedItem]; auto& entry = subEntries[index];
if (entry.IsCheatCategory()) if (entry.IsCheatCategory())
{ {
// Category activated // Category activated
if (_categoryStackLevel + 1 != _categoryStack.size()) if (_categoryStackLevel + 1 != _categoryStack.size())
{ {
_categoryStack[++_categoryStackLevel] = { &entry, (u32)_selectedItem }; _categoryStack[++_categoryStackLevel] = { &entry, (u32)index };
_selectedItem = 0; _selectedItem = 0;
} }
} }

View File

@@ -25,8 +25,8 @@ public:
CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserController* romBrowserController); CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserController* romBrowserController);
/// @brief Activates the selected cheat or category. /// @brief Activates the cheat or category at the specified \p index.
void ActivateSelectedItem(); void ActivateItem(int index);
/// @brief Navigates up in the cheat hierachy, or closes the cheats panel when at the root. /// @brief Navigates up in the cheat hierachy, or closes the cheats panel when at the root.
/// @return \c true when navigation happened in the cheats tree, or \c false when the cheats panel was closed. /// @return \c true when navigation happened in the cheats tree, or \c false when the cheats panel was closed.
@@ -54,9 +54,9 @@ public:
/// @param selectedItem The index of the selected item to set. /// @param selectedItem The index of the selected item to set.
void SetSelectedItem(int selectedItem) { _selectedItem = selectedItem; } void SetSelectedItem(int selectedItem) { _selectedItem = selectedItem; }
/// @brief Returns whether the category name should be displayed. /// @brief Returns whether the current displayed category is a sub-category.
/// @return \c true when the category name should be displayed, or \c false otherwise. /// @return \c true when the current displayed category is a sub-category, or \c false otherwise.
bool ShouldShowCategoryName() const bool IsInSubCategory() const
{ {
return _categoryStackLevel > 0; return _categoryStackLevel > 0;
} }

View File

@@ -0,0 +1,33 @@
#include "common.h"
#include "romBrowser/IRomBrowserController.h"
#include "RomBrowserViewModel.h"
#include "romBrowser/FileType/Nds/NdsFileType.h"
#include "RomBrowserItemViewModel.h"
void RomBrowserItemViewModel::Activate()
{
if (_index >= 0)
{
const auto& item = _romBrowserController->GetRomBrowserViewModel()->GetFileInfoManager().GetItem(_index);
if (item.GetFileType()->GetClassification() == FileTypeClassification::Folder)
{
_romBrowserController->NavigateToPath(item.GetFileName());
}
else
{
_romBrowserController->LaunchFile(item);
}
}
}
void RomBrowserItemViewModel::ShowGameInfo()
{
if (_index >= 0)
{
const auto& item = _romBrowserController->GetRomBrowserViewModel()->GetFileInfoManager().GetItem(_index);
if (item.GetFileType() == &NdsFileType::sInstance)
{
_romBrowserController->ShowGameInfo(item);
}
}
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include "core/task/TaskQueue.h"
class IRomBrowserController;
class RomBrowserItemViewModel
{
public:
explicit RomBrowserItemViewModel(IRomBrowserController* romBrowserController)
: _romBrowserController(romBrowserController) { }
void Activate();
void ShowGameInfo();
void SetIndex(int index)
{
_index = index;
}
void SetQueueTask(QueueTask<void> queueTask)
{
_queueTask = std::move(queueTask);
}
void CancelQueueTask()
{
_queueTask.CancelTask();
}
void DisposeQueueTaskWhenComplete()
{
if (_queueTask.GetTask().IsCompleted())
{
_queueTask.Dispose();
}
}
private:
int _index = -1;
QueueTask<void> _queueTask;
IRomBrowserController* _romBrowserController;
};

View File

@@ -40,29 +40,7 @@ RomBrowserViewModel::RomBrowserViewModel(IRomBrowserController* romBrowserContro
_selectedItem = _fileInfoManager->GetItemIndex(initialSelectedFileName); _selectedItem = _fileInfoManager->GetItemIndex(initialSelectedFileName);
} }
void RomBrowserViewModel::ItemActivated()
{
const auto& item = _fileInfoManager->GetItem(_selectedItem);
if (item.GetFileType()->GetClassification() == FileTypeClassification::Folder)
{
_romBrowserController->NavigateToPath(item.GetFileName());
}
else
{
_romBrowserController->LaunchFile(item);
}
}
void RomBrowserViewModel::NavigateUp() void RomBrowserViewModel::NavigateUp()
{ {
_romBrowserController->NavigateUp(); _romBrowserController->NavigateUp();
} }
void RomBrowserViewModel::ShowGameInfo()
{
const auto& item = _fileInfoManager->GetItem(_selectedItem);
if (item.GetFileType() == &NdsFileType::sInstance)
{
_romBrowserController->ShowGameInfo(item);
}
}

View File

@@ -13,6 +13,7 @@ class RomBrowserViewModel
public: public:
RomBrowserViewModel(IRomBrowserController* romBrowserController, const char* initialSelectedFileName = nullptr); RomBrowserViewModel(IRomBrowserController* romBrowserController, const char* initialSelectedFileName = nullptr);
IRomBrowserController* GetRomBrowserController() const { return _romBrowserController; }
FileInfoManager& GetFileInfoManager() const { return *_fileInfoManager; } FileInfoManager& GetFileInfoManager() const { return *_fileInfoManager; }
TaskQueueBase* GetIoTaskQueue() const { return _romBrowserController->GetIoTaskQueue(); } TaskQueueBase* GetIoTaskQueue() const { return _romBrowserController->GetIoTaskQueue(); }
TaskQueueBase* GetBgTaskQueue() const { return _romBrowserController->GetBgTaskQueue(); } TaskQueueBase* GetBgTaskQueue() const { return _romBrowserController->GetBgTaskQueue(); }
@@ -24,9 +25,7 @@ public:
constexpr u32 GetIconFrameCounter() const { return _iconFrameCounter; } constexpr u32 GetIconFrameCounter() const { return _iconFrameCounter; }
void SetIconFrameCounter(u32 iconFrameCounter) { _iconFrameCounter = iconFrameCounter; } void SetIconFrameCounter(u32 iconFrameCounter) { _iconFrameCounter = iconFrameCounter; }
void ItemActivated();
void NavigateUp(); void NavigateUp();
void ShowGameInfo();
private: private:
IRomBrowserController* _romBrowserController; IRomBrowserController* _romBrowserController;

View File

@@ -6,21 +6,12 @@
AppBarView::AppBarView(int x, int y, Orientation orientation, AppBarView::AppBarView(int x, int y, Orientation orientation,
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme) int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme)
: _orientation(orientation) : _orientation(orientation)
, _buttons(std::make_unique<IconButtonView*[]>(startButtonCount + endButtonCount)) , _buttons(std::make_unique<SharedPtr<IconButtonView>[]>(startButtonCount + endButtonCount))
, _startButtonCount(startButtonCount), _endButtonCount(endButtonCount) , _startButtonCount(startButtonCount), _endButtonCount(endButtonCount)
{ {
SetPosition(x, y); SetPosition(x, y);
} }
AppBarView::~AppBarView()
{
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{
delete _buttons[i];
_buttons[i] = nullptr;
}
}
Rectangle AppBarView::GetBounds() const Rectangle AppBarView::GetBounds() const
{ {
if (_orientation == Orientation::Horizontal) if (_orientation == Orientation::Horizontal)
@@ -39,9 +30,9 @@ void AppBarView::Update()
ViewContainer::Update(); ViewContainer::Update();
} }
View* AppBarView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) SharedPtr<View> AppBarView::MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
{ {
int idx = FindButtonIndex(currentFocus); int idx = FindButtonIndex(currentFocus.GetPointer());
if (idx >= 0) if (idx >= 0)
{ {
if (_orientation == Orientation::Horizontal) if (_orientation == Orientation::Horizontal)
@@ -71,21 +62,28 @@ View* AppBarView::MoveFocus(View* currentFocus, FocusMoveDirection direction, Vi
else if ((_orientation == Orientation::Horizontal && (direction == FocusMoveDirection::Up || direction == FocusMoveDirection::Down)) || else if ((_orientation == Orientation::Horizontal && (direction == FocusMoveDirection::Up || direction == FocusMoveDirection::Down)) ||
(_orientation == Orientation::Vertical && (direction == FocusMoveDirection::Left || direction == FocusMoveDirection::Right))) (_orientation == Orientation::Vertical && (direction == FocusMoveDirection::Left || direction == FocusMoveDirection::Right)))
{ {
if (currentFocus == nullptr) if (!currentFocus)
return _buttons[0]; return _buttons[0];
Point curFocusPoint = currentFocus->GetBounds().GetCenter(); Point curFocusPoint = currentFocus->GetBounds().GetCenter();
s64 bestDistance = std::numeric_limits<s64>::max(); s64 bestDistance = std::numeric_limits<s64>::max();
View* nearestButton = nullptr; int nearestButton = -1;
for (int i = 0; i < _startButtonCount + _endButtonCount; i++) for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{ {
s64 distance = curFocusPoint.DistanceSquaredTo(_buttons[i]->GetBounds().GetCenter()); s64 distance = curFocusPoint.DistanceSquaredTo(_buttons[i]->GetBounds().GetCenter());
if (distance < bestDistance) if (distance < bestDistance)
{ {
bestDistance = distance; bestDistance = distance;
nearestButton = _buttons[i]; nearestButton = i;
} }
} }
return nearestButton; if (nearestButton >= 0)
{
return _buttons[nearestButton];
}
else
{
return nullptr;
}
} }
else else
return View::MoveFocus(currentFocus, direction, this); return View::MoveFocus(currentFocus, direction, this);
@@ -126,7 +124,7 @@ int AppBarView::FindButtonIndex(const View* view)
{ {
for (int i = 0; i < _startButtonCount + _endButtonCount; i++) for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
{ {
if (_buttons[i] == view) if (_buttons[i].GetPointer() == view)
{ {
return i; return i;
} }

View File

@@ -14,8 +14,6 @@ public:
Vertical Vertical
}; };
virtual ~AppBarView();
void SetButtonIcon(int button, u32 vramOffset) void SetButtonIcon(int button, u32 vramOffset)
{ {
_buttons[button]->SetIconVramOffset(vramOffset); _buttons[button]->SetIconVramOffset(vramOffset);
@@ -28,14 +26,14 @@ public:
Rectangle GetBounds() const override; Rectangle GetBounds() const override;
void Update() override; void Update() override;
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override; SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source) override;
void Focus(FocusManager& focusManager, int button); void Focus(FocusManager& focusManager, int button);
constexpr Orientation GetOrientation() const { return _orientation; } constexpr Orientation GetOrientation() const { return _orientation; }
protected: protected:
Orientation _orientation; Orientation _orientation;
std::unique_ptr<IconButtonView*[]> _buttons; std::unique_ptr<SharedPtr<IconButtonView>[]> _buttons;
int _startButtonCount; int _startButtonCount;
int _endButtonCount; int _endButtonCount;

View File

@@ -1,21 +1,26 @@
#include "common.h" #include "common.h"
#include "gui/IVramManager.h" #include "gui/IVramManager.h"
#include "gui/GraphicsContext.h" #include "gui/GraphicsContext.h"
#include "gui/input/InputProvider.h"
#include "BannerListItemView.h" #include "BannerListItemView.h"
BannerListItemView::BannerListItemView(std::unique_ptr<LabelView> firstLine, BannerListItemView::BannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel,
std::unique_ptr<LabelView> secondLine, std::unique_ptr<LabelView> thirdLine) SharedPtr<LabelView> firstLine, SharedPtr<LabelView> secondLine, SharedPtr<LabelView> thirdLine)
: _firstLine(std::move(firstLine)) : _viewModel(std::move(viewModel))
, _firstLine(std::move(firstLine))
, _secondLine(std::move(secondLine)) , _secondLine(std::move(secondLine))
, _thirdLine(std::move(thirdLine)) , _thirdLine(std::move(thirdLine))
, _inputHandler(this, _viewModel.get())
{ {
AddChildTail(_firstLine.get()); AddChildTail(_firstLine.GetPointer());
AddChildTail(_secondLine.get()); AddChildTail(_secondLine.GetPointer());
AddChildTail(_thirdLine.get()); AddChildTail(_thirdLine.GetPointer());
} }
void BannerListItemView::Update() void BannerListItemView::Update()
{ {
_viewModel->DisposeQueueTaskWhenComplete();
ViewContainer::Update(); ViewContainer::Update();
if (_icon) if (_icon)
@@ -23,3 +28,24 @@ void BannerListItemView::Update()
_icon->Update(); _icon->Update();
} }
} }
bool BannerListItemView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
return _inputHandler.HandleInput(inputProvider, focusManager)
|| View::HandleInput(inputProvider, focusManager);
}
void BannerListItemView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenDown(touchPoint, focusManager);
}
void BannerListItemView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenMove(touchPoint, focusManager);
}
void BannerListItemView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
_inputHandler.HandlePenUp(lastTouchPoint, focusManager);
}

View File

@@ -2,6 +2,8 @@
#include "BannerView.h" #include "BannerView.h"
#include "gui/views/LabelView.h" #include "gui/views/LabelView.h"
#include "../FileType/FileIcon.h" #include "../FileType/FileIcon.h"
#include "romBrowser/viewModels/RomBrowserItemViewModel.h"
#include "RomBrowserItemInputHandler.h"
class BannerListItemView : public BannerView class BannerListItemView : public BannerView
{ {
@@ -19,11 +21,13 @@ public:
constexpr u32 GetVramOffset() const { return _vramOffset; } 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; void Update() override;
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
virtual void SetGraphics(const VramToken& vramToken) { } virtual void SetGraphics(const VramToken& vramToken) { }
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override
@@ -60,8 +64,18 @@ public:
_thirdLine->SetText(thirdLine, length); _thirdLine->SetText(thirdLine, length);
} }
RomBrowserItemViewModel& GetViewModel() const
{
return *_viewModel;
}
protected: protected:
std::unique_ptr<LabelView> _firstLine; std::unique_ptr<RomBrowserItemViewModel> _viewModel;
std::unique_ptr<LabelView> _secondLine; SharedPtr<LabelView> _firstLine;
std::unique_ptr<LabelView> _thirdLine; SharedPtr<LabelView> _secondLine;
SharedPtr<LabelView> _thirdLine;
RomBrowserItemInputHandler _inputHandler;
BannerListItemView(std::unique_ptr<RomBrowserItemViewModel> viewModel, SharedPtr<LabelView> firstLine,
SharedPtr<LabelView> secondLine, SharedPtr<LabelView> thirdLine);
}; };

View File

@@ -0,0 +1,34 @@
#include "common.h"
#include "BottomSheetView.h"
void BottomSheetView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
{
DialogView::HandlePenDown(touchPoint, focusManager);
if (!GetBounds().Contains(touchPoint))
{
_oobPenDown = true;
}
}
void BottomSheetView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
{
DialogView::HandlePenMove(touchPoint, focusManager);
if (GetBounds().Contains(touchPoint))
{
_oobPenDown = false;
}
}
void BottomSheetView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
{
DialogView::HandlePenUp(lastTouchPoint, focusManager);
if (_oobPenDown && !GetBounds().Contains(lastTouchPoint))
{
Close();
}
_oobPenDown = false;
}

Some files were not shown because too many files have changed in this diff Show More