mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-06-02 17:16:57 +02:00
Initial commit
This commit is contained in:
104
arm9/source/romBrowser/CoverRepository.cpp
Normal file
104
arm9/source/romBrowser/CoverRepository.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include "core/StringUtil.h"
|
||||
#include "FileType/NullFileTypeProvider.h"
|
||||
#include "FileType/BmpFileCover.h"
|
||||
#include "FileType/InternalFileInfo.h"
|
||||
#include "SdFolderFactory.h"
|
||||
#include "CoverRepository.h"
|
||||
|
||||
void CoverRepository::Initialize()
|
||||
{
|
||||
NullFileTypeProvider fileTypeProvider;
|
||||
_ndsCoversFolder = SdFolderFactory(&fileTypeProvider).CreateFromPath("/_pico/covers/nds");
|
||||
if (_ndsCoversFolder)
|
||||
{
|
||||
_ndsCoversFolder->SortByNameInPlace();
|
||||
}
|
||||
_gbaCoversFolder = SdFolderFactory(&fileTypeProvider).CreateFromPath("/_pico/covers/gba");
|
||||
if (_gbaCoversFolder)
|
||||
{
|
||||
_gbaCoversFolder->SortByNameInPlace();
|
||||
}
|
||||
_userCoversFolder = SdFolderFactory(&fileTypeProvider).CreateFromPath("/_pico/covers/user");
|
||||
if (_userCoversFolder)
|
||||
{
|
||||
_userCoversFolder->SortByNameInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
FileCover* CoverRepository::GetCoverForFile(const FileInfo& fileInfo, const InternalFileInfo* internalFileInfo) const
|
||||
{
|
||||
char nameBuffer[256];
|
||||
const auto& fileType = fileInfo.GetFileType();
|
||||
|
||||
if (fileType->GetClassification() != FileTypeClassification::Folder)
|
||||
{
|
||||
const FileInfo* coverFile = nullptr;
|
||||
|
||||
// Try to get a cover based on the filename in the user folder
|
||||
if (_userCoversFolder)
|
||||
{
|
||||
u32 length = StringUtil::Copy(nameBuffer, fileInfo.GetFileName(), sizeof(nameBuffer) - 5);
|
||||
nameBuffer[length + 0] = '.';
|
||||
nameBuffer[length + 1] = 'b';
|
||||
nameBuffer[length + 2] = 'm';
|
||||
nameBuffer[length + 3] = 'p';
|
||||
nameBuffer[length + 4] = 0;
|
||||
coverFile = _userCoversFolder->BinarySearch(nameBuffer);
|
||||
}
|
||||
|
||||
// Try to get a cover based on an internal game code
|
||||
if (!coverFile && internalFileInfo)
|
||||
{
|
||||
const auto* coverFolder = GetCoverFolder(fileType->GetShortName());
|
||||
if (coverFolder)
|
||||
{
|
||||
const char* gameCode = internalFileInfo->GetGameCode();
|
||||
if (gameCode)
|
||||
{
|
||||
u32 length = StringUtil::Copy(nameBuffer, gameCode, sizeof(nameBuffer) - 5);
|
||||
nameBuffer[length + 0] = '.';
|
||||
nameBuffer[length + 1] = 'b';
|
||||
nameBuffer[length + 2] = 'm';
|
||||
nameBuffer[length + 3] = 'p';
|
||||
nameBuffer[length + 4] = 0;
|
||||
}
|
||||
|
||||
coverFile = coverFolder->BinarySearch(nameBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (coverFile)
|
||||
{
|
||||
return new BmpFileCover(coverFile->GetFastFileRef());
|
||||
}
|
||||
|
||||
if (!coverFile && internalFileInfo)
|
||||
{
|
||||
auto cover = internalFileInfo->CreateGameCover();
|
||||
if (cover)
|
||||
{
|
||||
return cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fileType->CreateFileCover(fileInfo.GetFileName());
|
||||
}
|
||||
|
||||
const SdFolder* CoverRepository::GetCoverFolder(const char* coverFolderName) const
|
||||
{
|
||||
if (!strcmp(coverFolderName, "nds"))
|
||||
{
|
||||
return _ndsCoversFolder.get();
|
||||
}
|
||||
else if (!strcmp(coverFolderName, "gba"))
|
||||
{
|
||||
return _gbaCoversFolder.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
18
arm9/source/romBrowser/CoverRepository.h
Normal file
18
arm9/source/romBrowser/CoverRepository.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "ICoverRepository.h"
|
||||
#include "SdFolder.h"
|
||||
|
||||
class CoverRepository : public ICoverRepository
|
||||
{
|
||||
public:
|
||||
void Initialize() override;
|
||||
FileCover* GetCoverForFile(
|
||||
const FileInfo& fileInfo, const InternalFileInfo* internalFileInfo) const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<SdFolder> _ndsCoversFolder;
|
||||
std::unique_ptr<SdFolder> _gbaCoversFolder;
|
||||
std::unique_ptr<SdFolder> _userCoversFolder;
|
||||
|
||||
const SdFolder* GetCoverFolder(const char* coverFolderName) const;
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "common.h"
|
||||
#include "../FileInfoManager.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "../views/BannerListItemView.h"
|
||||
#include "../Theme/IRomBrowserViewFactory.h"
|
||||
#include "BannerListFileRecyclerAdapter.h"
|
||||
|
||||
void BannerListFileRecyclerAdapter::GetViewSize(int& width, int& height) const
|
||||
{
|
||||
width = 203;
|
||||
height = 44;
|
||||
}
|
||||
|
||||
View* BannerListFileRecyclerAdapter::CreateView() const
|
||||
{
|
||||
return _romBrowserViewFactory->CreateBannerListItemView(_vblankTextureLoader);
|
||||
}
|
||||
|
||||
void BannerListFileRecyclerAdapter::DestroyView(View* view) const
|
||||
{
|
||||
delete static_cast<BannerListItemView*>(view);
|
||||
}
|
||||
|
||||
void BannerListFileRecyclerAdapter::BindView(View* view, int index) const
|
||||
{
|
||||
auto listItemView = static_cast<BannerListItemView*>(view);
|
||||
listItemView->SetGraphics(_bannerListItemViewGraphics);
|
||||
FileRecyclerAdapter::BindView(view, index);
|
||||
}
|
||||
|
||||
TaskResult<void> BannerListFileRecyclerAdapter::BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
|
||||
{
|
||||
auto listItemView = static_cast<BannerListItemView*>(view);
|
||||
const auto& fileInfo = _fileInfoManager->GetItem(index);
|
||||
bool fileNameAsTitle = true;
|
||||
if (internalFileInfo)
|
||||
{
|
||||
const char16_t* gameTitle = internalFileInfo->GetGameTitle();
|
||||
if (gameTitle)
|
||||
{
|
||||
listItemView->SetGameTitle(gameTitle);
|
||||
fileNameAsTitle = false;
|
||||
}
|
||||
}
|
||||
listItemView->SetFileName(fileInfo.GetFileName(), fileNameAsTitle);
|
||||
auto icon = internalFileInfo ? internalFileInfo->CreateGameIcon() : nullptr;
|
||||
if (!icon)
|
||||
{
|
||||
icon = fileInfo.GetFileType()->CreateFileIcon("", _themeFileIconFactory);
|
||||
}
|
||||
if (icon != nullptr)
|
||||
{
|
||||
if (cancelRequested)
|
||||
{
|
||||
icon.reset();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
icon->SetAnimFrame(_iconFrameCounter);
|
||||
listItemView->SetIcon(std::move(icon));
|
||||
listItemView->UploadIconGraphics();
|
||||
if (cancelRequested)
|
||||
{
|
||||
listItemView->SetIcon(nullptr);
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
}
|
||||
return TaskResult<void>::Completed();
|
||||
}
|
||||
|
||||
void BannerListFileRecyclerAdapter::ReleaseView(View* view, int index) const
|
||||
{
|
||||
LOG_DEBUG("Releasing %d\n", index);
|
||||
auto listItemView = static_cast<BannerListItemView*>(view);
|
||||
listItemView->SetIcon(nullptr);
|
||||
listItemView->SetGameTitle(u"");
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
}
|
||||
|
||||
void BannerListFileRecyclerAdapter::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
_bannerListItemViewGraphics = _romBrowserViewFactory->UploadBannerListItemViewGraphics(vramContext);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "../FileRecyclerAdapter.h"
|
||||
#include "../views/BannerListItemView.h"
|
||||
|
||||
class TaskQueueBase;
|
||||
class IRomBrowserViewFactory;
|
||||
|
||||
class BannerListFileRecyclerAdapter : public FileRecyclerAdapter
|
||||
{
|
||||
public:
|
||||
BannerListFileRecyclerAdapter(FileInfoManager* fileInfoManager,
|
||||
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
VBlankTextureLoader* vblankTextureLoader)
|
||||
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory)
|
||||
, _romBrowserViewFactory(romBrowserViewFactory)
|
||||
, _vblankTextureLoader(vblankTextureLoader) { }
|
||||
|
||||
void GetViewSize(int& width, int& height) const override;
|
||||
View* CreateView() const override;
|
||||
void DestroyView(View* view) const override;
|
||||
void BindView(View* view, int index) const override;
|
||||
void ReleaseView(View* view, int index) const override;
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
|
||||
private:
|
||||
const IRomBrowserViewFactory* _romBrowserViewFactory;
|
||||
BannerListItemView::VramToken _bannerListItemViewGraphics;
|
||||
VBlankTextureLoader* _vblankTextureLoader;
|
||||
|
||||
TaskResult<void> BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "common.h"
|
||||
#include "../FileInfoManager.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "../views/CoverView.h"
|
||||
#include "../Theme/IRomBrowserViewFactory.h"
|
||||
#include "../FileType/UnknownFileCover.h"
|
||||
#include "romBrowser/ICoverRepository.h"
|
||||
#include "CoverFlowFileRecyclerAdapter.h"
|
||||
|
||||
void CoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height) const
|
||||
{
|
||||
width = 44;
|
||||
height = 44;
|
||||
}
|
||||
|
||||
View* CoverFlowFileRecyclerAdapter::CreateView() const
|
||||
{
|
||||
return new CoverView(_vblankTextureLoader);
|
||||
}
|
||||
|
||||
void CoverFlowFileRecyclerAdapter::DestroyView(View* view) const
|
||||
{
|
||||
auto coverView = static_cast<CoverView*>(view);
|
||||
delete coverView;
|
||||
}
|
||||
|
||||
TaskResult<void> CoverFlowFileRecyclerAdapter::BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
|
||||
{
|
||||
auto coverView = static_cast<CoverView*>(view);
|
||||
auto cover = _fileInfoManager->GetFileCover(index);
|
||||
if (cancelRequested)
|
||||
{
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
coverView->SetCover(std::move(cover));
|
||||
coverView->UploadCoverGraphics();
|
||||
if (cancelRequested)
|
||||
{
|
||||
coverView->ClearCover();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
return TaskResult<void>::Completed();
|
||||
}
|
||||
|
||||
void CoverFlowFileRecyclerAdapter::ReleaseView(View* view, int index) const
|
||||
{
|
||||
LOG_DEBUG("Releasing %d\n", index);
|
||||
auto coverView = static_cast<CoverView*>(view);
|
||||
coverView->ClearCover();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
}
|
||||
|
||||
void CoverFlowFileRecyclerAdapter::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
// _iconGridItemViewGraphics = _romBrowserViewFactory->UploadIconGridItemViewGraphics(vramManager);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "../FileRecyclerAdapter.h"
|
||||
|
||||
class IRomBrowserViewFactory;
|
||||
class VBlankTextureLoader;
|
||||
class ICoverRepository;
|
||||
|
||||
class CoverFlowFileRecyclerAdapter : public FileRecyclerAdapter
|
||||
{
|
||||
public:
|
||||
CoverFlowFileRecyclerAdapter(FileInfoManager* fileInfoManager,
|
||||
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
VBlankTextureLoader* vblankTextureLoader,
|
||||
const ICoverRepository* coverRepository)
|
||||
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory)
|
||||
, _romBrowserViewFactory(romBrowserViewFactory)
|
||||
, _vblankTextureLoader(vblankTextureLoader)
|
||||
, _coverRepository(coverRepository) { }
|
||||
|
||||
void GetViewSize(int& width, int& height) const override;
|
||||
View* CreateView() const override;
|
||||
void DestroyView(View* view) const override;
|
||||
void ReleaseView(View* view, int index) const override;
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
|
||||
private:
|
||||
const IRomBrowserViewFactory* _romBrowserViewFactory;
|
||||
VBlankTextureLoader* _vblankTextureLoader;
|
||||
const ICoverRepository* _coverRepository;
|
||||
|
||||
TaskResult<void> BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "common.h"
|
||||
#include "../FileInfoManager.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "../views/IconGridItemView.h"
|
||||
#include "../Theme/IRomBrowserViewFactory.h"
|
||||
#include "IconGridFileRecyclerAdapter.h"
|
||||
|
||||
void IconGridFileRecyclerAdapter::GetViewSize(int& width, int& height) const
|
||||
{
|
||||
width = 44;
|
||||
height = 44;
|
||||
}
|
||||
|
||||
View* IconGridFileRecyclerAdapter::CreateView() const
|
||||
{
|
||||
return _romBrowserViewFactory->CreateIconGridItemView();
|
||||
}
|
||||
|
||||
void IconGridFileRecyclerAdapter::DestroyView(View* view) const
|
||||
{
|
||||
delete static_cast<IconGridItemView*>(view);
|
||||
}
|
||||
|
||||
void IconGridFileRecyclerAdapter::BindView(View* view, int index) const
|
||||
{
|
||||
auto iconGridItemView = static_cast<IconGridItemView*>(view);
|
||||
iconGridItemView->SetGraphics(_iconGridItemViewGraphics);
|
||||
FileRecyclerAdapter::BindView(view, index);
|
||||
}
|
||||
|
||||
TaskResult<void> IconGridFileRecyclerAdapter::BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
|
||||
{
|
||||
auto iconGridItemView = static_cast<IconGridItemView*>(view);
|
||||
auto icon = internalFileInfo ? internalFileInfo->CreateGameIcon() : nullptr;
|
||||
if (!icon)
|
||||
{
|
||||
const auto& fileInfo = _fileInfoManager->GetItem(index);
|
||||
icon = fileInfo.GetFileType()->CreateFileIcon(fileInfo.GetFileName(), _themeFileIconFactory);
|
||||
}
|
||||
if (icon != nullptr)
|
||||
{
|
||||
if (cancelRequested)
|
||||
{
|
||||
icon.reset();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
icon->SetAnimFrame(_iconFrameCounter);
|
||||
iconGridItemView->SetIcon(std::move(icon));
|
||||
iconGridItemView->UploadIconGraphics();
|
||||
if (cancelRequested)
|
||||
{
|
||||
iconGridItemView->SetIcon(nullptr);
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
}
|
||||
return TaskResult<void>::Completed();
|
||||
}
|
||||
|
||||
void IconGridFileRecyclerAdapter::ReleaseView(View* view, int index) const
|
||||
{
|
||||
LOG_DEBUG("Releasing %d\n", index);
|
||||
auto iconGridItemView = static_cast<IconGridItemView*>(view);
|
||||
iconGridItemView->SetIcon(nullptr);
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
}
|
||||
|
||||
void IconGridFileRecyclerAdapter::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
_iconGridItemViewGraphics = _romBrowserViewFactory->UploadIconGridItemViewGraphics(vramContext);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "../FileRecyclerAdapter.h"
|
||||
#include "../views/IconGridItemView.h"
|
||||
|
||||
class IRomBrowserViewFactory;
|
||||
|
||||
class IconGridFileRecyclerAdapter : public FileRecyclerAdapter
|
||||
{
|
||||
public:
|
||||
IconGridFileRecyclerAdapter(FileInfoManager* fileInfoManager,
|
||||
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory)
|
||||
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory)
|
||||
, _romBrowserViewFactory(romBrowserViewFactory) { }
|
||||
|
||||
void GetViewSize(int& width, int& height) const override;
|
||||
View* CreateView() const override;
|
||||
void DestroyView(View* view) const override;
|
||||
void BindView(View* view, int index) const override;
|
||||
void ReleaseView(View* view, int index) const override;
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
|
||||
private:
|
||||
const IRomBrowserViewFactory* _romBrowserViewFactory;
|
||||
IconGridItemView::VramToken _iconGridItemViewGraphics;
|
||||
|
||||
TaskResult<void> BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "RomBrowserBannerListDisplayMode.h"
|
||||
|
||||
const RomBrowserBannerListDisplayMode RomBrowserBannerListDisplayMode::sInstance;
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "gui/views/RecyclerView.h"
|
||||
#include "RomBrowserDisplayMode.h"
|
||||
#include "BannerListFileRecyclerAdapter.h"
|
||||
|
||||
class RomBrowserBannerListDisplayMode : public RomBrowserDisplayMode
|
||||
{
|
||||
public:
|
||||
static const RomBrowserBannerListDisplayMode sInstance;
|
||||
|
||||
bool IsVertical() const override { return true; }
|
||||
|
||||
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
int startButtonCount, int endButtonCount) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateAppBarView(0, 0,
|
||||
AppBarView::Orientation::Vertical, startButtonCount, endButtonCount);
|
||||
}
|
||||
|
||||
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
|
||||
{
|
||||
auto recyclerView = std::make_unique<RecyclerView>(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalList);
|
||||
recyclerView->SetPadding(0, 3);
|
||||
recyclerView->SetItemSpacing(0, 3);
|
||||
return recyclerView;
|
||||
}
|
||||
|
||||
FileRecyclerAdapter* CreateRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return new BannerListFileRecyclerAdapter(
|
||||
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(), themeFileIconFactory,
|
||||
romBrowserViewFactory, vblankTextureLoader);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr RomBrowserBannerListDisplayMode() { }
|
||||
};
|
||||
23
arm9/source/romBrowser/DisplayMode/RomBrowserDisplayMode.h
Normal file
23
arm9/source/romBrowser/DisplayMode/RomBrowserDisplayMode.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "../views/AppBarView.h"
|
||||
#include "gui/views/RecyclerViewBase.h"
|
||||
#include "../FileRecyclerAdapter.h"
|
||||
#include "../viewModels/RomBrowserViewModel.h"
|
||||
#include "../Theme/IRomBrowserViewFactory.h"
|
||||
|
||||
class VBlankTextureLoader;
|
||||
class ICoverRepository;
|
||||
|
||||
class RomBrowserDisplayMode
|
||||
{
|
||||
public:
|
||||
virtual bool IsVertical() const = 0;
|
||||
virtual bool ShowCoverOnTopScreen() const { return true; }
|
||||
virtual std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
int startButtonCount, int endButtonCount) const = 0;
|
||||
virtual std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const = 0;
|
||||
virtual FileRecyclerAdapter* CreateRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const = 0;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "common.h"
|
||||
#include "RomBrowserHorizontalIconGridDisplayMode.h"
|
||||
#include "RomBrowserVerticalIconGridDisplayMode.h"
|
||||
#include "RomBrowserBannerListDisplayMode.h"
|
||||
#include "RomBrowserHorizontalCoverFlowDisplayMode.h"
|
||||
#include "RomBrowserDisplayModeFactory.h"
|
||||
|
||||
const RomBrowserDisplayMode* RomBrowserDisplayModeFactory::GetRomBrowserDisplayMode(
|
||||
RomBrowserLayout romBrowserDisplayMode) const
|
||||
{
|
||||
switch (romBrowserDisplayMode)
|
||||
{
|
||||
case RomBrowserLayout::HorizontalIconGrid:
|
||||
{
|
||||
return &RomBrowserHorizontalIconGridDisplayMode::sInstance;
|
||||
}
|
||||
case RomBrowserLayout::VerticalIconGrid:
|
||||
{
|
||||
return &RomBrowserVerticalIconGridDisplayMode::sInstance;
|
||||
}
|
||||
case RomBrowserLayout::BannerList:
|
||||
{
|
||||
return &RomBrowserBannerListDisplayMode::sInstance;
|
||||
}
|
||||
case RomBrowserLayout::CoverFlow:
|
||||
{
|
||||
return &RomBrowserHorizontalCoverFlowDisplayMode::sInstance;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "services/settings/RomBrowserLayout.h"
|
||||
#include "RomBrowserDisplayMode.h"
|
||||
|
||||
class RomBrowserDisplayModeFactory
|
||||
{
|
||||
public:
|
||||
const RomBrowserDisplayMode* GetRomBrowserDisplayMode(
|
||||
RomBrowserLayout romBrowserDisplayMode) const;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "RomBrowserHorizontalCoverFlowDisplayMode.h"
|
||||
|
||||
const RomBrowserHorizontalCoverFlowDisplayMode RomBrowserHorizontalCoverFlowDisplayMode::sInstance;
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "RomBrowserDisplayMode.h"
|
||||
|
||||
class RomBrowserHorizontalCoverFlowDisplayMode : public RomBrowserDisplayMode
|
||||
{
|
||||
public:
|
||||
static const RomBrowserHorizontalCoverFlowDisplayMode sInstance;
|
||||
|
||||
bool IsVertical() const override { return false; }
|
||||
bool ShowCoverOnTopScreen() const override { return false; }
|
||||
|
||||
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
int startButtonCount, int endButtonCount) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateAppBarView(0, 0,
|
||||
AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount);
|
||||
}
|
||||
|
||||
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateCoverFlowRecyclerView();
|
||||
}
|
||||
|
||||
FileRecyclerAdapter* CreateRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateCoverFlowRecyclerAdapter(
|
||||
viewModel, themeFileIconFactory, vblankTextureLoader);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr RomBrowserHorizontalCoverFlowDisplayMode() { }
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "RomBrowserHorizontalIconGridDisplayMode.h"
|
||||
|
||||
const RomBrowserHorizontalIconGridDisplayMode RomBrowserHorizontalIconGridDisplayMode::sInstance;
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "gui/views/RecyclerView.h"
|
||||
#include "RomBrowserDisplayMode.h"
|
||||
#include "IconGridFileRecyclerAdapter.h"
|
||||
|
||||
class RomBrowserHorizontalIconGridDisplayMode : public RomBrowserDisplayMode
|
||||
{
|
||||
public:
|
||||
static const RomBrowserHorizontalIconGridDisplayMode sInstance;
|
||||
|
||||
bool IsVertical() const override { return false; }
|
||||
|
||||
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
int startButtonCount, int endButtonCount) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateAppBarView(0, 0,
|
||||
AppBarView::Orientation::Horizontal, startButtonCount, endButtonCount);
|
||||
}
|
||||
|
||||
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
|
||||
{
|
||||
auto recyclerView = std::make_unique<RecyclerView>(0, 42, 256, 192 - 42, RecyclerView::Mode::HorizontalGrid);
|
||||
recyclerView->SetPadding(10, 0);
|
||||
recyclerView->SetItemSpacing(4, 4);
|
||||
return recyclerView;
|
||||
}
|
||||
|
||||
FileRecyclerAdapter* CreateRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return new IconGridFileRecyclerAdapter(
|
||||
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
|
||||
themeFileIconFactory, romBrowserViewFactory);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr RomBrowserHorizontalIconGridDisplayMode() { }
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "RomBrowserVerticalIconGridDisplayMode.h"
|
||||
|
||||
const RomBrowserVerticalIconGridDisplayMode RomBrowserVerticalIconGridDisplayMode::sInstance;
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "gui/views/RecyclerView.h"
|
||||
#include "RomBrowserDisplayMode.h"
|
||||
#include "IconGridFileRecyclerAdapter.h"
|
||||
|
||||
class RomBrowserVerticalIconGridDisplayMode : public RomBrowserDisplayMode
|
||||
{
|
||||
public:
|
||||
static const RomBrowserVerticalIconGridDisplayMode sInstance;
|
||||
|
||||
bool IsVertical() const override { return true; }
|
||||
|
||||
std::unique_ptr<AppBarView> CreateAppBarView(const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
int startButtonCount, int endButtonCount) const override
|
||||
{
|
||||
return romBrowserViewFactory->CreateAppBarView(0, 0,
|
||||
AppBarView::Orientation::Vertical, startButtonCount, endButtonCount);
|
||||
}
|
||||
|
||||
std::unique_ptr<RecyclerViewBase> CreateRecyclerView(const IRomBrowserViewFactory* romBrowserViewFactory) const override
|
||||
{
|
||||
auto recyclerView = std::make_unique<RecyclerView>(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalGrid);
|
||||
recyclerView->SetPadding(0, 3);
|
||||
recyclerView->SetItemSpacing(9, 3);
|
||||
return recyclerView;
|
||||
}
|
||||
|
||||
FileRecyclerAdapter* CreateRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory, VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return new IconGridFileRecyclerAdapter(
|
||||
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
|
||||
themeFileIconFactory, romBrowserViewFactory);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr RomBrowserVerticalIconGridDisplayMode() { }
|
||||
};
|
||||
20
arm9/source/romBrowser/FileInfo.cpp
Normal file
20
arm9/source/romBrowser/FileInfo.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include "core/StringUtil.h"
|
||||
#include "FileInfo.h"
|
||||
|
||||
FileInfo::FileInfo(const FileInfo& fileInfo)
|
||||
: _type(fileInfo._type), _fastFileRef(fileInfo._fastFileRef)
|
||||
{
|
||||
u32 bufferLength = strlen(fileInfo.GetFileName()) + 1;
|
||||
_name = std::make_unique_for_overwrite<TCHAR[]>(bufferLength);
|
||||
StringUtil::Copy(_name.get(), fileInfo.GetFileName(), bufferLength);
|
||||
}
|
||||
|
||||
FileInfo::FileInfo(const TCHAR* fileName, const FileType* type, const FastFileRef& fastFileRef)
|
||||
: _type(type), _fastFileRef(fastFileRef)
|
||||
{
|
||||
u32 bufferLength = strlen(fileName) + 1;
|
||||
_name = std::make_unique_for_overwrite<TCHAR[]>(bufferLength);
|
||||
StringUtil::Copy(_name.get(), fileName, bufferLength);
|
||||
}
|
||||
42
arm9/source/romBrowser/FileInfo.h
Normal file
42
arm9/source/romBrowser/FileInfo.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "fat/ff.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
#include "FileType/FileType.h"
|
||||
|
||||
class InternalFileInfo;
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
public:
|
||||
FileInfo() { }
|
||||
FileInfo(const FileInfo& fileInfo);
|
||||
FileInfo(const TCHAR* fileName, const FileType* type, const FastFileRef& fastFileRef);
|
||||
|
||||
FileInfo &operator=(FileInfo&& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
_name = std::move(rhs._name);
|
||||
_type = rhs._type;
|
||||
_fastFileRef = rhs._fastFileRef;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const TCHAR* GetFileName() const { return _name.get(); }
|
||||
const FileType* GetFileType() const { return _type; }
|
||||
u32 GetFileSize() const { return _fastFileRef.GetFileSize(); }
|
||||
|
||||
InternalFileInfo* CreateInternalFileInfo() const
|
||||
{
|
||||
return _type->CreateInternalFileInfo(_fastFileRef);
|
||||
}
|
||||
|
||||
const FastFileRef& GetFastFileRef() const { return _fastFileRef; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<TCHAR[]> _name;
|
||||
const FileType* _type;
|
||||
FastFileRef _fastFileRef;
|
||||
};
|
||||
32
arm9/source/romBrowser/FileInfoManager.cpp
Normal file
32
arm9/source/romBrowser/FileInfoManager.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include "FileInfoManager.h"
|
||||
|
||||
FileInfoManager::FileInfoManager(std::unique_ptr<const FileInfo*[]> items, u32 itemCount, const ICoverRepository& coverRepository)
|
||||
: _items(std::move(items)), _itemCount(itemCount)
|
||||
, _extraFileInfo(std::make_unique<ExtraFileInfo[]>(itemCount))
|
||||
, _coverRepository(coverRepository) { }
|
||||
|
||||
FileInfoManager::~FileInfoManager()
|
||||
{
|
||||
for (u32 i = 0; i < _itemCount; i++)
|
||||
{
|
||||
ReleaseFileInfo(i);
|
||||
}
|
||||
}
|
||||
|
||||
int FileInfoManager::GetItemIndex(const char* fileName)
|
||||
{
|
||||
if (fileName == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for (u32 i = 0; i < _itemCount; i++)
|
||||
{
|
||||
if (strcmp(fileName, _items[i]->GetFileName()) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
70
arm9/source/romBrowser/FileInfoManager.h
Normal file
70
arm9/source/romBrowser/FileInfoManager.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <memory>
|
||||
#include "FileInfo.h"
|
||||
#include "FileType/FileCover.h"
|
||||
#include "ICoverRepository.h"
|
||||
#include "core/SharedPtr.h"
|
||||
#include "FileType/InternalFileInfo.h"
|
||||
|
||||
class FileInfoManager
|
||||
{
|
||||
public:
|
||||
FileInfoManager(std::unique_ptr<const FileInfo*[]> items, u32 itemCount, const ICoverRepository& coverRepository);
|
||||
~FileInfoManager();
|
||||
|
||||
const InternalFileInfo* GetInternalFileInfo(int index)
|
||||
{
|
||||
return _extraFileInfo[index].internalFileInfo;
|
||||
}
|
||||
|
||||
SharedPtr<FileCover> GetFileCover(int index)
|
||||
{
|
||||
return _extraFileInfo[index].fileCover;
|
||||
}
|
||||
|
||||
void LoadFileInfo(int index)
|
||||
{
|
||||
auto internalFileInfo = GetInternalFileInfo(index);
|
||||
if (!internalFileInfo)
|
||||
{
|
||||
internalFileInfo = _items[index]->CreateInternalFileInfo();
|
||||
}
|
||||
|
||||
if (!_extraFileInfo[index].fileCover.IsValid())
|
||||
{
|
||||
_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);
|
||||
|
||||
const FileInfo& GetItem(int index) const { return *_items[index]; }
|
||||
u32 GetItemCount() const { return _itemCount; }
|
||||
|
||||
private:
|
||||
struct ExtraFileInfo
|
||||
{
|
||||
const InternalFileInfo* internalFileInfo;
|
||||
SharedPtr<FileCover> fileCover;
|
||||
};
|
||||
|
||||
std::unique_ptr<const FileInfo*[]> _items;
|
||||
u32 _itemCount;
|
||||
std::unique_ptr<ExtraFileInfo[]> _extraFileInfo;
|
||||
const ICoverRepository& _coverRepository;
|
||||
};
|
||||
26
arm9/source/romBrowser/FileRecyclerAdapter.cpp
Normal file
26
arm9/source/romBrowser/FileRecyclerAdapter.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "common.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "FileInfoManager.h"
|
||||
#include "FileRecyclerAdapter.h"
|
||||
|
||||
u32 FileRecyclerAdapter::GetItemCount() const
|
||||
{
|
||||
return _fileInfoManager->GetItemCount();
|
||||
}
|
||||
|
||||
void FileRecyclerAdapter::BindView(View* view, int index) const
|
||||
{
|
||||
LOG_DEBUG("Binding %d\n", index);
|
||||
_taskQueue->Enqueue([=, this] (const vu8& cancelRequested)
|
||||
{
|
||||
LOG_DEBUG("Started task to load %d\n", index);
|
||||
_fileInfoManager->LoadFileInfo(index);
|
||||
auto internalFileInfo = _fileInfoManager->GetInternalFileInfo(index);
|
||||
if (cancelRequested)
|
||||
{
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
return BindView(view, index, internalFileInfo, cancelRequested);
|
||||
});
|
||||
}
|
||||
37
arm9/source/romBrowser/FileRecyclerAdapter.h
Normal file
37
arm9/source/romBrowser/FileRecyclerAdapter.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "gui/views/RecyclerAdapter.h"
|
||||
|
||||
class FileInfoManager;
|
||||
class IVramManager;
|
||||
class InternalFileInfo;
|
||||
class IThemeFileIconFactory;
|
||||
class VramContext;
|
||||
|
||||
class FileRecyclerAdapter : public RecyclerAdapter
|
||||
{
|
||||
public:
|
||||
u32 GetItemCount() const override;
|
||||
void BindView(View* view, int index) const override;
|
||||
|
||||
void SetIconFrameCounter(u32 iconFrameCounter)
|
||||
{
|
||||
_iconFrameCounter = iconFrameCounter;
|
||||
}
|
||||
|
||||
virtual void InitVram(const VramContext& vramContext) { }
|
||||
|
||||
protected:
|
||||
FileInfoManager* _fileInfoManager;
|
||||
TaskQueueBase* _taskQueue;
|
||||
u32 _iconFrameCounter;
|
||||
const IThemeFileIconFactory* _themeFileIconFactory;
|
||||
|
||||
FileRecyclerAdapter(FileInfoManager* fileInfoManager, TaskQueueBase* taskQueue,
|
||||
const IThemeFileIconFactory* themeFileIconFactory)
|
||||
: _fileInfoManager(fileInfoManager), _taskQueue(taskQueue)
|
||||
, _iconFrameCounter(0), _themeFileIconFactory(themeFileIconFactory) { }
|
||||
|
||||
virtual TaskResult<void> BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const = 0;
|
||||
};
|
||||
48
arm9/source/romBrowser/FileType/BmpFileCover.cpp
Normal file
48
arm9/source/romBrowser/FileType/BmpFileCover.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <nds/arm9/cache.h>
|
||||
#include <memory>
|
||||
#include <libtwl/dma/dmaNitro.h>
|
||||
#include "fat/File.h"
|
||||
#include "core/math/ColorConverter.h"
|
||||
#include "BmpFileCover.h"
|
||||
|
||||
BmpFileCover::BmpFileCover(const FastFileRef& coverFileRef)
|
||||
{
|
||||
const auto file = std::make_unique<File>();
|
||||
file->Open(coverFileRef, FA_READ);
|
||||
|
||||
if (!file->ReadExact(_coverBuffer, 0x436))
|
||||
return;
|
||||
|
||||
u32 dataOffset = _coverBuffer[0xA] | (_coverBuffer[0xB] << 8) | (_coverBuffer[0xC] << 16) | (_coverBuffer[0xD] << 24);
|
||||
|
||||
u8* paletteData32 = &_coverBuffer[0x36];
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
u32 b = *paletteData32++;
|
||||
u32 g = *paletteData32++;
|
||||
u32 r = *paletteData32++;
|
||||
paletteData32++;
|
||||
_palette[i] = ColorConverter::ToXBGR555(Rgb<5, 5, 5>(Rgb<8, 8, 8>(r, g, b)));
|
||||
}
|
||||
|
||||
if (file->Seek(dataOffset) != FR_OK ||
|
||||
!file->ReadExact(_coverBuffer, sizeof(_coverBuffer)))
|
||||
return;
|
||||
|
||||
file->Close();
|
||||
|
||||
DC_FlushRange(_coverBuffer, sizeof(_coverBuffer));
|
||||
DC_FlushRange(_palette, sizeof(_palette));
|
||||
}
|
||||
|
||||
void BmpFileCover::Upload2DCoverBitmap(void* destination) const
|
||||
{
|
||||
cover_bitmapToTiledCopy(_coverBuffer, destination);
|
||||
}
|
||||
|
||||
void BmpFileCover::Upload2DCoverPalette(void* destination) const
|
||||
{
|
||||
dma_ntrCopy32(3, _palette, destination, sizeof(_palette));
|
||||
}
|
||||
27
arm9/source/romBrowser/FileType/BmpFileCover.h
Normal file
27
arm9/source/romBrowser/FileType/BmpFileCover.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "FileCover.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
|
||||
/// @brief Class representing a BMP file cover.
|
||||
class alignas(32) BmpFileCover : public FileCover
|
||||
{
|
||||
public:
|
||||
explicit BmpFileCover(const FastFileRef& coverFileRef);
|
||||
|
||||
VBlankTextureLoadRequest CreateTextureLoadRequest() const override
|
||||
{
|
||||
return VBlankTextureLoadRequest(
|
||||
_coverBuffer, 128 * 96, _texVramOffset,
|
||||
_palette, sizeof(_palette), _plttVramOffset,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Upload2DCoverBitmap(void* destination) const override;
|
||||
void Upload2DCoverPalette(void* destination) const override;
|
||||
|
||||
bool IsActualCover() const override { return true; }
|
||||
|
||||
private:
|
||||
u8 _coverBuffer[128 * 96] alignas(32);
|
||||
u16 _palette[256] alignas(32);
|
||||
};
|
||||
61
arm9/source/romBrowser/FileType/CustomFileType.h
Normal file
61
arm9/source/romBrowser/FileType/CustomFileType.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include "FileType.h"
|
||||
#include "services/settings/FileAssociation.h"
|
||||
#include "../Theme/IThemeFileIconFactory.h"
|
||||
|
||||
/// @brief Class representing a custom (user provided) file type.
|
||||
class CustomFileType : public FileType
|
||||
{
|
||||
public:
|
||||
CustomFileType()
|
||||
: FileType(nullptr, FileTypeClassification::Unknown) { }
|
||||
|
||||
explicit CustomFileType(const FileAssociation* fileAssociation)
|
||||
: CustomFileType(fileAssociation, nullptr) { }
|
||||
|
||||
CustomFileType(const FileAssociation* fileAssociation, const FileType* baseFileType)
|
||||
: FileType(
|
||||
baseFileType != nullptr ? baseFileType->GetShortName() : fileAssociation->extension.GetString(),
|
||||
baseFileType != nullptr ? baseFileType->GetClassification() : FileTypeClassification::Misc)
|
||||
, _fileAssociation(fileAssociation), _baseFileType(baseFileType) { }
|
||||
|
||||
std::unique_ptr<FileIcon> CreateFileIcon(const TCHAR* fileName,
|
||||
const IThemeFileIconFactory* themeFileIconFactory) const override
|
||||
{
|
||||
return _baseFileType != nullptr
|
||||
? _baseFileType->CreateFileIcon(fileName, themeFileIconFactory)
|
||||
: themeFileIconFactory->CreateGenericFileIcon(fileName);
|
||||
}
|
||||
|
||||
FileCover* CreateFileCover(const TCHAR* fileName) const override
|
||||
{
|
||||
return _baseFileType != nullptr
|
||||
? _baseFileType->CreateFileCover(fileName)
|
||||
: FileType::CreateFileCover(fileName);
|
||||
};
|
||||
|
||||
bool HasInternalFileInfo() const override
|
||||
{
|
||||
return _baseFileType != nullptr
|
||||
&& _baseFileType->HasInternalFileInfo();
|
||||
}
|
||||
|
||||
InternalFileInfo* CreateInternalFileInfo(const FastFileRef& fastFileRef) const override
|
||||
{
|
||||
return _baseFileType != nullptr
|
||||
? _baseFileType->CreateInternalFileInfo(fastFileRef)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool TrySetLaunchParameters(pload_params_t* launchParameters, const char* filePath) const override
|
||||
{
|
||||
StringUtil::Copy(launchParameters->romPath, _fileAssociation->applicationPath, sizeof(launchParameters->romPath));
|
||||
u32 length = StringUtil::Copy(launchParameters->arguments, filePath, sizeof(launchParameters->arguments));
|
||||
launchParameters->argumentsLength = length + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const FileAssociation* _fileAssociation;
|
||||
const FileType* _baseFileType = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include "UnknownFileType.h"
|
||||
#include "Nds/NdsFileType.h"
|
||||
#include "Gba/GbaFileType.h"
|
||||
#include "ExtensionFileTypeProvider.h"
|
||||
|
||||
static bool isNdsExtension(const char* extension)
|
||||
{
|
||||
return !strcasecmp(extension, "nds")
|
||||
|| !strcasecmp(extension, "srl")
|
||||
|| !strcasecmp(extension, "dsi");
|
||||
}
|
||||
|
||||
static bool isGbaExtension(const char* extension)
|
||||
{
|
||||
return !strcasecmp(extension, "gba")
|
||||
|| !strcasecmp(extension, "agb");
|
||||
}
|
||||
|
||||
ExtensionFileTypeProvider::ExtensionFileTypeProvider(const AppSettings& appSettings)
|
||||
: _appSettings(appSettings)
|
||||
{
|
||||
_customFileTypes = std::make_unique_for_overwrite<CustomFileType[]>(appSettings.numberOfFileAssociations);
|
||||
for (u32 i = 0; i < appSettings.numberOfFileAssociations; i++)
|
||||
{
|
||||
const FileType* baseFileType = nullptr;
|
||||
if (isGbaExtension(appSettings.fileAssociations[i].extension))
|
||||
{
|
||||
baseFileType = &GbaFileType::sInstance;
|
||||
}
|
||||
_customFileTypes[i] = CustomFileType(&appSettings.fileAssociations[i], baseFileType);
|
||||
}
|
||||
}
|
||||
|
||||
const FileType* ExtensionFileTypeProvider::GetFileType(const TCHAR* path) const
|
||||
{
|
||||
const char* extension = strrchr(path, '.');
|
||||
if (extension)
|
||||
{
|
||||
extension++; // skip over dot
|
||||
|
||||
if (isNdsExtension(extension))
|
||||
{
|
||||
return &NdsFileType::sInstance;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < _appSettings.numberOfFileAssociations; i++)
|
||||
{
|
||||
if (!strcasecmp(extension, _customFileTypes[i].GetShortName()))
|
||||
{
|
||||
return &_customFileTypes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &UnknownFileType::sInstance;
|
||||
}
|
||||
18
arm9/source/romBrowser/FileType/ExtensionFileTypeProvider.h
Normal file
18
arm9/source/romBrowser/FileType/ExtensionFileTypeProvider.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "IFileTypeProvider.h"
|
||||
#include "services/settings/AppSettings.h"
|
||||
#include "CustomFileType.h"
|
||||
|
||||
/// @brief Implementation of \see IFileTypeProvider that uses extensions to identify file types.
|
||||
class ExtensionFileTypeProvider : public IFileTypeProvider
|
||||
{
|
||||
public:
|
||||
explicit ExtensionFileTypeProvider(const AppSettings& appSettings);
|
||||
|
||||
const FileType* GetFileType(const TCHAR* path) const override;
|
||||
|
||||
private:
|
||||
const AppSettings& _appSettings;
|
||||
std::unique_ptr<CustomFileType[]> _customFileTypes;
|
||||
};
|
||||
46
arm9/source/romBrowser/FileType/FileCover.h
Normal file
46
arm9/source/romBrowser/FileType/FileCover.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include "gui/VBlankTextureLoadRequest.h"
|
||||
|
||||
extern "C" void cover_bitmapToTiledCopy(const void* bitmap, void* vram);
|
||||
|
||||
#define COVER_WIDTH 106
|
||||
#define COVER_HEIGHT 96
|
||||
|
||||
/// @brief Abstract base class for a file cover.
|
||||
class FileCover
|
||||
{
|
||||
public:
|
||||
virtual ~FileCover() = 0;
|
||||
|
||||
/// @brief Sets the texture and texture palette offsets of this cover after it has been loaded to vram.
|
||||
/// @param texVramOffset The texture vram offset.
|
||||
/// @param plttVramOffset The texture palette vram offset.
|
||||
void SetTexVramOffset(u32 texVramOffset, u32 plttVramOffset)
|
||||
{
|
||||
_texVramOffset = texVramOffset;
|
||||
_plttVramOffset = plttVramOffset;
|
||||
}
|
||||
|
||||
/// @brief Creates a texture load request to load this cover.
|
||||
/// @return The constructed texture load request.
|
||||
virtual VBlankTextureLoadRequest CreateTextureLoadRequest() const = 0;
|
||||
|
||||
/// @brief Uploads the 8bpp bitmap graphics of this cover to BG vram.
|
||||
/// @param destination The address to load to.
|
||||
virtual void Upload2DCoverBitmap(void* destination) const = 0;
|
||||
|
||||
/// @brief Uploads the 256 color palette of this cover to palette ram.
|
||||
/// @param destination The address to load to.
|
||||
virtual void Upload2DCoverPalette(void* destination) const = 0;
|
||||
|
||||
/// @brief Returns whether this cover is an actual cover graphic of the file.
|
||||
/// @return True when this cover is an actual cover graphic of the file,
|
||||
/// or false when the graphic is a (generic) placeholder.
|
||||
virtual bool IsActualCover() const = 0;
|
||||
|
||||
protected:
|
||||
u32 _texVramOffset = 0;
|
||||
u32 _plttVramOffset = 0;
|
||||
};
|
||||
|
||||
inline FileCover::~FileCover() { }
|
||||
32
arm9/source/romBrowser/FileType/FileCoverBitmapToTiledCopy.s
Normal file
32
arm9/source/romBrowser/FileType/FileCoverBitmapToTiledCopy.s
Normal file
@@ -0,0 +1,32 @@
|
||||
.section ".itcm", "ax"
|
||||
.arm
|
||||
|
||||
// r0 = bitmap
|
||||
// r1 = vram
|
||||
.global cover_bitmapToTiledCopy
|
||||
.type cover_bitmapToTiledCopy, %function
|
||||
cover_bitmapToTiledCopy:
|
||||
push {r4-r9}
|
||||
mov r12, #12
|
||||
1:
|
||||
sub r12, r12, #(14 << 16)
|
||||
2:
|
||||
ldrd r2, [r0], #128
|
||||
ldrd r4, [r0], #128
|
||||
ldrd r6, [r0], #128
|
||||
ldrd r8, [r0], #128
|
||||
stmia r1!, {r2-r9}
|
||||
ldrd r2, [r0], #128
|
||||
ldrd r4, [r0], #128
|
||||
ldrd r6, [r0], #128
|
||||
ldrd r8, [r0]
|
||||
stmia r1!, {r2-r9}
|
||||
sub r0, r0, #(7 * 128 - 8)
|
||||
adds r12, r12, #(1 << 16)
|
||||
bmi 2b
|
||||
add r0, r0, #(128 * 8 - (14 * 8))
|
||||
subs r12, r12, #1
|
||||
bne 1b
|
||||
|
||||
pop {r4-r9}
|
||||
bx lr
|
||||
58
arm9/source/romBrowser/FileType/FileIcon.h
Normal file
58
arm9/source/romBrowser/FileType/FileIcon.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include "core/math/Point.h"
|
||||
#include "core/math/Rgb.h"
|
||||
|
||||
class PaletteManager;
|
||||
class GraphicsContext;
|
||||
|
||||
#define FILE_ICON_VRAM_SIZE 4096
|
||||
|
||||
/// @brief Abstract base class representing a file icon.
|
||||
class FileIcon
|
||||
{
|
||||
public:
|
||||
virtual ~FileIcon() = 0;
|
||||
|
||||
/// @brief Uploads the graphics of this icon to the specified \p vram address.
|
||||
/// @param vram The vram address to load the graphics to.
|
||||
virtual void UploadGraphics(vu16* vram) const = 0;
|
||||
|
||||
/// @brief Updates this icon.
|
||||
virtual void Update() { }
|
||||
|
||||
/// @brief Draws this file icon.
|
||||
/// @param graphicsContext The graphics context to use.
|
||||
/// @param backgroundColor The color on which the icon is drawn.
|
||||
virtual void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) = 0;
|
||||
|
||||
/// @brief Sets the OBJ vram offset of this icon.
|
||||
/// @param offset The OBJ vram offset.
|
||||
void SetObjVramOffset(u32 offset) { _vramOffset = offset; }
|
||||
|
||||
/// @brief Sets the icon animation frame.
|
||||
/// @param frame The animation frame.
|
||||
void SetAnimFrame(u32 frame)
|
||||
{
|
||||
_frame = frame;
|
||||
}
|
||||
|
||||
/// @brief Sets the position where this icon will be drawn.
|
||||
/// @param position The position where this icon will be drawn.
|
||||
void SetPosition(const Point& position) { _position = position; }
|
||||
|
||||
/// @brief Sets the position where this icon will be drawn.
|
||||
/// @param x The X position where this icon will be drawn.
|
||||
/// @param y The Y position where this icon will be drawn.
|
||||
void SetPosition(int x, int y)
|
||||
{
|
||||
_position.x = x;
|
||||
_position.y = y;
|
||||
}
|
||||
|
||||
protected:
|
||||
u32 _vramOffset = 0;
|
||||
u32 _frame = 0;
|
||||
Point _position;
|
||||
};
|
||||
|
||||
inline FileIcon::~FileIcon() { }
|
||||
75
arm9/source/romBrowser/FileType/FileType.h
Normal file
75
arm9/source/romBrowser/FileType/FileType.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "fat/ff.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
#include "FileTypeClassification.h"
|
||||
#include "FileIcon.h"
|
||||
#include "FileCover.h"
|
||||
#include "UnknownFileCover.h"
|
||||
#include "picoLoaderBootstrap.h"
|
||||
|
||||
class FileInfo;
|
||||
class InternalFileInfo;
|
||||
class IThemeFileIconFactory;
|
||||
class ICoverRepository;
|
||||
|
||||
/// @brief Abstract base class representing a file type.
|
||||
class FileType
|
||||
{
|
||||
public:
|
||||
virtual ~FileType() = 0;
|
||||
|
||||
/// @brief Returns the short name for this file type.
|
||||
/// @return The short name for this file type.
|
||||
constexpr const char* GetShortName() const { return _shortName; }
|
||||
|
||||
/// @brief Returns the classification for this file type.
|
||||
/// @return The classification for this file type.
|
||||
constexpr FileTypeClassification GetClassification() const { return _classification; }
|
||||
|
||||
/// @brief Creates a generic file icon for a file of this file type.
|
||||
/// @param fileName The name of the file.
|
||||
/// @param themeFileIconFactory The theme file icon factory to use.
|
||||
/// @return The constructed file icon, or \c nullptr when no file icon for this file type is available.
|
||||
virtual std::unique_ptr<FileIcon> CreateFileIcon(const TCHAR* fileName,
|
||||
const IThemeFileIconFactory* themeFileIconFactory) const
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
/// @brief Creates a generic file cover for a file of this file type.
|
||||
/// @param fileName The name of the file.
|
||||
/// @return The constructed file cover.
|
||||
virtual FileCover* CreateFileCover(const TCHAR* fileName) const
|
||||
{
|
||||
return new UnknownFileCover();
|
||||
};
|
||||
|
||||
/// @brief Returns if this file format has internal file info or not.
|
||||
/// @return \c true if this file format has internal file info, or \c false otherwise.
|
||||
virtual bool HasInternalFileInfo() const { return false; }
|
||||
|
||||
/// @brief Reads the internal file info of the file specified by \p fastFileRef.
|
||||
/// @param fastFileRef The file to get the internal file info of.
|
||||
/// @return The internal file info of the specified file when successful, or \c nullptr otherwise.
|
||||
virtual InternalFileInfo* CreateInternalFileInfo(const FastFileRef& fastFileRef) const { return nullptr; }
|
||||
|
||||
/// @brief Tries to set the launch parameters to launch a file of this file type at the specified \p filePath.
|
||||
/// @param launchParameters The launch parameters to set.
|
||||
/// @param filePath The file that is going to be launched.
|
||||
/// @return \c true when the launch parameters were set successfully, or \c false otherwise.
|
||||
virtual bool TrySetLaunchParameters(pload_params_t* launchParameters, const char* filePath) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr FileType(const char* shortName, FileTypeClassification classification)
|
||||
: _shortName(shortName), _classification(classification) { }
|
||||
|
||||
private:
|
||||
const char* _shortName;
|
||||
FileTypeClassification _classification;
|
||||
};
|
||||
|
||||
inline FileType::~FileType() { }
|
||||
12
arm9/source/romBrowser/FileType/FileTypeClassification.h
Normal file
12
arm9/source/romBrowser/FileType/FileTypeClassification.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
enum class FileTypeClassification
|
||||
{
|
||||
Unknown,
|
||||
Folder,
|
||||
Misc,
|
||||
Game,
|
||||
Music,
|
||||
Picture,
|
||||
Video
|
||||
};
|
||||
11
arm9/source/romBrowser/FileType/Folder/FolderFileCover.h
Normal file
11
arm9/source/romBrowser/FileType/Folder/FolderFileCover.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "../StaticFileCover.h"
|
||||
#include "folderCover.h"
|
||||
|
||||
/// @brief Generic cover for a folder.
|
||||
class FolderFileCover : public StaticFileCover
|
||||
{
|
||||
public:
|
||||
FolderFileCover()
|
||||
: StaticFileCover(folderCoverBitmap, folderCoverPal) { }
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "FolderFileType.h"
|
||||
|
||||
const FolderFileType FolderFileType::sInstance;
|
||||
27
arm9/source/romBrowser/FileType/Folder/FolderFileType.h
Normal file
27
arm9/source/romBrowser/FileType/Folder/FolderFileType.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "../FileType.h"
|
||||
#include "../../Theme/IThemeFileIconFactory.h"
|
||||
#include "FolderFileCover.h"
|
||||
|
||||
/// @brief File type that represents a folder.
|
||||
class FolderFileType : public FileType
|
||||
{
|
||||
public:
|
||||
static const FolderFileType sInstance;
|
||||
|
||||
std::unique_ptr<FileIcon> CreateFileIcon(const TCHAR* fileName,
|
||||
const IThemeFileIconFactory* themeFileIconFactory) const override
|
||||
{
|
||||
return themeFileIconFactory->CreateFolderIcon(fileName);
|
||||
}
|
||||
|
||||
FileCover* CreateFileCover(const TCHAR* fileName) const override
|
||||
{
|
||||
return new FolderFileCover();
|
||||
};
|
||||
|
||||
private:
|
||||
constexpr FolderFileType()
|
||||
: FileType("folder", FileTypeClassification::Folder) { }
|
||||
};
|
||||
4
arm9/source/romBrowser/FileType/Gba/GbaFileType.cpp
Normal file
4
arm9/source/romBrowser/FileType/Gba/GbaFileType.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "GbaFileType.h"
|
||||
|
||||
const GbaFileType GbaFileType::sInstance;
|
||||
29
arm9/source/romBrowser/FileType/Gba/GbaFileType.h
Normal file
29
arm9/source/romBrowser/FileType/Gba/GbaFileType.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "../FileType.h"
|
||||
#include "GbaInternalFileInfo.h"
|
||||
#include "core/StringUtil.h"
|
||||
#include "../../Theme/IThemeFileIconFactory.h"
|
||||
|
||||
/// @brief File type for gba roms.
|
||||
class GbaFileType : public FileType
|
||||
{
|
||||
public:
|
||||
static const GbaFileType sInstance;
|
||||
|
||||
std::unique_ptr<FileIcon> CreateFileIcon(const TCHAR* fileName,
|
||||
const IThemeFileIconFactory* themeFileIconFactory) const override
|
||||
{
|
||||
return themeFileIconFactory->CreateGenericFileIcon(fileName);
|
||||
}
|
||||
|
||||
bool HasInternalFileInfo() const override { return true; }
|
||||
|
||||
InternalFileInfo* CreateInternalFileInfo(const FastFileRef& fastFileRef) const override
|
||||
{
|
||||
return new GbaInternalFileInfo(fastFileRef);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr GbaFileType()
|
||||
: FileType("gba", FileTypeClassification::Game) { }
|
||||
};
|
||||
20
arm9/source/romBrowser/FileType/Gba/GbaInternalFileInfo.cpp
Normal file
20
arm9/source/romBrowser/FileType/Gba/GbaInternalFileInfo.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <nds/arm9/cache.h>
|
||||
#include "fat/File.h"
|
||||
#include "GbaInternalFileInfo.h"
|
||||
|
||||
GbaInternalFileInfo::GbaInternalFileInfo(const FastFileRef& fastFileRef)
|
||||
{
|
||||
memset(_gameCode, 0, sizeof(_gameCode));
|
||||
|
||||
const auto file = std::make_unique<File>();
|
||||
file->Open(fastFileRef, FA_READ);
|
||||
|
||||
if (file->Seek(0xAC) != FR_OK)
|
||||
return;
|
||||
|
||||
u32 bytesRead;
|
||||
if (file->Read(_gameCode, 4, bytesRead) != FR_OK)
|
||||
return;
|
||||
}
|
||||
15
arm9/source/romBrowser/FileType/Gba/GbaInternalFileInfo.h
Normal file
15
arm9/source/romBrowser/FileType/Gba/GbaInternalFileInfo.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "../InternalFileInfo.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
|
||||
/// @brief Internal file info for gba roms.
|
||||
class alignas(32) GbaInternalFileInfo : public InternalFileInfo
|
||||
{
|
||||
public:
|
||||
explicit GbaInternalFileInfo(const FastFileRef& fastFileRef);
|
||||
|
||||
constexpr const char* GetGameCode() const override { return _gameCode; }
|
||||
|
||||
private:
|
||||
char _gameCode[5];
|
||||
};
|
||||
13
arm9/source/romBrowser/FileType/IFileTypeProvider.h
Normal file
13
arm9/source/romBrowser/FileType/IFileTypeProvider.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
class FileType;
|
||||
|
||||
/// @brief Interface for getting a file type based on a file path.
|
||||
class IFileTypeProvider
|
||||
{
|
||||
public:
|
||||
virtual ~IFileTypeProvider() = 0;
|
||||
|
||||
virtual const FileType* GetFileType(const TCHAR* path) const = 0;
|
||||
};
|
||||
|
||||
inline IFileTypeProvider::~IFileTypeProvider() { }
|
||||
29
arm9/source/romBrowser/FileType/InternalFileInfo.h
Normal file
29
arm9/source/romBrowser/FileType/InternalFileInfo.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "FileIcon.h"
|
||||
#include "FileCover.h"
|
||||
|
||||
/// @brief Abstract base class representing internal file information.
|
||||
class InternalFileInfo
|
||||
{
|
||||
public:
|
||||
virtual ~InternalFileInfo() = 0;
|
||||
|
||||
/// @brief Returns the game code of the file.
|
||||
/// @return A pointer to the game code if available, or \c nullptr otherwise.
|
||||
virtual const char* GetGameCode() const { return nullptr; }
|
||||
|
||||
/// @brief Returns the game title of the file.
|
||||
/// @return A pointer to the game title if available, or \c nullptr otherwise.
|
||||
virtual const char16_t* GetGameTitle() const { return nullptr; }
|
||||
|
||||
/// @brief Creates an icon based on the internal file information.
|
||||
/// @return A unique pointer to the created icon when successful, or \c nullptr otherwise.
|
||||
virtual std::unique_ptr<FileIcon> CreateGameIcon() const { return nullptr; }
|
||||
|
||||
/// @brief Creates a cover based on the internal file information.
|
||||
/// @return A unique pointer to the created cover when successful, or \c nullptr otherwise.
|
||||
virtual FileCover* CreateGameCover() const { return nullptr; }
|
||||
};
|
||||
|
||||
inline InternalFileInfo::~InternalFileInfo() { }
|
||||
142
arm9/source/romBrowser/FileType/Nds/NdsFileIcon.cpp
Normal file
142
arm9/source/romBrowser/FileType/Nds/NdsFileIcon.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/math/mathDiv.h>
|
||||
#include <libtwl/dma/dmaNitro.h>
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/OamManager.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "gui/palette/DirectPalette.h"
|
||||
#include "NdsFileIcon.h"
|
||||
|
||||
NdsFileIcon::NdsFileIcon(const nds_banner_t* banner)
|
||||
: _banner(banner), _animTokenIdx(0), _lastAnimToken(0)
|
||||
, _animLength(0), _loop(false)
|
||||
{
|
||||
_animated = _banner->header.version >= NDS_BANNER_VERSION_103
|
||||
&& _banner->animation.animTokens[0].duration != 0;
|
||||
if (_animated)
|
||||
{
|
||||
_lastAnimToken = NDS_BANNER_ANIM_TOKEN_COUNT - 1;
|
||||
int length = 0;
|
||||
_loop = true;
|
||||
for (int i = 0; i < NDS_BANNER_ANIM_TOKEN_COUNT; i++)
|
||||
{
|
||||
_tokenStartTimes[i] = length;
|
||||
const auto& token = _banner->animation.animTokens[i];
|
||||
if (token.duration == NDS_BANNER_ANIM_DURATION_CONTROL_FRAME)
|
||||
{
|
||||
_loop = token.control != NDS_BANNER_ANIM_CONTROL_STOP;
|
||||
_lastAnimToken = i - 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
length += token.duration;
|
||||
}
|
||||
_animLength = length;
|
||||
_tokenStartTimes[NDS_BANNER_ANIM_TOKEN_COUNT] = _animLength;
|
||||
}
|
||||
}
|
||||
|
||||
void NdsFileIcon::UploadGraphics(vu16* vram) const
|
||||
{
|
||||
if (_animated)
|
||||
dma_ntrCopy32(3, _banner->animation.iconGfx, vram, sizeof(_banner->animation.iconGfx));
|
||||
else
|
||||
dma_ntrCopy32(3, _banner->iconGfx, vram, sizeof(_banner->iconGfx));
|
||||
}
|
||||
|
||||
void NdsFileIcon::Update()
|
||||
{
|
||||
if (!_animated)
|
||||
return;
|
||||
|
||||
_frame %= _animLength;
|
||||
|
||||
if ((!_loop && _frame >= _animLength) || _lastAnimToken == 0)
|
||||
{
|
||||
_animTokenIdx = _lastAnimToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 start = 0;
|
||||
u32 end = _lastAnimToken;
|
||||
|
||||
while (start <= end)
|
||||
{
|
||||
const u32 mid = (start + end) >> 1;
|
||||
u32 midTime = _tokenStartTimes[mid];
|
||||
if (midTime <= _frame && _frame < _tokenStartTimes[mid + 1])
|
||||
{
|
||||
start = mid;
|
||||
break;
|
||||
}
|
||||
else if (_frame < midTime)
|
||||
end = mid - 1;
|
||||
else
|
||||
start = mid + 1;
|
||||
}
|
||||
|
||||
_animTokenIdx = start;
|
||||
}
|
||||
|
||||
if (++_frame == _animLength)
|
||||
_frame = 0;
|
||||
|
||||
|
||||
// if (++_durationCounter < _banner->animation.animTokens[_animTokenIdx].duration)
|
||||
// return;
|
||||
|
||||
// _durationCounter = 0;
|
||||
|
||||
// if (++_animTokenIdx >= NDS_BANNER_ANIM_TOKEN_COUNT)
|
||||
// {
|
||||
// _animTokenIdx = 0;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (_banner->animation.animTokens[_animTokenIdx].duration == NDS_BANNER_ANIM_DURATION_CONTROL_FRAME)
|
||||
// {
|
||||
// switch (_banner->animation.animTokens[_animTokenIdx].control)
|
||||
// {
|
||||
// case NDS_BANNER_ANIM_CONTROL_LOOP:
|
||||
// _animTokenIdx = 0;
|
||||
// break;
|
||||
|
||||
// case NDS_BANNER_ANIM_CONTROL_STOP:
|
||||
// _animTokenIdx--;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void NdsFileIcon::Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor)
|
||||
{
|
||||
if (!graphicsContext.IsVisible(Rectangle(_position, 32, 32)))
|
||||
return;
|
||||
|
||||
const u16* palette = _animated
|
||||
? _banner->animation.iconPltt[_banner->animation.animTokens[_animTokenIdx].plttIdx]
|
||||
: _banner->iconPltt;
|
||||
|
||||
u32 paletteRowIdx = graphicsContext.GetPaletteManager().AllocRow(
|
||||
DirectPalette(palette), _position.y, _position.y + 32);
|
||||
|
||||
u32 vramOffset = _vramOffset;
|
||||
if (_animated)
|
||||
vramOffset += _banner->animation.animTokens[_animTokenIdx].gfxIdx * 512;
|
||||
|
||||
auto builder = OamBuilder::OamWithSize<32, 32>(
|
||||
_position, vramOffset >> 7)
|
||||
.WithPalette16(paletteRowIdx)
|
||||
.WithPriority(graphicsContext.GetPriority());
|
||||
|
||||
if (_animated)
|
||||
{
|
||||
builder
|
||||
.WithHFlip(_banner->animation.animTokens[_animTokenIdx].hFlip)
|
||||
.WithVFlip(_banner->animation.animTokens[_animTokenIdx].vFlip);
|
||||
}
|
||||
|
||||
gfx_oam_entry_t* oam = graphicsContext.GetOamManager().AllocOams(1);
|
||||
builder.Build(oam[0]);
|
||||
}
|
||||
24
arm9/source/romBrowser/FileType/Nds/NdsFileIcon.h
Normal file
24
arm9/source/romBrowser/FileType/Nds/NdsFileIcon.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "../FileIcon.h"
|
||||
#include "ndsBanner.h"
|
||||
|
||||
/// @brief Icon of a nds rom.
|
||||
class NdsFileIcon : public FileIcon
|
||||
{
|
||||
public:
|
||||
explicit NdsFileIcon(const nds_banner_t* banner);
|
||||
|
||||
void UploadGraphics(vu16* vram) const override;
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;
|
||||
|
||||
private:
|
||||
const nds_banner_t* _banner;
|
||||
bool _animated;
|
||||
int _animTokenIdx;
|
||||
// int _durationCounter;
|
||||
u32 _lastAnimToken;
|
||||
u32 _animLength;
|
||||
u16 _tokenStartTimes[65];
|
||||
bool _loop;
|
||||
};
|
||||
4
arm9/source/romBrowser/FileType/Nds/NdsFileType.cpp
Normal file
4
arm9/source/romBrowser/FileType/Nds/NdsFileType.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "NdsFileType.h"
|
||||
|
||||
const NdsFileType NdsFileType::sInstance;
|
||||
36
arm9/source/romBrowser/FileType/Nds/NdsFileType.h
Normal file
36
arm9/source/romBrowser/FileType/Nds/NdsFileType.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "../FileType.h"
|
||||
#include "NdsInternalFileInfo.h"
|
||||
#include "core/StringUtil.h"
|
||||
#include "../../Theme/IThemeFileIconFactory.h"
|
||||
|
||||
/// @brief File type for nds roms.
|
||||
class NdsFileType : public FileType
|
||||
{
|
||||
public:
|
||||
static const NdsFileType sInstance;
|
||||
|
||||
std::unique_ptr<FileIcon> CreateFileIcon(const TCHAR* fileName,
|
||||
const IThemeFileIconFactory* themeFileIconFactory) const override
|
||||
{
|
||||
return themeFileIconFactory->CreateNdsFileIcon(fileName);
|
||||
}
|
||||
|
||||
bool HasInternalFileInfo() const override { return true; }
|
||||
|
||||
InternalFileInfo* CreateInternalFileInfo(const FastFileRef& fastFileRef) const override
|
||||
{
|
||||
return new NdsInternalFileInfo(fastFileRef);
|
||||
}
|
||||
|
||||
bool TrySetLaunchParameters(pload_params_t* launchParameters, const char* filePath) const override
|
||||
{
|
||||
StringUtil::Copy(launchParameters->romPath, filePath, sizeof(launchParameters->romPath));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr NdsFileType()
|
||||
: FileType("nds", FileTypeClassification::Game) { }
|
||||
|
||||
};
|
||||
53
arm9/source/romBrowser/FileType/Nds/NdsInternalFileInfo.cpp
Normal file
53
arm9/source/romBrowser/FileType/Nds/NdsInternalFileInfo.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <nds/arm9/cache.h>
|
||||
#include "fat/File.h"
|
||||
#include "romBrowser/ICoverRepository.h"
|
||||
#include "NdsInternalFileInfo.h"
|
||||
|
||||
NdsInternalFileInfo::NdsInternalFileInfo(const FastFileRef& fastFileRef)
|
||||
{
|
||||
const auto file = std::make_unique<File>();
|
||||
_hasBanner = false;
|
||||
memset(_gameCode, 0, sizeof(_gameCode));
|
||||
|
||||
file->Open(fastFileRef, FA_READ);
|
||||
|
||||
if (file->Seek(0xC) != FR_OK)
|
||||
return;
|
||||
|
||||
u32 bytesRead;
|
||||
if (file->Read(_gameCode, 4, bytesRead) != FR_OK)
|
||||
return;
|
||||
|
||||
if (file->Seek(0x68) != FR_OK)
|
||||
return;
|
||||
|
||||
u32 bannerOffset;
|
||||
if (file->Read(&bannerOffset, 4, bytesRead) != FR_OK)
|
||||
return;
|
||||
|
||||
if (bannerOffset == 0)
|
||||
return;
|
||||
|
||||
if (file->Seek(bannerOffset) != FR_OK)
|
||||
return;
|
||||
|
||||
if (file->Read(&_banner, 0xA00, bytesRead) != FR_OK)
|
||||
return;
|
||||
|
||||
if (_banner.header.version >= NDS_BANNER_VERSION_103)
|
||||
{
|
||||
if (file->Read(((u8*)&_banner) + 0xA00, 0x19C0, bytesRead) != FR_OK)
|
||||
return;
|
||||
}
|
||||
_hasBanner = true;
|
||||
DC_FlushRange(&_banner, sizeof(_banner));
|
||||
}
|
||||
|
||||
const char16_t* NdsInternalFileInfo::GetGameTitle() const
|
||||
{
|
||||
if (!_hasBanner)
|
||||
return nullptr;
|
||||
return _banner.title[NDS_BANNER_TITLE_LANGUAGE_ENGLISH];
|
||||
}
|
||||
29
arm9/source/romBrowser/FileType/Nds/NdsInternalFileInfo.h
Normal file
29
arm9/source/romBrowser/FileType/Nds/NdsInternalFileInfo.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "../InternalFileInfo.h"
|
||||
#include "ndsBanner.h"
|
||||
#include "NdsFileIcon.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
|
||||
/// @brief Internal file info for nds roms.
|
||||
class alignas(32) NdsInternalFileInfo : public InternalFileInfo
|
||||
{
|
||||
public:
|
||||
explicit NdsInternalFileInfo(const FastFileRef& fastFileRef);
|
||||
|
||||
constexpr const char* GetGameCode() const override { return _gameCode; }
|
||||
const char16_t* GetGameTitle() const override;
|
||||
|
||||
std::unique_ptr<FileIcon> CreateGameIcon() const override
|
||||
{
|
||||
if (!_hasBanner)
|
||||
return nullptr;
|
||||
return std::make_unique<NdsFileIcon>(&_banner);
|
||||
}
|
||||
|
||||
const nds_banner_t& GetBanner() const { return _banner; }
|
||||
|
||||
private:
|
||||
nds_banner_t _banner alignas(32);
|
||||
bool _hasBanner;
|
||||
char _gameCode[5];
|
||||
};
|
||||
66
arm9/source/romBrowser/FileType/Nds/ndsBanner.h
Normal file
66
arm9/source/romBrowser/FileType/Nds/ndsBanner.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#define NDS_BANNER_VERSION_1 0x0001
|
||||
#define NDS_BANNER_VERSION_2 0x0002
|
||||
#define NDS_BANNER_VERSION_3 0x0003
|
||||
#define NDS_BANNER_VERSION_103 0x0103
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 version;
|
||||
u16 version1Crc;
|
||||
u16 version2Crc;
|
||||
u16 version3Crc;
|
||||
u16 version103AnimCrc;
|
||||
u8 reserved[0x16];
|
||||
} nds_banner_header_t;
|
||||
|
||||
#define NDS_BANNER_ANIM_DURATION_CONTROL_FRAME 0
|
||||
|
||||
#define NDS_BANNER_ANIM_CONTROL_LOOP 0
|
||||
#define NDS_BANNER_ANIM_CONTROL_STOP 1
|
||||
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_JAPANESE 0
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_ENGLISH 1
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_FRENCH 2
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_GERMAN 3
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_ITALIAN 4
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_SPANISH 5
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_CHINESE 6
|
||||
#define NDS_BANNER_TITLE_LANGUAGE_KOREAN 7
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 duration;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 gfxIdx : 3;
|
||||
u8 plttIdx : 3;
|
||||
u8 hFlip : 1;
|
||||
u8 vFlip : 1;
|
||||
};
|
||||
u8 control;
|
||||
};
|
||||
} nds_banner_anim_token_t;
|
||||
|
||||
#define NDS_BANNER_ANIM_TOKEN_COUNT 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 iconGfx[8][0x200];
|
||||
u16 iconPltt[8][16];
|
||||
nds_banner_anim_token_t animTokens[NDS_BANNER_ANIM_TOKEN_COUNT];
|
||||
} nds_banner_anim_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nds_banner_header_t header;
|
||||
u8 iconGfx[0x200];
|
||||
u16 iconPltt[16];
|
||||
char16_t title[16][128];
|
||||
nds_banner_anim_t animation;
|
||||
} nds_banner_t;
|
||||
|
||||
static_assert(sizeof(nds_banner_t) == 0x23C0, "Invalid size for nds_banner_t");
|
||||
13
arm9/source/romBrowser/FileType/NullFileTypeProvider.h
Normal file
13
arm9/source/romBrowser/FileType/NullFileTypeProvider.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "IFileTypeProvider.h"
|
||||
#include "UnknownFileType.h"
|
||||
|
||||
/// @brief Dummy implementation of \see IFileTypeProvider that always returns \see UnknownFileType.
|
||||
class NullFileTypeProvider : public IFileTypeProvider
|
||||
{
|
||||
public:
|
||||
const FileType* GetFileType(const TCHAR* path) const override
|
||||
{
|
||||
return &UnknownFileType::sInstance;
|
||||
}
|
||||
};
|
||||
34
arm9/source/romBrowser/FileType/StaticFileCover.h
Normal file
34
arm9/source/romBrowser/FileType/StaticFileCover.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "FileCover.h"
|
||||
#include <libtwl/dma/dmaNitro.h>
|
||||
|
||||
class StaticFileCover : public FileCover
|
||||
{
|
||||
public:
|
||||
StaticFileCover(const void* bitmapData, const void* paletteData)
|
||||
: _bitmapData(bitmapData), _paletteData(paletteData) { }
|
||||
|
||||
VBlankTextureLoadRequest CreateTextureLoadRequest() const override
|
||||
{
|
||||
return VBlankTextureLoadRequest(
|
||||
_bitmapData, 128 * 96, _texVramOffset,
|
||||
_paletteData, 512, _plttVramOffset,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Upload2DCoverBitmap(void* destination) const override
|
||||
{
|
||||
cover_bitmapToTiledCopy(_bitmapData, destination);
|
||||
}
|
||||
|
||||
void Upload2DCoverPalette(void* destination) const override
|
||||
{
|
||||
dma_ntrCopy32(3, _paletteData, destination, 512);
|
||||
}
|
||||
|
||||
bool IsActualCover() const override { return false; }
|
||||
|
||||
private:
|
||||
const void* _bitmapData;
|
||||
const void* _paletteData;
|
||||
};
|
||||
33
arm9/source/romBrowser/FileType/StaticIcon.cpp
Normal file
33
arm9/source/romBrowser/FileType/StaticIcon.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/dma/dmaNitro.h>
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/OamManager.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "gui/palette/DirectPalette.h"
|
||||
#include "StaticIcon.h"
|
||||
|
||||
void StaticIcon::UploadGraphics(vu16* vram) const
|
||||
{
|
||||
dma_ntrCopy32(3, _tileData, vram, 512);
|
||||
}
|
||||
|
||||
void StaticIcon::Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void StaticIcon::Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor)
|
||||
{
|
||||
if (!graphicsContext.IsVisible(Rectangle(_position, 32, 32)))
|
||||
return;
|
||||
|
||||
u32 paletteRowIdx = graphicsContext.GetPaletteManager().AllocRow(
|
||||
DirectPalette(_paletteData), _position.y, _position.y + 32);
|
||||
|
||||
gfx_oam_entry_t* oam = graphicsContext.GetOamManager().AllocOams(1);
|
||||
OamBuilder::OamWithSize<32, 32>(_position, _vramOffset >> 7)
|
||||
.WithPalette16(paletteRowIdx)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[0]);
|
||||
}
|
||||
18
arm9/source/romBrowser/FileType/StaticIcon.h
Normal file
18
arm9/source/romBrowser/FileType/StaticIcon.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "FileIcon.h"
|
||||
|
||||
class StaticIcon : public FileIcon
|
||||
{
|
||||
public:
|
||||
StaticIcon(const u8* tileData, const u16* paletteData)
|
||||
: _tileData(tileData), _paletteData(paletteData) { }
|
||||
|
||||
void UploadGraphics(vu16* vram) const override;
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;
|
||||
|
||||
private:
|
||||
const u8* _tileData;
|
||||
const u16* _paletteData;
|
||||
u32 _vramOffset;
|
||||
};
|
||||
11
arm9/source/romBrowser/FileType/UnknownFileCover.h
Normal file
11
arm9/source/romBrowser/FileType/UnknownFileCover.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "unknownCover.h"
|
||||
#include "StaticFileCover.h"
|
||||
|
||||
/// @brief Fallback question mark cover.
|
||||
class UnknownFileCover : public StaticFileCover
|
||||
{
|
||||
public:
|
||||
UnknownFileCover()
|
||||
: StaticFileCover(unknownCoverBitmap, unknownCoverPal) { }
|
||||
};
|
||||
4
arm9/source/romBrowser/FileType/UnknownFileType.cpp
Normal file
4
arm9/source/romBrowser/FileType/UnknownFileType.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "UnknownFileType.h"
|
||||
|
||||
const UnknownFileType UnknownFileType::sInstance;
|
||||
12
arm9/source/romBrowser/FileType/UnknownFileType.h
Normal file
12
arm9/source/romBrowser/FileType/UnknownFileType.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "FileType.h"
|
||||
|
||||
class UnknownFileType : public FileType
|
||||
{
|
||||
public:
|
||||
static const UnknownFileType sInstance;
|
||||
|
||||
private:
|
||||
constexpr UnknownFileType()
|
||||
: FileType("other", FileTypeClassification::Unknown) { }
|
||||
};
|
||||
17
arm9/source/romBrowser/ICoverRepository.h
Normal file
17
arm9/source/romBrowser/ICoverRepository.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "FileType/FileCover.h"
|
||||
|
||||
class FileInfo;
|
||||
class InternalFileInfo;
|
||||
|
||||
class ICoverRepository
|
||||
{
|
||||
public:
|
||||
virtual ~ICoverRepository() = 0;
|
||||
|
||||
virtual void Initialize() = 0;
|
||||
virtual FileCover* GetCoverForFile(
|
||||
const FileInfo& fileInfo, const InternalFileInfo* internalFileInfo) const = 0;
|
||||
};
|
||||
|
||||
inline ICoverRepository::~ICoverRepository() { }
|
||||
43
arm9/source/romBrowser/IRomBrowserController.h
Normal file
43
arm9/source/romBrowser/IRomBrowserController.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include "core/SharedPtr.h"
|
||||
#include "services/settings/AppSettings.h"
|
||||
|
||||
class SdFolder;
|
||||
class RomBrowserStateMachine;
|
||||
class RomBrowserViewModel;
|
||||
class FileInfo;
|
||||
class TaskQueueBase;
|
||||
class ICoverRepository;
|
||||
|
||||
class IRomBrowserController
|
||||
{
|
||||
public:
|
||||
virtual ~IRomBrowserController() = 0;
|
||||
|
||||
virtual void NavigateUp() = 0;
|
||||
virtual void NavigateToPath(const TCHAR* name) = 0;
|
||||
virtual void LaunchFile(const FileInfo& fileInfo) = 0;
|
||||
virtual void ShowGameInfo() = 0;
|
||||
virtual void HideGameInfo() = 0;
|
||||
virtual void ShowDisplaySettings() = 0;
|
||||
virtual void HideDisplaySettings() = 0;
|
||||
|
||||
virtual void Update() = 0;
|
||||
|
||||
virtual const SdFolder& GetSdFolder() const = 0;
|
||||
|
||||
virtual const RomBrowserStateMachine& GetStateMachine() const = 0;
|
||||
|
||||
virtual const SharedPtr<RomBrowserViewModel>& GetRomBrowserViewModel() = 0;
|
||||
|
||||
virtual TaskQueueBase* GetIoTaskQueue() const = 0;
|
||||
virtual TaskQueueBase* GetBgTaskQueue() const = 0;
|
||||
virtual const ICoverRepository& GetCoverRepository() const = 0;
|
||||
|
||||
virtual const RomBrowserDisplaySettings& GetRomBrowserDisplaySettings() const = 0;
|
||||
|
||||
virtual void SetRomBrowserDisplaySettings(
|
||||
const RomBrowserDisplaySettings& romBrowserDisplaySettings) = 0;
|
||||
};
|
||||
|
||||
inline IRomBrowserController::~IRomBrowserController() { }
|
||||
209
arm9/source/romBrowser/RomBrowserController.cpp
Normal file
209
arm9/source/romBrowser/RomBrowserController.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "common.h"
|
||||
#include <array>
|
||||
#include "picoLoaderBootstrap.h"
|
||||
#include "PicoLoaderProcess.h"
|
||||
#include "FileType/ExtensionFileTypeProvider.h"
|
||||
#include "FileType/FileType.h"
|
||||
#include "SdFolderFactory.h"
|
||||
#include "services/settings/IAppSettingsService.h"
|
||||
#include "RomBrowserController.h"
|
||||
|
||||
RomBrowserController::RomBrowserController(
|
||||
IAppSettingsService* appSettingsService, TaskQueueBase* ioTaskQueue,
|
||||
TaskQueueBase* bgTaskQueue)
|
||||
: _appSettingsService(appSettingsService)
|
||||
, _ioTaskQueue(ioTaskQueue), _bgTaskQueue(bgTaskQueue)
|
||||
, _fileTypeProvider(appSettingsService->GetAppSettings()) { }
|
||||
|
||||
void RomBrowserController::NavigateToPath(const TCHAR* name)
|
||||
{
|
||||
StringUtil::Copy(_navigatePath, name, sizeof(_navigatePath) / sizeof(_navigatePath[0]));
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::Navigate);
|
||||
}
|
||||
|
||||
void RomBrowserController::LaunchFile(const FileInfo& fileInfo)
|
||||
{
|
||||
_launchFileInfo = FileInfo(fileInfo);
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::Launch);
|
||||
}
|
||||
|
||||
void RomBrowserController::ShowGameInfo()
|
||||
{
|
||||
// Currently disabled, as the game info panel is not complete
|
||||
// _stateMachine.Fire(RomBrowserStateTrigger::ShowGameInfo);
|
||||
}
|
||||
|
||||
void RomBrowserController::HideGameInfo()
|
||||
{
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::HideGameInfo);
|
||||
}
|
||||
|
||||
void RomBrowserController::ShowDisplaySettings()
|
||||
{
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::ShowDisplaySettings);
|
||||
}
|
||||
|
||||
void RomBrowserController::HideDisplaySettings()
|
||||
{
|
||||
if (_saveSettingsPending)
|
||||
{
|
||||
_saveSettingsPending = false;
|
||||
_ioTaskQueue->Enqueue([this] (const vu8& cancelRequested)
|
||||
{
|
||||
_appSettingsService->Save();
|
||||
return TaskResult<void>::Completed();
|
||||
});
|
||||
}
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::HideDisplaySettings);
|
||||
}
|
||||
|
||||
void RomBrowserController::SetRomBrowserDisplaySettings(
|
||||
const RomBrowserDisplaySettings& romBrowserDisplaySettings)
|
||||
{
|
||||
_appSettingsService->GetAppSettings().romBrowserDisplaySettings = romBrowserDisplaySettings;
|
||||
_saveSettingsPending = true;
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::ChangeDisplayMode);
|
||||
}
|
||||
|
||||
void RomBrowserController::Update()
|
||||
{
|
||||
_stateMachine.Update();
|
||||
if (_stateMachine.HasStateChanged())
|
||||
{
|
||||
HandleTrigger();
|
||||
}
|
||||
switch (_stateMachine.GetCurrentState())
|
||||
{
|
||||
case RomBrowserState::Start:
|
||||
{
|
||||
LOG_DEBUG("RomBrowserState::Start\n");
|
||||
const auto& lastUsed = _appSettingsService->GetAppSettings().lastUsedFilePath;
|
||||
if (strlen(lastUsed.GetString()) != 0)
|
||||
{
|
||||
NavigateToPath(lastUsed.GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigateToPath("/");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RomBrowserState::LoadingFolder:
|
||||
{
|
||||
if (_navigateTask.GetTask().IsCompletedSuccessfully())
|
||||
{
|
||||
_navigateTask.Dispose();
|
||||
_stateMachine.Fire(RomBrowserStateTrigger::FolderLoadDone);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RomBrowserState::Launching:
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RomBrowserController::HandleTrigger()
|
||||
{
|
||||
switch (_stateMachine.GetLastTrigger())
|
||||
{
|
||||
case RomBrowserStateTrigger::Navigate:
|
||||
HandleNavigateTrigger();
|
||||
break;
|
||||
|
||||
case RomBrowserStateTrigger::FolderLoadDone:
|
||||
HandleFolderLoadDoneTrigger();
|
||||
break;
|
||||
|
||||
case RomBrowserStateTrigger::Launch:
|
||||
HandleLaunchTrigger();
|
||||
break;
|
||||
|
||||
case RomBrowserStateTrigger::ChangeDisplayMode:
|
||||
HandleChangeDisplayModeTrigger();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RomBrowserController::HandleNavigateTrigger()
|
||||
{
|
||||
LOG_DEBUG("RomBrowserStateTrigger::Navigate\n");
|
||||
_navigateTask = _ioTaskQueue->Enqueue([this] (const vu8& cancelRequested)
|
||||
{
|
||||
if (!_coverRepository)
|
||||
{
|
||||
_coverRepository = std::make_unique<CoverRepository>();
|
||||
_coverRepository->Initialize();
|
||||
}
|
||||
|
||||
u64 startTick = gTickCounter.GetValue();
|
||||
_navigateFileName = nullptr;
|
||||
if (strcmp(_navigatePath, "/") != 0) // can't f_stat on root dir
|
||||
{
|
||||
FILINFO fileInfo;
|
||||
if (f_stat(_navigatePath, &fileInfo) != FR_OK)
|
||||
{
|
||||
StringUtil::Copy(_navigatePath, "/", sizeof(_navigatePath) / sizeof(_navigatePath[0]));
|
||||
}
|
||||
else if (!(fileInfo.fattrib & AM_DIR))
|
||||
{
|
||||
_navigateFileName = strrchr(_navigatePath, '/') + 1;
|
||||
_navigateFileName[-1] = 0;
|
||||
}
|
||||
}
|
||||
f_chdir(_navigatePath);
|
||||
SdFolderFactory sdFolderFactory { &_fileTypeProvider };
|
||||
_newSdFolder = sdFolderFactory.CreateFromPath(".");
|
||||
u64 endTick = gTickCounter.GetValue();
|
||||
LOG_DEBUG("Loading files in folder took: %d us\n", (u32)TickCounter::TicksToMicroSeconds(endTick - startTick));
|
||||
return TaskResult<void>::Completed();
|
||||
});
|
||||
}
|
||||
|
||||
void RomBrowserController::HandleFolderLoadDoneTrigger()
|
||||
{
|
||||
LOG_DEBUG("RomBrowserStateTrigger::FolderLoadDone\n");
|
||||
_romBrowserViewModel.Reset();
|
||||
_sdFolder = std::move(_newSdFolder);
|
||||
_romBrowserViewModel = SharedPtr(new RomBrowserViewModel(this, _navigateFileName));
|
||||
}
|
||||
|
||||
void RomBrowserController::HandleLaunchTrigger()
|
||||
{
|
||||
LOG_DEBUG("RomBrowserStateTrigger::Launch\n");
|
||||
_ioTaskQueue->Enqueue([this] (const vu8& cancelRequested)
|
||||
{
|
||||
f_getcwd(_navigatePath, sizeof(_navigatePath) / sizeof(_navigatePath[0]));
|
||||
int idx = strlcat(_navigatePath, "/", sizeof(_navigatePath));
|
||||
if (_navigatePath[idx - 2] == '/')
|
||||
_navigatePath[idx - 1] = 0;
|
||||
strlcat(_navigatePath, _launchFileInfo.GetFileName(), sizeof(_navigatePath));
|
||||
_appSettingsService->GetAppSettings().lastUsedFilePath = _navigatePath;
|
||||
_appSettingsService->Save();
|
||||
|
||||
auto loadParams = pload_getLoadParams();
|
||||
loadParams->savePath[0] = 0;
|
||||
loadParams->arguments[0] = 0;
|
||||
loadParams->argumentsLength = 0;
|
||||
if (_launchFileInfo.GetFileType()->TrySetLaunchParameters(loadParams, _navigatePath))
|
||||
{
|
||||
gProcessManager.Goto<PicoLoaderProcess>();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_FATAL("Failed to set launch parameters.\n");
|
||||
}
|
||||
return TaskResult<void>::Completed();
|
||||
});
|
||||
}
|
||||
|
||||
void RomBrowserController::HandleChangeDisplayModeTrigger()
|
||||
{
|
||||
LOG_DEBUG("RomBrowserStateTrigger::ChangeDisplayMode\n");
|
||||
_romBrowserViewModel = SharedPtr(new RomBrowserViewModel(this));
|
||||
}
|
||||
72
arm9/source/romBrowser/RomBrowserController.h
Normal file
72
arm9/source/romBrowser/RomBrowserController.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/SharedPtr.h"
|
||||
#include "SdFolder.h"
|
||||
#include "viewModels/RomBrowserViewModel.h"
|
||||
#include "RomBrowserStateMachine.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "IRomBrowserController.h"
|
||||
#include "CoverRepository.h"
|
||||
#include "FileType/ExtensionFileTypeProvider.h"
|
||||
#include "services/settings/IAppSettingsService.h"
|
||||
|
||||
class RomBrowserController : public IRomBrowserController
|
||||
{
|
||||
public:
|
||||
RomBrowserController(IAppSettingsService* appSettingsService,
|
||||
TaskQueueBase* ioTaskQueue, TaskQueueBase* bgTaskQueue);
|
||||
|
||||
void NavigateUp() override
|
||||
{
|
||||
NavigateToPath("..");
|
||||
}
|
||||
|
||||
void NavigateToPath(const TCHAR* name) override;
|
||||
void LaunchFile(const FileInfo& fileInfo) override;
|
||||
void ShowGameInfo() override;
|
||||
void HideGameInfo() override;
|
||||
void ShowDisplaySettings() override;
|
||||
void HideDisplaySettings() override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
const SdFolder& GetSdFolder() const override { return *_sdFolder; }
|
||||
|
||||
const RomBrowserStateMachine& GetStateMachine() const override { return _stateMachine; }
|
||||
|
||||
const SharedPtr<RomBrowserViewModel>& GetRomBrowserViewModel() override { return _romBrowserViewModel; }
|
||||
|
||||
TaskQueueBase* GetIoTaskQueue() const override { return _ioTaskQueue; }
|
||||
TaskQueueBase* GetBgTaskQueue() const override { return _bgTaskQueue; }
|
||||
const ICoverRepository& GetCoverRepository() const override { return *_coverRepository; }
|
||||
|
||||
void SetRomBrowserDisplaySettings(const RomBrowserDisplaySettings& romBrowserDisplaySettings) override;
|
||||
|
||||
const RomBrowserDisplaySettings& GetRomBrowserDisplaySettings() const override
|
||||
{
|
||||
return _appSettingsService->GetAppSettings().romBrowserDisplaySettings;
|
||||
}
|
||||
|
||||
private:
|
||||
IAppSettingsService* _appSettingsService;
|
||||
TaskQueueBase* _ioTaskQueue;
|
||||
TaskQueueBase* _bgTaskQueue;
|
||||
|
||||
std::unique_ptr<SdFolder> _sdFolder;
|
||||
SharedPtr<RomBrowserViewModel> _romBrowserViewModel;
|
||||
std::unique_ptr<SdFolder> _newSdFolder;
|
||||
RomBrowserStateMachine _stateMachine;
|
||||
TCHAR _navigatePath[256];
|
||||
TCHAR* _navigateFileName;
|
||||
FileInfo _launchFileInfo;
|
||||
QueueTask<void> _navigateTask;
|
||||
bool _saveSettingsPending = false;
|
||||
std::unique_ptr<CoverRepository> _coverRepository;
|
||||
ExtensionFileTypeProvider _fileTypeProvider;
|
||||
|
||||
void HandleTrigger();
|
||||
void HandleNavigateTrigger();
|
||||
void HandleFolderLoadDoneTrigger();
|
||||
void HandleLaunchTrigger();
|
||||
void HandleChangeDisplayModeTrigger();
|
||||
};
|
||||
11
arm9/source/romBrowser/RomBrowserState.h
Normal file
11
arm9/source/romBrowser/RomBrowserState.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
enum class RomBrowserState
|
||||
{
|
||||
Start,
|
||||
Browser,
|
||||
GameInfo,
|
||||
LoadingFolder,
|
||||
Launching,
|
||||
DisplaySettings
|
||||
};
|
||||
58
arm9/source/romBrowser/RomBrowserStateMachine.cpp
Normal file
58
arm9/source/romBrowser/RomBrowserStateMachine.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "common.h"
|
||||
#include "StateMachineTriggerChecker.h"
|
||||
#include "RomBrowserStateMachine.h"
|
||||
|
||||
void RomBrowserStateMachine::Fire(RomBrowserStateTrigger trigger)
|
||||
{
|
||||
LOG_DEBUG("Fire %d\n", trigger);
|
||||
_newTrigger = trigger;
|
||||
}
|
||||
|
||||
bool RomBrowserStateMachine::FireDirect(RomBrowserStateTrigger trigger)
|
||||
{
|
||||
LOG_DEBUG("FireDirect %d\n", trigger);
|
||||
RomBrowserState newState;
|
||||
if (StateMachineTriggerChecker(_curState, trigger)
|
||||
.In(RomBrowserState::Start)
|
||||
.Trigger(RomBrowserStateTrigger::Navigate).GoesTo(RomBrowserState::LoadingFolder)
|
||||
.In(RomBrowserState::Browser)
|
||||
.Trigger(RomBrowserStateTrigger::ChangeDisplayMode).GoesTo(RomBrowserState::Browser)
|
||||
.Trigger(RomBrowserStateTrigger::Navigate).GoesTo(RomBrowserState::LoadingFolder)
|
||||
.Trigger(RomBrowserStateTrigger::ShowGameInfo).GoesTo(RomBrowserState::GameInfo)
|
||||
.Trigger(RomBrowserStateTrigger::Launch).GoesTo(RomBrowserState::Launching)
|
||||
.Trigger(RomBrowserStateTrigger::ShowDisplaySettings).GoesTo(RomBrowserState::DisplaySettings)
|
||||
.In(RomBrowserState::GameInfo)
|
||||
.Trigger(RomBrowserStateTrigger::HideGameInfo).GoesTo(RomBrowserState::Browser)
|
||||
.In(RomBrowserState::LoadingFolder)
|
||||
.Trigger(RomBrowserStateTrigger::FolderLoadDone).GoesTo(RomBrowserState::Browser)
|
||||
.In(RomBrowserState::DisplaySettings)
|
||||
.Trigger(RomBrowserStateTrigger::ChangeDisplayMode).GoesTo(RomBrowserState::DisplaySettings)
|
||||
.Trigger(RomBrowserStateTrigger::HideDisplaySettings).GoesTo(RomBrowserState::Browser)
|
||||
.Check(newState))
|
||||
{
|
||||
_prevState = _curState;
|
||||
_curState = newState;
|
||||
_lastTrigger = trigger;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RomBrowserStateMachine::Update()
|
||||
{
|
||||
_stateChanged = false;
|
||||
|
||||
if (_newTrigger == RomBrowserStateTrigger::None)
|
||||
return;
|
||||
|
||||
if (!FireDirect(_newTrigger))
|
||||
{
|
||||
LOG_ERROR("Trigger %d invalid in state %d\n", _newTrigger, _curState);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stateChanged = true;
|
||||
}
|
||||
|
||||
_newTrigger = RomBrowserStateTrigger::None;
|
||||
}
|
||||
26
arm9/source/romBrowser/RomBrowserStateMachine.h
Normal file
26
arm9/source/romBrowser/RomBrowserStateMachine.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "RomBrowserState.h"
|
||||
#include "RomBrowserStateTrigger.h"
|
||||
|
||||
class RomBrowserStateMachine
|
||||
{
|
||||
public:
|
||||
void Fire(RomBrowserStateTrigger trigger);
|
||||
|
||||
void Update();
|
||||
|
||||
constexpr RomBrowserState GetPreviousState() const { return _prevState; }
|
||||
constexpr RomBrowserStateTrigger GetLastTrigger() const { return _lastTrigger; }
|
||||
constexpr RomBrowserState GetCurrentState() const { return _curState; }
|
||||
|
||||
constexpr bool HasStateChanged() const { return _stateChanged; }
|
||||
|
||||
private:
|
||||
RomBrowserStateTrigger _lastTrigger = RomBrowserStateTrigger::None;
|
||||
RomBrowserState _prevState = RomBrowserState::Start;
|
||||
RomBrowserState _curState = RomBrowserState::Start;
|
||||
RomBrowserStateTrigger _newTrigger = RomBrowserStateTrigger::None;
|
||||
bool _stateChanged = false;
|
||||
|
||||
bool FireDirect(RomBrowserStateTrigger trigger);
|
||||
};
|
||||
14
arm9/source/romBrowser/RomBrowserStateTrigger.h
Normal file
14
arm9/source/romBrowser/RomBrowserStateTrigger.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
enum class RomBrowserStateTrigger
|
||||
{
|
||||
None,
|
||||
Navigate,
|
||||
ChangeDisplayMode,
|
||||
ShowGameInfo,
|
||||
HideGameInfo,
|
||||
FolderLoadDone,
|
||||
Launch,
|
||||
ShowDisplaySettings,
|
||||
HideDisplaySettings
|
||||
};
|
||||
111
arm9/source/romBrowser/SdFolder.cpp
Normal file
111
arm9/source/romBrowser/SdFolder.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include "SdFolder.h"
|
||||
|
||||
SdFolder::SdFolder(FileInfo** files, int fileCount)
|
||||
: _files(files), _fileCount(fileCount) { }
|
||||
|
||||
SdFolder::~SdFolder()
|
||||
{
|
||||
for (int i = 0; i < _fileCount; i++)
|
||||
delete _files[i];
|
||||
free(_files);
|
||||
}
|
||||
|
||||
std::unique_ptr<const FileInfo*[]> SdFolder::FilterAndSort(
|
||||
const SdFolderFilterSortParams& filterSortParams, int& resultCount) const
|
||||
{
|
||||
auto sortedFilteredFiles = std::make_unique<const FileInfo*[]>(_fileCount);
|
||||
int filteredCount = 0;
|
||||
for (int i = 0; i < _fileCount; i++)
|
||||
{
|
||||
const FileInfo* file = _files[i];
|
||||
auto classification = file->GetFileType()->GetClassification();
|
||||
if (classification != FileTypeClassification::Unknown)
|
||||
{
|
||||
sortedFilteredFiles[filteredCount++] = file;
|
||||
}
|
||||
}
|
||||
std::sort(sortedFilteredFiles.get(), sortedFilteredFiles.get() + filteredCount,
|
||||
[filterSortParams] (const FileInfo*& a, const FileInfo*& b)
|
||||
{
|
||||
bool result = true;
|
||||
if (CompareClassification(a, b, result))
|
||||
return result;
|
||||
|
||||
auto sortType = filterSortParams.sortType;
|
||||
auto sortDirection = filterSortParams.sortDirection;
|
||||
if (a->GetFileType()->GetClassification() == FileTypeClassification::Folder &&
|
||||
b->GetFileType()->GetClassification() == FileTypeClassification::Folder)
|
||||
{
|
||||
if (sortType != SdFolderSortType::Name)
|
||||
{
|
||||
sortType = SdFolderSortType::Name;
|
||||
sortDirection = SdFolderSortDirection::Ascending;
|
||||
}
|
||||
}
|
||||
switch (sortType)
|
||||
{
|
||||
case SdFolderSortType::Name:
|
||||
default:
|
||||
{
|
||||
result = CompareName(a, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sortDirection == SdFolderSortDirection::Ascending ? result : !result;
|
||||
});
|
||||
resultCount = filteredCount;
|
||||
return sortedFilteredFiles;
|
||||
}
|
||||
|
||||
bool SdFolder::CompareClassification(const FileInfo* a, const FileInfo* b, bool& result)
|
||||
{
|
||||
auto aClassification = a->GetFileType()->GetClassification();
|
||||
auto bClassification = b->GetFileType()->GetClassification();
|
||||
if (aClassification == bClassification)
|
||||
return false;
|
||||
|
||||
if (aClassification == FileTypeClassification::Folder)
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
else if (bClassification == FileTypeClassification::Folder)
|
||||
{
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SdFolder::CompareName(const FileInfo* a, const FileInfo* b)
|
||||
{
|
||||
return strcasecmp(a->GetFileName(), b->GetFileName()) < 0;
|
||||
}
|
||||
|
||||
void SdFolder::SortByNameInPlace()
|
||||
{
|
||||
std::sort(_files, _files + _fileCount, CompareName);
|
||||
}
|
||||
|
||||
const FileInfo* SdFolder::BinarySearch(const char* fileName) const
|
||||
{
|
||||
if (_fileCount != 0)
|
||||
{
|
||||
const auto file = std::lower_bound(_files, _files + _fileCount, fileName,
|
||||
[] (const FileInfo* entry, const char* value)
|
||||
{
|
||||
return strcasecmp(entry->GetFileName(), value) < 0;
|
||||
});
|
||||
|
||||
if (file != _files + _fileCount && !strcasecmp((*file)->GetFileName(), fileName))
|
||||
{
|
||||
return *file;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
41
arm9/source/romBrowser/SdFolder.h
Normal file
41
arm9/source/romBrowser/SdFolder.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "FileInfo.h"
|
||||
#include "SdFolderFilterSortParams.h"
|
||||
|
||||
/// @brief Class representing the contents of a folder on the sd card.
|
||||
class SdFolder
|
||||
{
|
||||
FileInfo** _files;
|
||||
int _fileCount;
|
||||
|
||||
static bool CompareClassification(const FileInfo* a, const FileInfo* b, bool& result);
|
||||
static bool CompareName(const FileInfo* a, const FileInfo* b);
|
||||
public:
|
||||
/// @brief Creates an SdFolder from the given files. The ownership of both the array
|
||||
/// and the FileInfo structs it points to will be taken over.
|
||||
/// @param files The array of files.
|
||||
/// @param fileCount The number of files in the array.
|
||||
SdFolder(FileInfo** files, int fileCount);
|
||||
|
||||
/// @brief Destructs the folder, together with the FileInfo structs.
|
||||
~SdFolder();
|
||||
|
||||
/// @brief Filters and sorts the files in this folder using the given filterSortParams.
|
||||
/// @param filterSortParams The filter and sort parameters.
|
||||
/// @param resultCount Will contain the number of results.
|
||||
/// @return A unique pointer to an array of FileInfo pointers containing the results.
|
||||
std::unique_ptr<const FileInfo*[]> FilterAndSort(
|
||||
const SdFolderFilterSortParams& filterSortParams, int& resultCount) const;
|
||||
|
||||
void SortByNameInPlace();
|
||||
const FileInfo* BinarySearch(const char* fileName) const;
|
||||
|
||||
/// @brief Gets a pointer to an array with all files in the folder.
|
||||
/// @return A pointer to an array with all files in the folder.
|
||||
const FileInfo* const* GetFiles() const { return _files; }
|
||||
|
||||
/// @brief Gets the total number of files in the folder.
|
||||
/// @return The total number of files.
|
||||
int GetFileCount() const { return _fileCount; }
|
||||
};
|
||||
39
arm9/source/romBrowser/SdFolderFactory.cpp
Normal file
39
arm9/source/romBrowser/SdFolderFactory.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "common.h"
|
||||
#include <vector>
|
||||
#include "fat/Directory.h"
|
||||
#include "FileInfo.h"
|
||||
#include "FileType/Folder/FolderFileType.h"
|
||||
#include "SdFolderFactory.h"
|
||||
|
||||
std::unique_ptr<SdFolder> SdFolderFactory::CreateFromPath(const char* path) const
|
||||
{
|
||||
Directory directory;
|
||||
if (directory.Open(path) != FR_OK)
|
||||
return nullptr;
|
||||
|
||||
int count = 0;
|
||||
int bufferSize = 8;
|
||||
auto fileInfos = (FileInfo**)malloc(sizeof(FileInfo*) * bufferSize);
|
||||
auto sdFileInfo = std::make_unique<FILINFO>();
|
||||
while (true)
|
||||
{
|
||||
if (directory.Read(sdFileInfo.get()) != FR_OK)
|
||||
return nullptr;
|
||||
|
||||
if (sdFileInfo->fname[0] == 0)
|
||||
break;
|
||||
|
||||
if (count >= bufferSize)
|
||||
{
|
||||
bufferSize *= 2;
|
||||
fileInfos = (FileInfo**)realloc(fileInfos, sizeof(FileInfo*) * bufferSize);
|
||||
}
|
||||
auto fileType = sdFileInfo->fattrib & AM_DIR
|
||||
? &FolderFileType::sInstance
|
||||
: _fileTypeProvider->GetFileType(sdFileInfo->fname);
|
||||
fileInfos[count++] = new FileInfo(sdFileInfo->fname, fileType,
|
||||
FastFileRef(directory.GetFatFsDirectory(), sdFileInfo.get()));
|
||||
}
|
||||
|
||||
return std::make_unique<SdFolder>(fileInfos, count);
|
||||
}
|
||||
16
arm9/source/romBrowser/SdFolderFactory.h
Normal file
16
arm9/source/romBrowser/SdFolderFactory.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "SdFolder.h"
|
||||
#include "FileType/IFileTypeProvider.h"
|
||||
|
||||
class SdFolderFactory
|
||||
{
|
||||
public:
|
||||
SdFolderFactory(const IFileTypeProvider* fileTypeProvider)
|
||||
: _fileTypeProvider(fileTypeProvider) { }
|
||||
|
||||
std::unique_ptr<SdFolder> CreateFromPath(const char* path) const;
|
||||
|
||||
private:
|
||||
const IFileTypeProvider* _fileTypeProvider;
|
||||
};
|
||||
15
arm9/source/romBrowser/SdFolderFilterSortParams.h
Normal file
15
arm9/source/romBrowser/SdFolderFilterSortParams.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "SdFolderSortType.h"
|
||||
#include "SdFolderSortDirection.h"
|
||||
|
||||
class SdFolderFilterSortParams
|
||||
{
|
||||
public:
|
||||
SdFolderSortType sortType = SdFolderSortType::Name;
|
||||
SdFolderSortDirection sortDirection = SdFolderSortDirection::Ascending;
|
||||
|
||||
SdFolderFilterSortParams() { }
|
||||
|
||||
SdFolderFilterSortParams(SdFolderSortType sortType, SdFolderSortDirection sortDirection)
|
||||
: sortType(sortType), sortDirection(sortDirection) { }
|
||||
};
|
||||
7
arm9/source/romBrowser/SdFolderSortDirection.h
Normal file
7
arm9/source/romBrowser/SdFolderSortDirection.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum class SdFolderSortDirection
|
||||
{
|
||||
Ascending,
|
||||
Descending
|
||||
};
|
||||
7
arm9/source/romBrowser/SdFolderSortType.h
Normal file
7
arm9/source/romBrowser/SdFolderSortType.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum class SdFolderSortType
|
||||
{
|
||||
Name,
|
||||
LastModified
|
||||
};
|
||||
70
arm9/source/romBrowser/StateMachineTriggerChecker.h
Normal file
70
arm9/source/romBrowser/StateMachineTriggerChecker.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Helper class for specifying state machine state transitions in an intuitive way.
|
||||
/// @tparam TState The state enum type.
|
||||
/// @tparam TTrigger The trigger enum type.
|
||||
template <typename TState, typename TTrigger>
|
||||
class StateMachineTriggerChecker
|
||||
{
|
||||
const TState _fromState;
|
||||
const TTrigger _trigger;
|
||||
bool _isValid;
|
||||
TState _newState;
|
||||
|
||||
TState _from;
|
||||
TTrigger _fromTrigger;
|
||||
public:
|
||||
/// @brief Constructs a StateMachineTriggerChecker for a state machine
|
||||
/// that is currently in state fromState and received the given trigger.
|
||||
/// @param fromState The current state of the state machine.
|
||||
/// @param trigger The received trigger.
|
||||
explicit constexpr StateMachineTriggerChecker(TState fromState, TTrigger trigger)
|
||||
: _fromState(fromState), _trigger(trigger), _isValid(false), _newState(fromState) { }
|
||||
|
||||
/// @brief Specifies the start of a state transition. Multiple triggers can be
|
||||
/// specified for a given from state.
|
||||
/// @param from The start state of the following trigger definitions.
|
||||
/// @return this
|
||||
constexpr StateMachineTriggerChecker& In(TState from)
|
||||
{
|
||||
if (!_isValid)
|
||||
_from = from;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Specifies the trigger for a state transition. Should be used
|
||||
/// after In has been used at least once.
|
||||
/// @param trigger The trigger of the state transition.
|
||||
/// @return this
|
||||
constexpr StateMachineTriggerChecker& Trigger(TTrigger trigger)
|
||||
{
|
||||
if (!_isValid)
|
||||
_fromTrigger = trigger;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Specifies the end state for a state transition. Should be used
|
||||
/// after every Trigger.
|
||||
/// @param to The end state of the state transition.
|
||||
/// @return this
|
||||
constexpr StateMachineTriggerChecker& GoesTo(TState to)
|
||||
{
|
||||
if (!_isValid && _fromState == _from && _trigger == _fromTrigger)
|
||||
{
|
||||
_isValid = true;
|
||||
_newState = to;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Ends the state transition definitions and returns
|
||||
/// the check result.
|
||||
/// @param newState The new state for the state machine.
|
||||
/// @return true if the received trigger was valid for the
|
||||
/// state of the state machine, or false otherwise.
|
||||
constexpr bool Check(TState& newState) const
|
||||
{
|
||||
newState = _newState;
|
||||
return _isValid;
|
||||
}
|
||||
};
|
||||
40
arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h
Normal file
40
arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "../views/IconGridItemView.h"
|
||||
#include "../views/BannerListItemView.h"
|
||||
#include "../views/AppBarView.h"
|
||||
#include "../views/BannerView.h"
|
||||
#include "gui/views/RecyclerViewBase.h"
|
||||
|
||||
class VramContext;
|
||||
class VBlankTextureLoader;
|
||||
class RomBrowserViewModel;
|
||||
class IThemeFileIconFactory;
|
||||
class FileRecyclerAdapter;
|
||||
|
||||
class IRomBrowserViewFactory
|
||||
{
|
||||
public:
|
||||
virtual ~IRomBrowserViewFactory() = 0;
|
||||
|
||||
virtual IconGridItemView* CreateIconGridItemView() const = 0;
|
||||
virtual IconGridItemView::VramToken UploadIconGridItemViewGraphics(
|
||||
const VramContext& vramContext) const { return IconGridItemView::VramToken(0); }
|
||||
|
||||
virtual BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const = 0;
|
||||
virtual BannerListItemView::VramToken UploadBannerListItemViewGraphics(
|
||||
const VramContext& vramContext) const { return BannerListItemView::VramToken(0); }
|
||||
|
||||
virtual std::unique_ptr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation,
|
||||
int startButtonCount, int endButtonCount) const = 0;
|
||||
|
||||
virtual std::unique_ptr<BannerView> CreateFileInfoView() const = 0;
|
||||
|
||||
virtual std::unique_ptr<RecyclerViewBase> CreateCoverFlowRecyclerView() const = 0;
|
||||
|
||||
virtual FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
VBlankTextureLoader* vblankTextureLoader) const = 0;
|
||||
};
|
||||
|
||||
inline IRomBrowserViewFactory::~IRomBrowserViewFactory() { }
|
||||
14
arm9/source/romBrowser/Theme/IThemeFileIconFactory.h
Normal file
14
arm9/source/romBrowser/Theme/IThemeFileIconFactory.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
class FileIcon;
|
||||
|
||||
class IThemeFileIconFactory
|
||||
{
|
||||
public:
|
||||
virtual ~IThemeFileIconFactory() = 0;
|
||||
virtual std::unique_ptr<FileIcon> CreateFolderIcon(const TCHAR* name) const = 0;
|
||||
virtual std::unique_ptr<FileIcon> CreateGenericFileIcon(const TCHAR* name) const = 0;
|
||||
virtual std::unique_ptr<FileIcon> CreateNdsFileIcon(const TCHAR* name) const = 0;
|
||||
};
|
||||
|
||||
inline IThemeFileIconFactory::~IThemeFileIconFactory() { }
|
||||
227
arm9/source/romBrowser/Theme/Material/CarouselRecyclerView.cpp
Normal file
227
arm9/source/romBrowser/Theme/Material/CarouselRecyclerView.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <libtwl/mem/memVram.h>
|
||||
#include "gui/Gx.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "gui/materialDesign.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
#include "romBrowser/FileType/FileCover.h"
|
||||
#include "core/math/SinTable.h"
|
||||
#include "carouselMask.h"
|
||||
#include "CarouselRecyclerView.h"
|
||||
|
||||
#define COVER_SPACING 4
|
||||
#define Y_OFFSET 56
|
||||
#define CORNER_RADIUS 18
|
||||
#define SELECTED_COVER_WIDTH COVER_WIDTH
|
||||
#define SELECTED_COVER_X 46
|
||||
#define NEXT_COVER_WIDTH 54
|
||||
#define NEXT_COVER_X (SELECTED_COVER_X + SELECTED_COVER_WIDTH + COVER_SPACING)
|
||||
#define SMALL_COVER_WIDTH 36
|
||||
#define HORIZONTAL_PADDING 6
|
||||
|
||||
u32 CarouselRecyclerView::sMaskTextureVramOffset;
|
||||
|
||||
void CarouselRecyclerView::UploadGraphics(const VramContext& vramContext)
|
||||
{
|
||||
const auto textureVramManager = vramContext.GetTexVramManager();
|
||||
if (textureVramManager)
|
||||
{
|
||||
sMaskTextureVramOffset = textureVramManager->Alloc(carouselMaskBitmapLen);
|
||||
dma_ntrCopy32(3, carouselMaskBitmap, textureVramManager->GetVramAddress(sMaskTextureVramOffset), carouselMaskBitmapLen);
|
||||
}
|
||||
}
|
||||
|
||||
void CarouselRecyclerView::Update()
|
||||
{
|
||||
if (_itemCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int rangeStartIndex = GetSelectedItem() - 4;
|
||||
int rangeEndIndex = GetSelectedItem() + 1 + 4;
|
||||
rangeStartIndex = std::clamp(rangeStartIndex, 0, (int)_itemCount - 1);
|
||||
rangeEndIndex = std::clamp(rangeEndIndex, 0, (int)_itemCount);
|
||||
|
||||
if (_curRangeStart != rangeStartIndex || _curRangeLength != rangeEndIndex - rangeStartIndex)
|
||||
{
|
||||
LOG_DEBUG("range: %d - %d\n", rangeStartIndex, rangeEndIndex - 1);
|
||||
if (_curRangeLength != 0)
|
||||
{
|
||||
if (_curRangeStart < rangeStartIndex)
|
||||
ReleaseRange(_curRangeStart, rangeStartIndex);
|
||||
|
||||
if (rangeEndIndex < _curRangeStart + _curRangeLength)
|
||||
ReleaseRange(rangeEndIndex, _curRangeStart + _curRangeLength);
|
||||
}
|
||||
|
||||
BindRange(rangeStartIndex, rangeEndIndex);
|
||||
|
||||
_curRangeStart = rangeStartIndex;
|
||||
_curRangeLength = rangeEndIndex - rangeStartIndex;
|
||||
}
|
||||
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
|
||||
{
|
||||
_viewPoolEx[i].xPositionAnimator.Update();
|
||||
_viewPoolEx[i].widthAnimator.Update();
|
||||
_viewPool[i].view->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void CarouselRecyclerView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
|
||||
{
|
||||
fix32<12> x = (_viewPoolEx[i].xPositionAnimator.GetValue() + 0.5).Int();
|
||||
fix32<12> width = (_viewPoolEx[i].widthAnimator.GetValue() + 0.5).Int();
|
||||
fix32<12> left = x;
|
||||
if (left < HORIZONTAL_PADDING)
|
||||
{
|
||||
left = HORIZONTAL_PADDING;
|
||||
}
|
||||
fix32<12> right = x + width;
|
||||
if (right > (256 - HORIZONTAL_PADDING))
|
||||
{
|
||||
right = 256 - HORIZONTAL_PADDING;
|
||||
}
|
||||
if (left != right)
|
||||
{
|
||||
graphicsContext.SetPolygonId(i);
|
||||
Gx::MtxIdentity();
|
||||
Gx::MtxTranslate(0, 0, fix32<12>(-5 - std::abs(GetSelectedItem() - _viewPool[i].itemIdx)) / 64);
|
||||
RenderCoverMask(graphicsContext, left, right);
|
||||
|
||||
// Render cover
|
||||
_viewPool[i].view->SetPosition((x - ((COVER_WIDTH - width) / 2) + 0.5).Int(), Y_OFFSET);
|
||||
_viewPool[i].view->Draw(graphicsContext);
|
||||
|
||||
RenderRoundedCorners(graphicsContext, x, width);
|
||||
}
|
||||
}
|
||||
|
||||
Gx::MtxIdentity();
|
||||
}
|
||||
|
||||
void CarouselRecyclerView::RenderCoverMask(GraphicsContext& graphicsContext, fix32<12> left, fix32<12> right) const
|
||||
{
|
||||
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
|
||||
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 0);
|
||||
Gx::TexImageParam((128 * 1024) >> 3, false, false, false, false, GX_TEXSIZE_8,
|
||||
GX_TEXSIZE_8, GX_TEXFMT_PLTT16, false, GX_TEXGEN_NONE);
|
||||
graphicsContext.GetRgb6Palette()->ApplyColor(Rgb<6, 6, 6>(_materialColorScheme->surfaceBright));
|
||||
Gx::TexCoord(0, 0);
|
||||
Gx::Begin(GX_PRIMITIVE_QUAD);
|
||||
{
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((left / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((left / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((right / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((right / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
}
|
||||
Gx::End();
|
||||
}
|
||||
|
||||
void CarouselRecyclerView::RenderRoundedCorners(GraphicsContext& graphicsContext, fix32<12> x, fix32<12> width) const
|
||||
{
|
||||
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
|
||||
false, false, false, GX_DEPTH_FUNC_EQUAL, false, 31, 0);
|
||||
Gx::TexImageParam(sMaskTextureVramOffset >> 3, true, true, true, true, GX_TEXSIZE_32,
|
||||
GX_TEXSIZE_32, GX_TEXFMT_A5I3, false, GX_TEXGEN_NONE);
|
||||
|
||||
graphicsContext.GetRgb6Palette()->ApplyColor(Rgb<6, 6, 6>(_materialColorScheme->inverseOnSurface));
|
||||
Gx::Begin(GX_PRIMITIVE_QUAD);
|
||||
// top-left
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((x / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
Gx::TexCoord(0, CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((x / 64).GetRawValue(), (Y_OFFSET + CORNER_RADIUS) << 3);
|
||||
Gx::TexCoord(CORNER_RADIUS, CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + CORNER_RADIUS) << 3);
|
||||
Gx::TexCoord(CORNER_RADIUS, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + CORNER_RADIUS) / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
|
||||
// top-right
|
||||
Gx::TexCoord(-CORNER_RADIUS, 0);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK(((x + width - CORNER_RADIUS) / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
Gx::TexCoord(-CORNER_RADIUS, CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width - CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + CORNER_RADIUS) << 3);
|
||||
Gx::TexCoord(0, CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width) / 64).GetRawValue(), (Y_OFFSET + CORNER_RADIUS) << 3);
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width) / 64).GetRawValue(), Y_OFFSET << 3);
|
||||
|
||||
// bottom-left
|
||||
Gx::TexCoord(0, -CORNER_RADIUS);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((x / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT - CORNER_RADIUS) << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((x / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(CORNER_RADIUS, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(CORNER_RADIUS, -CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT - CORNER_RADIUS) << 3);
|
||||
|
||||
// bottom-right
|
||||
Gx::TexCoord(-CORNER_RADIUS, -CORNER_RADIUS);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK(((x + width - CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT - CORNER_RADIUS) << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
Gx::TexCoord(-CORNER_RADIUS, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width - CORNER_RADIUS) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(0, -CORNER_RADIUS);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(((x + width) / 64).GetRawValue(), (Y_OFFSET + COVER_HEIGHT - CORNER_RADIUS) << 3);
|
||||
Gx::End();
|
||||
}
|
||||
|
||||
void CarouselRecyclerView::UpdateItemPosition(int viewPoolIndex, bool initial)
|
||||
{
|
||||
ViewPoolEntry* item = &_viewPool[viewPoolIndex];
|
||||
ViewPoolEntryEx* itemEx = &_viewPoolEx[viewPoolIndex];
|
||||
int selectedIndex = GetSelectedItem();
|
||||
if (selectedIndex == -1)
|
||||
{
|
||||
selectedIndex = 0;
|
||||
}
|
||||
int itemIndex = item->itemIdx;
|
||||
fix32<12> x;
|
||||
fix32<12> width;
|
||||
if (itemIndex < selectedIndex)
|
||||
{
|
||||
x = SELECTED_COVER_X + (SMALL_COVER_WIDTH + COVER_SPACING) * (itemIndex - selectedIndex);
|
||||
width = SMALL_COVER_WIDTH;
|
||||
}
|
||||
else if (itemIndex == selectedIndex + 1)
|
||||
{
|
||||
x = NEXT_COVER_X;
|
||||
width = NEXT_COVER_WIDTH;
|
||||
}
|
||||
else if (itemIndex > selectedIndex + 1)
|
||||
{
|
||||
x = NEXT_COVER_X + NEXT_COVER_WIDTH + COVER_SPACING
|
||||
+ (SMALL_COVER_WIDTH + COVER_SPACING) * (itemIndex - selectedIndex - 2);
|
||||
width = SMALL_COVER_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = SELECTED_COVER_X;
|
||||
width = SELECTED_COVER_WIDTH;
|
||||
}
|
||||
|
||||
if (initial)
|
||||
{
|
||||
itemEx->xPositionAnimator = Animator(x);
|
||||
itemEx->widthAnimator = Animator(width);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemEx->xPositionAnimator.Goto(x, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
|
||||
itemEx->widthAnimator.Goto(width, md::sys::motion::duration::medium4, &md::sys::motion::easing::standard);
|
||||
}
|
||||
}
|
||||
41
arm9/source/romBrowser/Theme/Material/CarouselRecyclerView.h
Normal file
41
arm9/source/romBrowser/Theme/Material/CarouselRecyclerView.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include "romBrowser/views/CoverFlowRecyclerViewBase.h"
|
||||
#include "animation/Animator.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
|
||||
class CarouselRecyclerView : public CoverFlowRecyclerViewBase
|
||||
{
|
||||
public:
|
||||
explicit CarouselRecyclerView(const MaterialColorScheme* materialColorScheme)
|
||||
: _materialColorScheme(materialColorScheme) { }
|
||||
|
||||
static void UploadGraphics(const VramContext& vramContext);
|
||||
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext &graphicsContext) override;
|
||||
|
||||
private:
|
||||
struct ViewPoolEntryEx
|
||||
{
|
||||
Animator<fix32<12>> xPositionAnimator;
|
||||
Animator<fix32<12>> widthAnimator;
|
||||
};
|
||||
|
||||
std::array<ViewPoolEntryEx, 10> _viewPoolEx;
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
|
||||
static u32 sMaskTextureVramOffset;
|
||||
|
||||
void RenderCoverMask(GraphicsContext& graphicsContext, fix32<12> left, fix32<12> right) const;
|
||||
void RenderRoundedCorners(GraphicsContext& graphicsContext, fix32<12> x, fix32<12> width) const;
|
||||
|
||||
void UpdateItemPosition(int viewPoolIndex, bool initial) override;
|
||||
|
||||
void SwapViewPoolEntry(int indexA, int indexB) override
|
||||
{
|
||||
CoverFlowRecyclerViewBase::SwapViewPoolEntry(indexA, indexB);
|
||||
std::swap(_viewPoolEx[indexA], _viewPoolEx[indexB]);
|
||||
}
|
||||
};
|
||||
32
arm9/source/romBrowser/Theme/Material/MaterialAppBarView.cpp
Normal file
32
arm9/source/romBrowser/Theme/Material/MaterialAppBarView.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "common.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "romBrowser/views/IconButton2DView.h"
|
||||
#include "MaterialAppBarView.h"
|
||||
|
||||
MaterialAppBarView::MaterialAppBarView(int x, int y, Orientation orientation,
|
||||
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme)
|
||||
: AppBarView(x, y, orientation, startButtonCount, endButtonCount, materialColorScheme)
|
||||
{
|
||||
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
|
||||
{
|
||||
_buttons[i] = new IconButton2DView(
|
||||
IconButtonView::Type::Standard,
|
||||
IconButtonView::State::NoToggle,
|
||||
md::sys::color::inverseOnSurface,
|
||||
materialColorScheme);
|
||||
AddChildTail(_buttons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialAppBarView::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
const auto objVramManager = vramContext.GetObjVramManager();
|
||||
if (objVramManager)
|
||||
{
|
||||
auto iconButtonVramToken = IconButton2DView::UploadGraphics(*objVramManager);
|
||||
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
|
||||
{
|
||||
static_cast<IconButton2DView*>(_buttons[i])->SetGraphics(iconButtonVramToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
arm9/source/romBrowser/Theme/Material/MaterialAppBarView.h
Normal file
11
arm9/source/romBrowser/Theme/Material/MaterialAppBarView.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "../../views/AppBarView.h"
|
||||
|
||||
class MaterialAppBarView : public AppBarView
|
||||
{
|
||||
public:
|
||||
MaterialAppBarView(int x, int y, Orientation orientation,
|
||||
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme);
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/gfx/gfx.h>
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/OamManager.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/IVramManager.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "core/math/ColorConverter.h"
|
||||
#include "core/math/RgbMixer.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
#include "themes/IFontRepository.h"
|
||||
#include "bannerListItemBg0.h"
|
||||
#include "bannerListItemBg1.h"
|
||||
#include "bannerListItemBg2.h"
|
||||
#include "gui/palette/GradientPalette.h"
|
||||
#include "gui/palette/DirectPalette.h"
|
||||
#include "gui/views/Label2DView.h"
|
||||
#include "MaterialBannerListItemView.h"
|
||||
|
||||
MaterialBannerListItemView::MaterialBannerListItemView(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: BannerListItemView(
|
||||
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Medium10)),
|
||||
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Regular10)),
|
||||
std::make_unique<Label2DView>(160, 16, 50, fontRepository->GetFont(FontType::Regular10)))
|
||||
, _materialColorScheme(materialColorScheme) { }
|
||||
|
||||
void MaterialBannerListItemView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
if (!graphicsContext.IsVisible(Rectangle(_position.x - 2, _position.y - 2, 207, 48)))
|
||||
return;
|
||||
|
||||
auto backColor = _materialColorScheme->inverseOnSurface;
|
||||
auto frontColor = _isFocused
|
||||
? _materialColorScheme->mainIconBg
|
||||
: _materialColorScheme->surfaceBright;
|
||||
u16 bgPltt[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
auto blendFactors = ColorConverter::FromXBGR555(bannerListItemBg0Pal[i]);
|
||||
auto palColor = Rgb<8, 8, 8>(
|
||||
(backColor.r * blendFactors.r + frontColor.r * blendFactors.g + 16) / 31,
|
||||
(backColor.g * blendFactors.r + frontColor.g * blendFactors.g + 16) / 31,
|
||||
(backColor.b * blendFactors.r + frontColor.b * blendFactors.g + 16) / 31);
|
||||
palColor = palColor.Clamped();
|
||||
bgPltt[i] = ColorConverter::ToGBGR565(palColor);
|
||||
}
|
||||
u32 bgPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
|
||||
DirectPalette(bgPltt), _position.y - 2, _position.y - 2 + 48);
|
||||
|
||||
gfx_oam_entry_t* oam = graphicsContext.GetOamManager().AllocOams(4);
|
||||
OamBuilder::OamWithSize<64, 64>(
|
||||
_position.x - 2,
|
||||
_position.y - 2, _bgVramOffset >> 7)
|
||||
.WithPalette16(bgPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[0]);
|
||||
OamBuilder::OamWithSize<64, 64>(
|
||||
_position.x - 2 + 64,
|
||||
_position.y - 2, (_bgVramOffset + bannerListItemBg0TilesLen) >> 7)
|
||||
.WithPalette16(bgPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[1]);
|
||||
OamBuilder::OamWithSize<64, 64>(
|
||||
_position.x - 2 + 64 + 64,
|
||||
_position.y - 2, (_bgVramOffset + bannerListItemBg0TilesLen) >> 7)
|
||||
.WithPalette16(bgPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[2]);
|
||||
OamBuilder::OamWithSize<32, 64>(
|
||||
_position.x - 2 + 64 + 64 + 64,
|
||||
_position.y - 2, (_bgVramOffset + bannerListItemBg0TilesLen + bannerListItemBg1TilesLen) >> 7)
|
||||
.WithPalette16(bgPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[3]);
|
||||
|
||||
if (_isFocused)
|
||||
{
|
||||
_firstLine->SetBackgroundColor(frontColor);
|
||||
_firstLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
_secondLine->SetBackgroundColor(frontColor);
|
||||
_secondLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
_thirdLine->SetBackgroundColor(frontColor);
|
||||
_thirdLine->SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstLine->SetForegroundColor(_materialColorScheme->onSurface);
|
||||
_firstLine->SetBackgroundColor(_materialColorScheme->surfaceBright);
|
||||
_secondLine->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
|
||||
_secondLine->SetBackgroundColor(_materialColorScheme->surfaceBright);
|
||||
_thirdLine->SetForegroundColor(_materialColorScheme->onSurfaceVariant);
|
||||
_thirdLine->SetBackgroundColor(_materialColorScheme->surfaceBright);
|
||||
}
|
||||
|
||||
if (_lines == 1)
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 14);
|
||||
}
|
||||
else if (_lines == 2)
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 8);
|
||||
_secondLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 2);
|
||||
_secondLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 14);
|
||||
_thirdLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 26);
|
||||
}
|
||||
|
||||
if (_lines >= 1)
|
||||
_firstLine->Draw(graphicsContext);
|
||||
if (_lines >= 2)
|
||||
_secondLine->Draw(graphicsContext);
|
||||
if (_lines >= 3)
|
||||
_thirdLine->Draw(graphicsContext);
|
||||
|
||||
if (_icon)
|
||||
{
|
||||
_icon->SetObjVramOffset(_iconVramOffset);
|
||||
_icon->SetPosition(6 + _position.x, 6 + _position.y);
|
||||
_icon->Draw(graphicsContext, frontColor);
|
||||
}
|
||||
}
|
||||
|
||||
BannerListItemView::VramToken MaterialBannerListItemView::UploadGraphics(const VramContext& vramContext)
|
||||
{
|
||||
const auto objVramManager = vramContext.GetObjVramManager();
|
||||
u32 vramOffset = 0;
|
||||
if (objVramManager)
|
||||
{
|
||||
vramOffset = objVramManager->Alloc(
|
||||
bannerListItemBg0TilesLen + bannerListItemBg1TilesLen + bannerListItemBg2TilesLen);
|
||||
dma_ntrCopy32(3, bannerListItemBg0Tiles,
|
||||
objVramManager->GetVramAddress(vramOffset),
|
||||
bannerListItemBg0TilesLen);
|
||||
dma_ntrCopy32(3, bannerListItemBg1Tiles,
|
||||
objVramManager->GetVramAddress(vramOffset + bannerListItemBg0TilesLen),
|
||||
bannerListItemBg1TilesLen);
|
||||
dma_ntrCopy32(3, bannerListItemBg2Tiles,
|
||||
objVramManager->GetVramAddress(vramOffset + bannerListItemBg0TilesLen + bannerListItemBg1TilesLen),
|
||||
bannerListItemBg2TilesLen);
|
||||
}
|
||||
return BannerListItemView::VramToken(vramOffset);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "gui/views/LabelView.h"
|
||||
#include "../../views/BannerListItemView.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
class MaterialBannerListItemView : public BannerListItemView
|
||||
{
|
||||
public:
|
||||
MaterialBannerListItemView(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository);
|
||||
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
Rectangle GetBounds() const override
|
||||
{
|
||||
return Rectangle(_position, 203, 44);
|
||||
}
|
||||
|
||||
void SetGraphics(const VramToken& vramToken) override
|
||||
{
|
||||
_bgVramOffset = vramToken.GetVramOffset();
|
||||
}
|
||||
|
||||
static VramToken UploadGraphics(const VramContext& vramContext);
|
||||
|
||||
private:
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
u32 _bgVramOffset;
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "common.h"
|
||||
#include "romBrowser/FileInfoManager.h"
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "MaterialCoverView.h"
|
||||
#include "romBrowser/Theme/IRomBrowserViewFactory.h"
|
||||
#include "romBrowser/FileType/UnknownFileCover.h"
|
||||
#include "romBrowser/ICoverRepository.h"
|
||||
#include "MaterialCoverFlowFileRecyclerAdapter.h"
|
||||
|
||||
void MaterialCoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height) const
|
||||
{
|
||||
width = COVER_WIDTH;
|
||||
height = COVER_HEIGHT;
|
||||
}
|
||||
|
||||
View* MaterialCoverFlowFileRecyclerAdapter::CreateView() const
|
||||
{
|
||||
return new MaterialCoverView(_vblankTextureLoader);
|
||||
}
|
||||
|
||||
void MaterialCoverFlowFileRecyclerAdapter::DestroyView(View* view) const
|
||||
{
|
||||
auto coverView = static_cast<MaterialCoverView*>(view);
|
||||
delete coverView;
|
||||
}
|
||||
|
||||
TaskResult<void> MaterialCoverFlowFileRecyclerAdapter::BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const
|
||||
{
|
||||
auto coverView = static_cast<MaterialCoverView*>(view);
|
||||
auto cover = _fileInfoManager->GetFileCover(index);
|
||||
if (cancelRequested)
|
||||
{
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
coverView->SetCover(std::move(cover));
|
||||
coverView->UploadCoverGraphics();
|
||||
if (cancelRequested)
|
||||
{
|
||||
coverView->ClearCover();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
return TaskResult<void>::Canceled();
|
||||
}
|
||||
return TaskResult<void>::Completed();
|
||||
}
|
||||
|
||||
void MaterialCoverFlowFileRecyclerAdapter::ReleaseView(View* view, int index) const
|
||||
{
|
||||
LOG_DEBUG("Releasing %d\n", index);
|
||||
auto coverView = static_cast<MaterialCoverView*>(view);
|
||||
coverView->ClearCover();
|
||||
_fileInfoManager->ReleaseFileInfo(index);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include "romBrowser/FileRecyclerAdapter.h"
|
||||
|
||||
class IRomBrowserViewFactory;
|
||||
class VBlankTextureLoader;
|
||||
class ICoverRepository;
|
||||
|
||||
class MaterialCoverFlowFileRecyclerAdapter : public FileRecyclerAdapter
|
||||
{
|
||||
public:
|
||||
MaterialCoverFlowFileRecyclerAdapter(FileInfoManager* fileInfoManager,
|
||||
TaskQueueBase* taskQueue, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
const IRomBrowserViewFactory* romBrowserViewFactory,
|
||||
VBlankTextureLoader* vblankTextureLoader,
|
||||
const ICoverRepository* coverRepository)
|
||||
: FileRecyclerAdapter(fileInfoManager, taskQueue, themeFileIconFactory)
|
||||
, _romBrowserViewFactory(romBrowserViewFactory)
|
||||
, _vblankTextureLoader(vblankTextureLoader)
|
||||
, _coverRepository(coverRepository) { }
|
||||
|
||||
void GetViewSize(int& width, int& height) const override;
|
||||
View* CreateView() const override;
|
||||
void DestroyView(View* view) const override;
|
||||
void ReleaseView(View* view, int index) const override;
|
||||
|
||||
private:
|
||||
const IRomBrowserViewFactory* _romBrowserViewFactory;
|
||||
VBlankTextureLoader* _vblankTextureLoader;
|
||||
const ICoverRepository* _coverRepository;
|
||||
|
||||
TaskResult<void> BindView(View* view, int index,
|
||||
const InternalFileInfo* internalFileInfo, const vu8& cancelRequested) const override;
|
||||
};
|
||||
56
arm9/source/romBrowser/Theme/Material/MaterialCoverView.cpp
Normal file
56
arm9/source/romBrowser/Theme/Material/MaterialCoverView.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "common.h"
|
||||
#include "core/math/SinTable.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "gui/Gx.h"
|
||||
#include "gui/materialDesign.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "MaterialCoverView.h"
|
||||
|
||||
void MaterialCoverView::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
const auto texVramManager = vramContext.GetTexVramManager();
|
||||
const auto texPlttVramManager = vramContext.GetTexPlttVramManager();
|
||||
if (texVramManager && texPlttVramManager)
|
||||
{
|
||||
_texVramOffset = texVramManager->Alloc(128 * 96);
|
||||
_plttVramOffset = texPlttVramManager->Alloc(256 * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialCoverView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
if (_cover.IsValid() && _textureLoadRequest.GetState() == VBlankTextureLoadRequestState::LoadComplete)
|
||||
{
|
||||
Gx::TexImageParam(_texVramOffset >> 3, false, true, false, true, GX_TEXSIZE_128,
|
||||
GX_TEXSIZE_128, GX_TEXFMT_PLTT256, false, GX_TEXGEN_NONE);
|
||||
Gx::TexPlttBase(_plttVramOffset >> 4);
|
||||
|
||||
u32 polygonId = graphicsContext.GetPolygonId();
|
||||
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
|
||||
false, false, false, GX_DEPTH_FUNC_EQUAL, false, 31, polygonId);
|
||||
|
||||
Gx::Color(31, 31, 31);
|
||||
Gx::Begin(GX_PRIMITIVE_QUAD);
|
||||
Gx::TexCoord(0, -COVER_HEIGHT);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK(_position.x << 6, _position.y << 3);
|
||||
REG_GX_VTX_16 = 0;
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK(_position.x << 6, (_position.y + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(COVER_WIDTH, 0);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((_position.x + COVER_WIDTH) << 6, (_position.y + COVER_HEIGHT) << 3);
|
||||
Gx::TexCoord(COVER_WIDTH, -COVER_HEIGHT);
|
||||
REG_GX_VTX_XY = GX_VTX_PACK((_position.x + COVER_WIDTH) << 6, _position.y << 3);
|
||||
Gx::End();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialCoverView::UploadCoverGraphics()
|
||||
{
|
||||
if (_cover.IsValid())
|
||||
{
|
||||
_cover->SetTexVramOffset(_texVramOffset, _plttVramOffset);
|
||||
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
|
||||
_textureLoadRequest = _cover->CreateTextureLoadRequest();
|
||||
_vblankTextureLoader->RequestLoad(_textureLoadRequest);
|
||||
}
|
||||
}
|
||||
54
arm9/source/romBrowser/Theme/Material/MaterialCoverView.h
Normal file
54
arm9/source/romBrowser/Theme/Material/MaterialCoverView.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/SharedPtr.h"
|
||||
#include "gui/views/View.h"
|
||||
#include "romBrowser/FileType/FileCover.h"
|
||||
#include "gui/VBlankTextureLoader.h"
|
||||
|
||||
class MaterialCoverView : public View
|
||||
{
|
||||
public:
|
||||
explicit MaterialCoverView(VBlankTextureLoader* vblankTextureLoader)
|
||||
: _vblankTextureLoader(vblankTextureLoader) { }
|
||||
|
||||
~MaterialCoverView() override
|
||||
{
|
||||
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
|
||||
}
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
Rectangle GetBounds() const override
|
||||
{
|
||||
return Rectangle(_position.x - (COVER_WIDTH / 2), _position.y - (COVER_HEIGHT / 2), COVER_WIDTH, COVER_HEIGHT);
|
||||
}
|
||||
|
||||
void SetCover(SharedPtr<FileCover> cover)
|
||||
{
|
||||
if (_cover.IsValid())
|
||||
{
|
||||
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
|
||||
}
|
||||
_cover = std::move(cover);
|
||||
}
|
||||
|
||||
void ClearCover()
|
||||
{
|
||||
if (_cover.IsValid())
|
||||
{
|
||||
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
|
||||
}
|
||||
_cover.Reset();
|
||||
}
|
||||
|
||||
void UploadCoverGraphics();
|
||||
|
||||
private:
|
||||
VBlankTextureLoader* _vblankTextureLoader;
|
||||
SharedPtr<FileCover> _cover;
|
||||
VBlankTextureLoadRequest _textureLoadRequest;
|
||||
u32 _texVramOffset = 0;
|
||||
u32 _plttVramOffset = 0;
|
||||
};
|
||||
66
arm9/source/romBrowser/Theme/Material/MaterialFileIcon.cpp
Normal file
66
arm9/source/romBrowser/Theme/Material/MaterialFileIcon.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "common.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/font/nitroFont2.h"
|
||||
#include "core/math/RgbMixer.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "largeFolderIcon.h"
|
||||
#include "gui/palette/GradientPalette.h"
|
||||
#include "themes/IFontRepository.h"
|
||||
#include "MaterialFileIcon.h"
|
||||
|
||||
MaterialFileIcon::MaterialFileIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: _materialColorScheme(materialColorScheme), _fontRepository(fontRepository)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
TCHAR c = name[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
_displayName[i] = c;
|
||||
}
|
||||
_displayName[i] = 0;
|
||||
}
|
||||
|
||||
void MaterialFileIcon::UploadGraphics(vu16* vram) const
|
||||
{
|
||||
dma_ntrCopy32(3, GetIconTiles(), vram, 32 * 32 / 2);
|
||||
|
||||
auto font = _fontRepository->GetFont(FontType::Medium11);
|
||||
u8 tileBuffer[32 * 16 / 2];
|
||||
memset(tileBuffer, 0, sizeof(tileBuffer));
|
||||
u32 textWidth, textHeight;
|
||||
nft2_measureString(font, _displayName, textWidth, textHeight);
|
||||
nft2_string_render_params_t renderParams;
|
||||
renderParams.x = ((int)32 - (int)textWidth) / 2;
|
||||
renderParams.y = 0;
|
||||
renderParams.width = 32;
|
||||
renderParams.height = 16;
|
||||
renderParams.a5i3 = false;
|
||||
nft2_renderString(font, _displayName, tileBuffer, 32, &renderParams);
|
||||
memcpy((u8*)vram + largeFolderIconTilesLen, tileBuffer, sizeof(tileBuffer));
|
||||
}
|
||||
|
||||
void MaterialFileIcon::Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor)
|
||||
{
|
||||
auto iconColor = GetIconColor();
|
||||
auto nameColor = GetTextColor();
|
||||
|
||||
auto oams = graphicsContext.GetOamManager().AllocOams(2);
|
||||
|
||||
u32 iconPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
|
||||
GradientPalette(backgroundColor, iconColor), _position.y, _position.y + 32);
|
||||
OamBuilder::OamWithSize<32, 32>(_position.x, _position.y, _vramOffset >> 7)
|
||||
.WithPalette16(iconPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oams[1]);
|
||||
|
||||
u32 namePaletteRow = graphicsContext.GetPaletteManager().AllocRow(
|
||||
GradientPalette(iconColor, nameColor), _position.y, _position.y + 32);
|
||||
OamBuilder::OamWithSize<32, 16>(_position.x, _position.y + GetTextYOffset(), (_vramOffset + largeFolderIconTilesLen) >> 7)
|
||||
.WithPalette16(namePaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oams[0]);
|
||||
}
|
||||
28
arm9/source/romBrowser/Theme/Material/MaterialFileIcon.h
Normal file
28
arm9/source/romBrowser/Theme/Material/MaterialFileIcon.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "../../FileType/FileIcon.h"
|
||||
#include "core/math/Rgb.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
class MaterialFileIcon : public FileIcon
|
||||
{
|
||||
public:
|
||||
MaterialFileIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository);
|
||||
|
||||
void UploadGraphics(vu16* vram) const override;
|
||||
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;
|
||||
|
||||
protected:
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
const IFontRepository* _fontRepository;
|
||||
|
||||
virtual const void* GetIconTiles() const = 0;
|
||||
virtual Rgb<8, 8, 8> GetIconColor() const = 0;
|
||||
virtual Rgb<8, 8, 8> GetTextColor() const = 0;
|
||||
virtual int GetTextYOffset() const = 0;
|
||||
|
||||
private:
|
||||
char16_t _displayName[4];
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "common.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/IVramManager.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "core/math/RgbMixer.h"
|
||||
#include "core/math/ColorConverter.h"
|
||||
#include "iconCell.h"
|
||||
#include "gui/palette/GradientPalette.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
#include "themes/IFontRepository.h"
|
||||
#include "MaterialFileInfoCardView.h"
|
||||
|
||||
MaterialFileInfoCardView::MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: _firstLine(176, 16, 50, fontRepository->GetFont(FontType::Medium11))
|
||||
, _secondLine(176, 16, 50, fontRepository->GetFont(FontType::Regular10))
|
||||
, _thirdLine(176, 16, 50, fontRepository->GetFont(FontType::Regular10))
|
||||
, _filenameLabelView(220, 16, 200, fontRepository->GetFont(FontType::Medium7_5))
|
||||
, _materialColorScheme(materialColorScheme)
|
||||
{
|
||||
AddChildTail(&_firstLine);
|
||||
AddChildTail(&_secondLine);
|
||||
AddChildTail(&_thirdLine);
|
||||
_filenameLabelView.SetEllipsis(true);
|
||||
AddChildTail(&_filenameLabelView);
|
||||
}
|
||||
|
||||
void MaterialFileInfoCardView::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
BannerView::InitVram(vramContext);
|
||||
|
||||
const auto objVramManager = vramContext.GetObjVramManager();
|
||||
if (objVramManager)
|
||||
{
|
||||
_iconCellVramOffset = objVramManager->Alloc(iconCellTilesLen);
|
||||
dma_ntrCopy32(3, iconCellTiles, objVramManager->GetVramAddress(_iconCellVramOffset), iconCellTilesLen);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialFileInfoCardView::Update()
|
||||
{
|
||||
BannerView::Update();
|
||||
_firstLine.SetPosition(_position.x + 70, _position.y + 130 - 8);
|
||||
_secondLine.SetPosition(_position.x + 70, _position.y + 145 - 8);
|
||||
_thirdLine.SetPosition(_position.x + 70, _position.y + 159 - 8);
|
||||
_filenameLabelView.SetPosition(_position.x + 18, _position.y + 168);
|
||||
if (_icon)
|
||||
{
|
||||
_icon->SetPosition(_position.x + 24, _position.y + 136 - 8);
|
||||
_icon->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialFileInfoCardView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
_firstLine.SetBackgroundColor(_materialColorScheme->secondaryContainer);
|
||||
_firstLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
_secondLine.SetBackgroundColor(_materialColorScheme->secondaryContainer);
|
||||
_secondLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
_thirdLine.SetBackgroundColor(_materialColorScheme->secondaryContainer);
|
||||
_thirdLine.SetForegroundColor(_materialColorScheme->onSecondaryContainer);
|
||||
_filenameLabelView.SetBackgroundColor(_materialColorScheme->secondaryContainer);
|
||||
_filenameLabelView.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
|
||||
|
||||
BannerView::Draw(graphicsContext);
|
||||
|
||||
const auto& bgColor = _materialColorScheme->secondaryContainer;
|
||||
const auto& fgColor = _materialColorScheme->mainIconBg;
|
||||
u32 iconCellPlttRow = graphicsContext.GetPaletteManager().AllocRow(
|
||||
GradientPalette(bgColor, fgColor));
|
||||
|
||||
gfx_oam_entry_t* oam = graphicsContext.GetOamManager().AllocOams(1);
|
||||
OamBuilder::OamWithSize<64, 64>(_position.x + 18, _position.y + 130 - 8, _iconCellVramOffset >> 7)
|
||||
.WithPalette16(iconCellPlttRow)
|
||||
.WithPriority(3)
|
||||
.Build(oam[0]);
|
||||
|
||||
if (_icon)
|
||||
{
|
||||
_icon->SetObjVramOffset(_iconVramOffset);
|
||||
_icon->Draw(graphicsContext, fgColor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include "core/task/TaskQueue.h"
|
||||
#include "gui/views/Label2DView.h"
|
||||
#include "../../views/BannerView.h"
|
||||
|
||||
class FileIcon;
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
class MaterialFileInfoCardView : public BannerView
|
||||
{
|
||||
public:
|
||||
MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository);
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) override
|
||||
{
|
||||
_firstLine.SetEllipsis(ellipsis);
|
||||
if (taskQueue)
|
||||
_firstLine.SetTextAsync(taskQueue, firstLine);
|
||||
else
|
||||
_firstLine.SetText(firstLine);
|
||||
}
|
||||
|
||||
void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override
|
||||
{
|
||||
_firstLine.SetEllipsis(ellipsis);
|
||||
if (taskQueue)
|
||||
_firstLine.SetTextAsync(taskQueue, firstLine, length);
|
||||
else
|
||||
_firstLine.SetText(firstLine, length);
|
||||
}
|
||||
|
||||
void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override
|
||||
{
|
||||
if (taskQueue)
|
||||
_secondLine.SetTextAsync(taskQueue, secondLine, length);
|
||||
else
|
||||
_secondLine.SetText(secondLine, length);
|
||||
}
|
||||
|
||||
void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override
|
||||
{
|
||||
if (taskQueue)
|
||||
_thirdLine.SetTextAsync(taskQueue, thirdLine, length);
|
||||
else
|
||||
_thirdLine.SetText(thirdLine, length);
|
||||
}
|
||||
|
||||
void SetFileNameAsync(TaskQueueBase* taskQueue, const TCHAR* fileName, bool useAsTitle) override
|
||||
{
|
||||
BannerView::SetFileNameAsync(taskQueue, fileName, useAsTitle);
|
||||
if (taskQueue)
|
||||
_filenameLabelView.SetTextAsync(taskQueue, fileName);
|
||||
else
|
||||
_filenameLabelView.SetText(fileName);
|
||||
}
|
||||
|
||||
Rectangle GetBounds() const override
|
||||
{
|
||||
return Rectangle(_position, 236, 60);
|
||||
}
|
||||
|
||||
private:
|
||||
Label2DView _firstLine;
|
||||
Label2DView _secondLine;
|
||||
Label2DView _thirdLine;
|
||||
Label2DView _filenameLabelView;
|
||||
u32 _iconCellVramOffset;
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
};
|
||||
30
arm9/source/romBrowser/Theme/Material/MaterialFolderIcon.h
Normal file
30
arm9/source/romBrowser/Theme/Material/MaterialFolderIcon.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "MaterialFileIcon.h"
|
||||
#include "largeFolderIcon.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
|
||||
class MaterialFolderIcon : public MaterialFileIcon
|
||||
{
|
||||
public:
|
||||
MaterialFolderIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: MaterialFileIcon(name, materialColorScheme, fontRepository) { }
|
||||
|
||||
protected:
|
||||
const void* GetIconTiles() const override
|
||||
{
|
||||
return largeFolderIconTiles;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetIconColor() const override
|
||||
{
|
||||
return _materialColorScheme->tertiaryContainer;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetTextColor() const override
|
||||
{
|
||||
return _materialColorScheme->onTertiaryContainer;
|
||||
}
|
||||
|
||||
int GetTextYOffset() const override { return 10; }
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "MaterialFileIcon.h"
|
||||
#include "largeFileIcon.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
|
||||
class MaterialGenericFileIcon : public MaterialFileIcon
|
||||
{
|
||||
public:
|
||||
MaterialGenericFileIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: MaterialFileIcon(name, materialColorScheme, fontRepository) { }
|
||||
|
||||
protected:
|
||||
const void* GetIconTiles() const override
|
||||
{
|
||||
return largeFileIconTiles;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetIconColor() const override
|
||||
{
|
||||
return _materialColorScheme->tertiary;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetTextColor() const override
|
||||
{
|
||||
return _materialColorScheme->onTertiary;
|
||||
}
|
||||
|
||||
int GetTextYOffset() const override { return 8; }
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/gfx/gfx.h>
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/OamManager.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/IVramManager.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "iconCell2.h"
|
||||
#include "iconCell3.h"
|
||||
#include "core/math/ColorConverter.h"
|
||||
#include "core/math/RgbMixer.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
#include "gui/palette/DirectPalette.h"
|
||||
#include "MaterialIconGridItemView.h"
|
||||
|
||||
void MaterialIconGridItemView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
if (!graphicsContext.IsVisible(Rectangle(_position.x - 2, _position.y - 2, 48, 48)))
|
||||
return;
|
||||
|
||||
auto backColor = _materialColorScheme->inverseOnSurface;
|
||||
auto frontColor = _isFocused
|
||||
? _materialColorScheme->mainIconBg
|
||||
: _materialColorScheme->surfaceBright;
|
||||
u16 selectedIconCellPltt[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
auto blendFactors = ColorConverter::FromXBGR555(iconCell3Pal[i]);
|
||||
auto palColor = Rgb<8, 8, 8>(
|
||||
(backColor.r * blendFactors.r + frontColor.r * blendFactors.g + 16) / 31,
|
||||
(backColor.g * blendFactors.r + frontColor.g * blendFactors.g + 16) / 31,
|
||||
(backColor.b * blendFactors.r + frontColor.b * blendFactors.g + 16) / 31);
|
||||
palColor = palColor.Clamped();
|
||||
selectedIconCellPltt[i] = ColorConverter::ToGBGR565(palColor);
|
||||
}
|
||||
u32 cellPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
|
||||
DirectPalette(selectedIconCellPltt), _position.y - 2, _position.y - 2 + 48);
|
||||
|
||||
gfx_oam_entry_t* oam = graphicsContext.GetOamManager().AllocOams(1);
|
||||
OamBuilder::OamWithSize<64, 64>(
|
||||
_position.x - 2,
|
||||
_position.y - 2, _bgVramOffset >> 7)
|
||||
.WithPalette16(cellPaletteRow)
|
||||
.WithPriority(graphicsContext.GetPriority())
|
||||
.Build(oam[0]);
|
||||
|
||||
if (_icon)
|
||||
{
|
||||
_icon->SetObjVramOffset(_iconVramOffset);
|
||||
_icon->SetPosition(6 + _position.x, 6 + _position.y);
|
||||
_icon->Draw(graphicsContext, frontColor);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIconGridItemView::VramToken MaterialIconGridItemView::UploadGraphics(const VramContext& vramContext)
|
||||
{
|
||||
const auto objVramManager = vramContext.GetObjVramManager();
|
||||
u32 vramOffset = 0;
|
||||
if (objVramManager)
|
||||
{
|
||||
vramOffset = objVramManager->Alloc(iconCell3TilesLen);
|
||||
dma_ntrCopy32(3, iconCell3Tiles, objVramManager->GetVramAddress(vramOffset), iconCell3TilesLen);
|
||||
}
|
||||
|
||||
return MaterialIconGridItemView::VramToken(vramOffset);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "../../views/IconGridItemView.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
|
||||
class MaterialIconGridItemView : public IconGridItemView
|
||||
{
|
||||
public:
|
||||
explicit MaterialIconGridItemView(const MaterialColorScheme* materialColorScheme)
|
||||
: _materialColorScheme(materialColorScheme) { }
|
||||
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
Rectangle GetBounds() const override
|
||||
{
|
||||
return Rectangle(_position, 44, 44);
|
||||
}
|
||||
|
||||
void SetGraphics(const VramToken& vramToken) override
|
||||
{
|
||||
_bgVramOffset = vramToken.GetVramOffset();
|
||||
}
|
||||
|
||||
static VramToken UploadGraphics(const VramContext& vramContext);
|
||||
|
||||
private:
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
u32 _bgVramOffset;
|
||||
};
|
||||
30
arm9/source/romBrowser/Theme/Material/MaterialNdsFileIcon.h
Normal file
30
arm9/source/romBrowser/Theme/Material/MaterialNdsFileIcon.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "MaterialFileIcon.h"
|
||||
#include "largeDSCardIcon.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
|
||||
class MaterialNdsFileIcon : public MaterialFileIcon
|
||||
{
|
||||
public:
|
||||
MaterialNdsFileIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: MaterialFileIcon(name, materialColorScheme, fontRepository) { }
|
||||
|
||||
protected:
|
||||
const void* GetIconTiles() const override
|
||||
{
|
||||
return largeDSCardIconTiles;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetIconColor() const override
|
||||
{
|
||||
return _materialColorScheme->tertiary;
|
||||
}
|
||||
|
||||
Rgb<8, 8, 8> GetTextColor() const override
|
||||
{
|
||||
return _materialColorScheme->onTertiary;
|
||||
}
|
||||
|
||||
int GetTextYOffset() const override { return 3; }
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include "MaterialIconGridItemView.h"
|
||||
#include "MaterialBannerListItemView.h"
|
||||
#include "MaterialFileInfoCardView.h"
|
||||
#include "../IRomBrowserViewFactory.h"
|
||||
#include "romBrowser/viewModels/RomBrowserViewModel.h"
|
||||
#include "CarouselRecyclerView.h"
|
||||
#include "MaterialCoverFlowFileRecyclerAdapter.h"
|
||||
#include "MaterialAppBarView.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
class MaterialRomBrowserViewFactory : public IRomBrowserViewFactory
|
||||
{
|
||||
public:
|
||||
MaterialRomBrowserViewFactory(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { }
|
||||
|
||||
IconGridItemView* CreateIconGridItemView() const override
|
||||
{
|
||||
return new MaterialIconGridItemView(_materialColorScheme);
|
||||
}
|
||||
|
||||
IconGridItemView::VramToken UploadIconGridItemViewGraphics(
|
||||
const VramContext& vramContext) const override
|
||||
{
|
||||
return MaterialIconGridItemView::UploadGraphics(vramContext);
|
||||
}
|
||||
|
||||
BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return new MaterialBannerListItemView(_materialColorScheme, _fontRepository);
|
||||
}
|
||||
|
||||
BannerListItemView::VramToken UploadBannerListItemViewGraphics(
|
||||
const VramContext& vramContext) const override
|
||||
{
|
||||
return MaterialBannerListItemView::UploadGraphics(vramContext);
|
||||
}
|
||||
|
||||
std::unique_ptr<AppBarView> CreateAppBarView(int x, int y, AppBarView::Orientation orientation,
|
||||
int startButtonCount, int endButtonCount) const override
|
||||
{
|
||||
return std::make_unique<MaterialAppBarView>(x, y, orientation, startButtonCount, endButtonCount, _materialColorScheme);
|
||||
}
|
||||
|
||||
std::unique_ptr<BannerView> CreateFileInfoView() const override
|
||||
{
|
||||
return std::make_unique<MaterialFileInfoCardView>(_materialColorScheme, _fontRepository);
|
||||
}
|
||||
|
||||
std::unique_ptr<RecyclerViewBase> CreateCoverFlowRecyclerView() const override
|
||||
{
|
||||
return std::make_unique<CarouselRecyclerView>(_materialColorScheme);
|
||||
}
|
||||
|
||||
FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter(
|
||||
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
|
||||
VBlankTextureLoader* vblankTextureLoader) const override
|
||||
{
|
||||
return new MaterialCoverFlowFileRecyclerAdapter(
|
||||
&viewModel->GetFileInfoManager(), viewModel->GetIoTaskQueue(),
|
||||
themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository());
|
||||
}
|
||||
|
||||
private:
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
const IFontRepository* _fontRepository;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "../IThemeFileIconFactory.h"
|
||||
#include "MaterialFolderIcon.h"
|
||||
#include "MaterialGenericFileIcon.h"
|
||||
#include "MaterialNdsFileIcon.h"
|
||||
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
class MaterialThemeFileIconFactory : public IThemeFileIconFactory
|
||||
{
|
||||
public:
|
||||
explicit MaterialThemeFileIconFactory(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository)
|
||||
: _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { }
|
||||
|
||||
std::unique_ptr<FileIcon> CreateFolderIcon(const TCHAR* name) const override
|
||||
{
|
||||
return std::make_unique<MaterialFolderIcon>(name, _materialColorScheme, _fontRepository);
|
||||
}
|
||||
|
||||
std::unique_ptr<FileIcon> CreateGenericFileIcon(const TCHAR* name) const override
|
||||
{
|
||||
return std::make_unique<MaterialGenericFileIcon>(name, _materialColorScheme, _fontRepository);
|
||||
}
|
||||
|
||||
std::unique_ptr<FileIcon> CreateNdsFileIcon(const TCHAR* name) const override
|
||||
{
|
||||
return std::make_unique<MaterialNdsFileIcon>(name, _materialColorScheme, _fontRepository);
|
||||
}
|
||||
|
||||
private:
|
||||
const MaterialColorScheme* _materialColorScheme;
|
||||
const IFontRepository* _fontRepository;
|
||||
};
|
||||
60
arm9/source/romBrowser/Theme/custom/CustomAppBarView.cpp
Normal file
60
arm9/source/romBrowser/Theme/custom/CustomAppBarView.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "common.h"
|
||||
#include "gui/Gx.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "romBrowser/views/IconButton3DView.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,
|
||||
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme,
|
||||
u32 scrimTexVramOffset, u32 scrimPlttVramOffset)
|
||||
: AppBarView(x, y, orientation, startButtonCount, endButtonCount, materialColorScheme)
|
||||
, _scrimTexVramOffset(scrimTexVramOffset), _scrimPlttVramOffset(scrimPlttVramOffset)
|
||||
{
|
||||
for (int i = 0; i < _startButtonCount + _endButtonCount; i++)
|
||||
{
|
||||
_buttons[i] = new IconButton3DView(
|
||||
IconButtonView::Type::Tonal,
|
||||
IconButtonView::State::NoToggle,
|
||||
md::sys::color::inverseOnSurface,
|
||||
materialColorScheme);
|
||||
AddChildTail(_buttons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomAppBarView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
Gx::MtxIdentity();
|
||||
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
|
||||
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 63);
|
||||
Gx::Color(0);
|
||||
Gx::TexImageParam(_scrimTexVramOffset >> 3, true, false, false, false, GX_TEXSIZE_8,
|
||||
GX_TEXSIZE_64, GX_TEXFMT_A5I3, false, GX_TEXGEN_NONE);
|
||||
Gx::TexPlttBase(_scrimPlttVramOffset >> 4);
|
||||
Gx::Begin(GX_PRIMITIVE_QUAD);
|
||||
if (GetOrientation() == Orientation::Horizontal)
|
||||
{
|
||||
Gx::TexCoord(0, 0);
|
||||
Gx::Vtx16(0, 0, -1.0 / 64);
|
||||
Gx::TexCoord(0, 42);
|
||||
Gx::Vtx16(0, 42.0 / 512.0, -1.0 / 64);
|
||||
Gx::TexCoord(256, 42);
|
||||
Gx::Vtx16(256.0 / 64, 42.0 / 512.0, -1.0 / 64);
|
||||
Gx::TexCoord(256, 0);
|
||||
Gx::Vtx16(256.0 / 64, 0, -1.0 / 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gx::TexCoord(0, 0);
|
||||
Gx::Vtx16(0, 192.0 / 512, -1.0 / 64);
|
||||
Gx::TexCoord(0, 42);
|
||||
Gx::Vtx16(42.0 / 64, 192.0 / 512, -1.0 / 64);
|
||||
Gx::TexCoord(192, 42);
|
||||
Gx::Vtx16(42.0 / 64, 0, -1.0 / 64);
|
||||
Gx::TexCoord(192, 0);
|
||||
Gx::Vtx16(0, 0, -1.0 / 64);
|
||||
Gx::End();
|
||||
}
|
||||
AppBarView::Draw(graphicsContext);
|
||||
}
|
||||
16
arm9/source/romBrowser/Theme/custom/CustomAppBarView.h
Normal file
16
arm9/source/romBrowser/Theme/custom/CustomAppBarView.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "../../views/AppBarView.h"
|
||||
|
||||
class CustomAppBarView : public AppBarView
|
||||
{
|
||||
public:
|
||||
CustomAppBarView(int x, int y, Orientation orientation,
|
||||
int startButtonCount, int endButtonCount, const MaterialColorScheme* materialColorScheme,
|
||||
u32 scrimTexVramOffset, u32 scrimPlttVramOffset);
|
||||
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
private:
|
||||
u32 _scrimTexVramOffset = 0;
|
||||
u32 _scrimPlttVramOffset = 0;
|
||||
};
|
||||
124
arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp
Normal file
124
arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/gfx/gfx.h>
|
||||
#include "core/math/Rgb.h"
|
||||
#include "gui/PaletteManager.h"
|
||||
#include "gui/OamManager.h"
|
||||
#include "gui/Gx.h"
|
||||
#include "gui/OamBuilder.h"
|
||||
#include "gui/IVramManager.h"
|
||||
#include "gui/VramContext.h"
|
||||
#include "gui/GraphicsContext.h"
|
||||
#include "core/math/ColorConverter.h"
|
||||
#include "core/math/RgbMixer.h"
|
||||
#include "themes/material/MaterialColorScheme.h"
|
||||
#include "themes/IFontRepository.h"
|
||||
#include "bannerListItemBg0.h"
|
||||
#include "bannerListItemBg1.h"
|
||||
#include "bannerListItemBg2.h"
|
||||
#include "gui/palette/GradientPalette.h"
|
||||
#include "gui/palette/DirectPalette.h"
|
||||
#include "gui/views/Label3DView.h"
|
||||
#include "CustomBannerListItemView.h"
|
||||
|
||||
#define X_OFFSET (-3)
|
||||
#define Y_OFFSET (-2)
|
||||
#define Z_OFFSET 300
|
||||
#define WIDTH 209
|
||||
#define HEIGHT 49
|
||||
|
||||
#define LINE_WIDTH 160
|
||||
#define LINE_HEIGHT 16
|
||||
#define MAX_LINE_STRING_LENGTH 50
|
||||
|
||||
CustomBannerListItemView::CustomBannerListItemView(const MaterialColorScheme* materialColorScheme,
|
||||
const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset,
|
||||
u32 selectedTexVramOffset, u32 selectedPlttVramOffset, VBlankTextureLoader* vblankTextureLoader)
|
||||
: BannerListItemView(
|
||||
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
|
||||
fontRepository->GetFont(FontType::Medium10), vblankTextureLoader),
|
||||
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
|
||||
fontRepository->GetFont(FontType::Regular10), vblankTextureLoader),
|
||||
std::make_unique<Label3DView>(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH,
|
||||
fontRepository->GetFont(FontType::Regular10), vblankTextureLoader))
|
||||
, _materialColorScheme(materialColorScheme)
|
||||
, _texVramOffset(texVramOffset)
|
||||
, _plttVramOffset(plttVramOffset)
|
||||
, _selectedTexVramOffset(selectedTexVramOffset)
|
||||
, _selectedPlttVramOffset(selectedPlttVramOffset) { }
|
||||
|
||||
void CustomBannerListItemView::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
if (!graphicsContext.IsVisible(Rectangle(_position.x + X_OFFSET, _position.y + Y_OFFSET, WIDTH, HEIGHT)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto backgroundColor = Rgb<8, 8, 8>(200, 200, 200);
|
||||
|
||||
Gx::MtxIdentity();
|
||||
Gx::PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGON_MODE_MODULATE, GX_DISPLAY_MODE_FRONT,
|
||||
false, false, false, GX_DEPTH_FUNC_LESS, false, 31, 0);
|
||||
Gx::Color(0x7FFF);
|
||||
|
||||
u32 tex = _isFocused ? _selectedTexVramOffset : _texVramOffset;
|
||||
u32 pltt = _isFocused ? _selectedPlttVramOffset : _plttVramOffset;
|
||||
Gx::TexImageParam(tex >> 3, false, false, false, false, GX_TEXSIZE_256,
|
||||
GX_TEXSIZE_64, GX_TEXFMT_A3I5, false, GX_TEXGEN_NONE);
|
||||
Gx::TexPlttBase(pltt >> 4);
|
||||
Gx::Begin(GX_PRIMITIVE_QUAD);
|
||||
Gx::TexCoord(0, 0);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((_position.x + X_OFFSET) << 6, (_position.y + Y_OFFSET) << 3);
|
||||
REG_GX_VTX_16 = (Z_OFFSET) << 6;
|
||||
Gx::TexCoord(0, HEIGHT);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((_position.x + X_OFFSET) << 6, (_position.y + Y_OFFSET + HEIGHT) << 3);
|
||||
REG_GX_VTX_16 = (Z_OFFSET) << 6;
|
||||
Gx::TexCoord(WIDTH, HEIGHT);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((_position.x + X_OFFSET + WIDTH) << 6, (_position.y + Y_OFFSET + HEIGHT) << 3);
|
||||
REG_GX_VTX_16 = (Z_OFFSET) << 6;
|
||||
Gx::TexCoord(WIDTH, 0);
|
||||
REG_GX_VTX_16 = GX_VTX_PACK((_position.x + X_OFFSET + WIDTH) << 6, (_position.y + Y_OFFSET) << 3);
|
||||
REG_GX_VTX_16 = (Z_OFFSET) << 6;
|
||||
Gx::End();
|
||||
|
||||
graphicsContext.SetPolygonId(1);
|
||||
|
||||
_firstLine->SetForegroundColor(Rgb<8, 8, 8>(30, 30, 30));
|
||||
_secondLine->SetForegroundColor(Rgb<8, 8, 8>(30, 30, 30));
|
||||
_thirdLine->SetForegroundColor(Rgb<8, 8, 8>(30, 30, 30));
|
||||
|
||||
if (_lines == 1)
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 14);
|
||||
}
|
||||
else if (_lines == 2)
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 8);
|
||||
_secondLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 2);
|
||||
_secondLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 14);
|
||||
_thirdLine->SetPosition(_position.x + 6 + 32 + 6, _position.y + 26);
|
||||
}
|
||||
|
||||
if (_lines >= 1)
|
||||
{
|
||||
_firstLine->Draw(graphicsContext);
|
||||
}
|
||||
if (_lines >= 2)
|
||||
{
|
||||
_secondLine->Draw(graphicsContext);
|
||||
}
|
||||
if (_lines >= 3)
|
||||
{
|
||||
_thirdLine->Draw(graphicsContext);
|
||||
}
|
||||
|
||||
if (_icon)
|
||||
{
|
||||
_icon->SetObjVramOffset(_iconVramOffset);
|
||||
_icon->SetPosition(6 + _position.x, 6 + _position.y);
|
||||
_icon->Draw(graphicsContext, backgroundColor);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user