Add ability to set the position of the top screen cover image in custom themes

This commit is contained in:
Gericom
2026-04-04 10:01:15 +02:00
parent 127de36b1c
commit bec797ffe7
11 changed files with 62 additions and 4 deletions

View File

@@ -2,6 +2,9 @@
## [Unreleased] ## [Unreleased]
### Added
- Ability to set the position of the top screen cover image in custom themes
## [v1.2.0] - 29 Mar 2026 ## [v1.2.0] - 29 Mar 2026
### Added ### Added

View File

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

View File

@@ -35,6 +35,8 @@ public:
virtual FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter( virtual FileRecyclerAdapter* CreateCoverFlowRecyclerAdapter(
RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory, RomBrowserViewModel* viewModel, const IThemeFileIconFactory* themeFileIconFactory,
VBlankTextureLoader* vblankTextureLoader) const = 0; VBlankTextureLoader* vblankTextureLoader) const = 0;
virtual Point GetTopCoverPosition() const = 0;
}; };
inline IRomBrowserViewFactory::~IRomBrowserViewFactory() { } inline IRomBrowserViewFactory::~IRomBrowserViewFactory() { }

View File

@@ -65,6 +65,11 @@ public:
themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository()); themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository());
} }
Point GetTopCoverPosition() const override
{
return Point(75, 18);
}
private: private:
const MaterialColorScheme* _materialColorScheme; const MaterialColorScheme* _materialColorScheme;
const IFontRepository* _fontRepository; const IFontRepository* _fontRepository;

View File

@@ -7,12 +7,12 @@
#include "romBrowser/views/CoverFlowRecyclerView.h" #include "romBrowser/views/CoverFlowRecyclerView.h"
#include "romBrowser/viewModels/RomBrowserViewModel.h" #include "romBrowser/viewModels/RomBrowserViewModel.h"
#include "romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.h" #include "romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.h"
#include "themes/custom/CustomThemeInfo.h"
class MaterialColorScheme; class MaterialColorScheme;
class ITheme; class ITheme;
class VramContext; class VramContext;
class IFontRepository; class IFontRepository;
class CustomThemeInfo;
class CustomRomBrowserViewFactory : public IRomBrowserViewFactory class CustomRomBrowserViewFactory : public IRomBrowserViewFactory
{ {
@@ -65,6 +65,11 @@ public:
themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository()); themeFileIconFactory, this, vblankTextureLoader, &viewModel->GetCoverRepository());
} }
Point GetTopCoverPosition() const override
{
return _customThemeInfo->topCoverInfo.GetPosition();
}
void LoadResources(const ITheme& theme, const VramContext& mainVramContext); void LoadResources(const ITheme& theme, const VramContext& mainVramContext);
private: private:

View File

@@ -20,6 +20,7 @@ RomBrowserTopScreenView::RomBrowserTopScreenView(
, _themeFileIconFactory(themeFileIconFactory) , _themeFileIconFactory(themeFileIconFactory)
, _fileInfoView(romBrowserViewFactory->CreateFileInfoView()) , _fileInfoView(romBrowserViewFactory->CreateFileInfoView())
, _showCover(displayMode->ShowCoverOnTopScreen()) , _showCover(displayMode->ShowCoverOnTopScreen())
, _coverPosition(romBrowserViewFactory->GetTopCoverPosition())
{ {
AddChildTail(_fileInfoView.get()); AddChildTail(_fileInfoView.get());
} }
@@ -135,11 +136,11 @@ void RomBrowserTopScreenView::VBlank()
REG_BG3PB_SUB = 0; REG_BG3PB_SUB = 0;
REG_BG3PC_SUB = 0; REG_BG3PC_SUB = 0;
REG_BG3PD_SUB = -0x100; REG_BG3PD_SUB = -0x100;
REG_BG3X_SUB = -75 << 8; REG_BG3X_SUB = (-_coverPosition.x) << 8;
REG_BG3Y_SUB = 113 << 8; REG_BG3Y_SUB = (96 + _coverPosition.y - 1) << 8;
REG_BG3CNT_SUB = 0x0705; REG_BG3CNT_SUB = 0x0705;
REG_DISPCNT_SUB |= ((1 << 3) | (1 << 5)) << 8; REG_DISPCNT_SUB |= ((1 << 3) | (1 << 5)) << 8;
gfx_setSubWindow0(75, 18, 75 + 106, 18 + 96); gfx_setSubWindow0(_coverPosition.x, _coverPosition.y, _coverPosition.x + 106, _coverPosition.y + 96);
REG_WININ_SUB = 0x002A; REG_WININ_SUB = 0x002A;
REG_WINOUT_SUB = ~(1 << 3); REG_WINOUT_SUB = ~(1 << 3);
} }

View File

@@ -36,4 +36,5 @@ private:
bool _iconGraphicsUploaded = false; bool _iconGraphicsUploaded = false;
bool _coverGraphicsUploaded = false; bool _coverGraphicsUploaded = false;
bool _showCover; bool _showCover;
Point _coverPosition;
}; };

View File

@@ -25,6 +25,7 @@
#define KEY_TOP_BANNER_TEXT_LINE_1 "topBannerTextLine1" #define KEY_TOP_BANNER_TEXT_LINE_1 "topBannerTextLine1"
#define KEY_TOP_BANNER_TEXT_LINE_2 "topBannerTextLine2" #define KEY_TOP_BANNER_TEXT_LINE_2 "topBannerTextLine2"
#define KEY_TOP_FILE_NAME_TEXT "topFileNameText" #define KEY_TOP_FILE_NAME_TEXT "topFileNameText"
#define KEY_TOP_COVER "topCover"
#define KEY_GRID_ICON "gridIcon" #define KEY_GRID_ICON "gridIcon"
#define KEY_BANNER_LIST_ICON "bannerListIcon" #define KEY_BANNER_LIST_ICON "bannerListIcon"
#define KEY_BANNER_LIST_TEXT_LINE_0 "bannerListTextLine0" #define KEY_BANNER_LIST_TEXT_LINE_0 "bannerListTextLine0"
@@ -43,6 +44,7 @@ static const CustomThemeInfo sDefaultCustomThemeInfo
.topBannerTextLine1Info = CustomTopTextElementInfo(Point(70, 141), 176, Rgb8(30, 30, 30), Rgb8(200, 200, 200)), .topBannerTextLine1Info = CustomTopTextElementInfo(Point(70, 141), 176, Rgb8(30, 30, 30), Rgb8(200, 200, 200)),
.topBannerTextLine2Info = CustomTopTextElementInfo(Point(70, 155), 176, Rgb8(30, 30, 30), Rgb8(200, 200, 200)), .topBannerTextLine2Info = CustomTopTextElementInfo(Point(70, 155), 176, Rgb8(30, 30, 30), Rgb8(200, 200, 200)),
.topFileNameTextInfo = CustomTopTextElementInfo(Point(18, 170), 220, Rgb8(30, 30, 30), Rgb8(200, 200, 200)), .topFileNameTextInfo = CustomTopTextElementInfo(Point(18, 170), 220, Rgb8(30, 30, 30), Rgb8(200, 200, 200)),
.topCoverInfo = CustomTopCoverInfo(Point(75, 18)),
.gridIconInfo = CustomBottomIconInfo(Rgb8(200, 200, 200)), .gridIconInfo = CustomBottomIconInfo(Rgb8(200, 200, 200)),
@@ -122,6 +124,18 @@ static CustomTopIconInfo parseCustomTopIconInfo(const JsonObjectConst& json, con
); );
} }
static CustomTopCoverInfo parseCustomTopCoverInfo(const JsonObjectConst& json, const CustomTopCoverInfo& defaultInfo)
{
if (json.isNull())
{
return defaultInfo;
}
return CustomTopCoverInfo(
parsePoint(json[KEY_ELEMENT_POSITION], defaultInfo.GetPosition())
);
}
static CustomTopTextElementInfo parseCustomTextElementInfo( static CustomTopTextElementInfo parseCustomTextElementInfo(
const JsonObjectConst& json, const CustomTopTextElementInfo& defaultInfo) const JsonObjectConst& json, const CustomTopTextElementInfo& defaultInfo)
{ {
@@ -151,6 +165,7 @@ static CustomThemeInfo parseCustomThemeInfo(const JsonDocument& json)
json[KEY_TOP_BANNER_TEXT_LINE_2], sDefaultCustomThemeInfo.topBannerTextLine2Info), json[KEY_TOP_BANNER_TEXT_LINE_2], sDefaultCustomThemeInfo.topBannerTextLine2Info),
.topFileNameTextInfo = parseCustomTextElementInfo( .topFileNameTextInfo = parseCustomTextElementInfo(
json[KEY_TOP_FILE_NAME_TEXT], sDefaultCustomThemeInfo.topFileNameTextInfo), json[KEY_TOP_FILE_NAME_TEXT], sDefaultCustomThemeInfo.topFileNameTextInfo),
.topCoverInfo = parseCustomTopCoverInfo(json[KEY_TOP_COVER], sDefaultCustomThemeInfo.topCoverInfo),
.gridIconInfo = parseCustomBottomIconInfo(json[KEY_GRID_ICON], sDefaultCustomThemeInfo.gridIconInfo), .gridIconInfo = parseCustomBottomIconInfo(json[KEY_GRID_ICON], sDefaultCustomThemeInfo.gridIconInfo),

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "CustomBannerListTextElementInfo.h" #include "CustomBannerListTextElementInfo.h"
#include "CustomBottomIconInfo.h" #include "CustomBottomIconInfo.h"
#include "CustomTopCoverInfo.h"
#include "CustomTopIconInfo.h" #include "CustomTopIconInfo.h"
#include "CustomTextElementInfo.h" #include "CustomTextElementInfo.h"
@@ -11,6 +12,7 @@ struct CustomThemeInfo
CustomTopTextElementInfo topBannerTextLine1Info; CustomTopTextElementInfo topBannerTextLine1Info;
CustomTopTextElementInfo topBannerTextLine2Info; CustomTopTextElementInfo topBannerTextLine2Info;
CustomTopTextElementInfo topFileNameTextInfo; CustomTopTextElementInfo topFileNameTextInfo;
CustomTopCoverInfo topCoverInfo;
CustomBottomIconInfo gridIconInfo; CustomBottomIconInfo gridIconInfo;

View File

@@ -0,0 +1,14 @@
#pragma once
#include "core/math/Point.h"
class CustomTopCoverInfo
{
public:
CustomTopCoverInfo(const Point& position)
: _position(position) { }
const Point& GetPosition() const { return _position; }
private:
Point _position;
};

View File

@@ -61,6 +61,7 @@ Custom themes support additional properties in the `theme.json` file to allow fo
- **topBannerTextLine1** - Properties of the second banner text line displayed on the top screen. - **topBannerTextLine1** - Properties of the second banner text line displayed on the top screen.
- **topBannerTextLine2** - Properties of the third banner text line displayed on the top screen. - **topBannerTextLine2** - Properties of the third banner text line displayed on the top screen.
- **topFileNameText** - Properties of the file name text displayed on the top screen. - **topFileNameText** - Properties of the file name text displayed on the top screen.
- **topCover** - Properties of the cover image displayed on the top screen.
- **gridIcon** - Properties of the icons displayed on the bottom screen in grid display modes. - **gridIcon** - Properties of the icons displayed on the bottom screen in grid display modes.
- **bannerListIcon** - Properties of the icons displayed on the bottom screen in banner list display mode. - **bannerListIcon** - Properties of the icons displayed on the bottom screen in banner list display mode.
- **bannerListTextLine0** - Properties of the first banner text line displayed on the bottom screen in banner list display mode. - **bannerListTextLine0** - Properties of the first banner text line displayed on the bottom screen in banner list display mode.
@@ -105,6 +106,9 @@ Blend colors are used to fake translucency. They should be set to an approximati
"textColor": { "r": 30, "g": 30, "b": 30 }, "textColor": { "r": 30, "g": 30, "b": 30 },
"blendColor": { "r": 200, "g": 200, "b": 200 } "blendColor": { "r": 200, "g": 200, "b": 200 }
}, },
"topCover": {
"position": { "x": 75, "y": 18 }
},
"gridIcon": { "gridIcon": {
"blendColor": { "r": 200, "g": 200, "b": 200 } "blendColor": { "r": 200, "g": 200, "b": 200 }
}, },