From cf9ce63db5bf54cb5ee7c06021d65f77815daeb9 Mon Sep 17 00:00:00 2001 From: Gericom Date: Sun, 29 Mar 2026 14:48:12 +0200 Subject: [PATCH] Add various extra customization options for custom themes. Fixes #40 --- _pico/themes/raspberry/theme.json | 116 ++++++++++++- arm9/source/core/math/Rgb.h | 4 +- .../Theme/custom/CustomBannerListItemView.cpp | 19 ++- .../Theme/custom/CustomBannerListItemView.h | 4 +- .../Theme/custom/CustomFileInfoView.cpp | 41 ++--- .../Theme/custom/CustomFileInfoView.h | 6 +- .../Theme/custom/CustomIconGridItemView.cpp | 3 +- .../Theme/custom/CustomIconGridItemView.h | 15 +- .../custom/CustomRomBrowserViewFactory.h | 12 +- .../custom/CustomBannerListTextElementInfo.h | 15 ++ .../themes/custom/CustomBottomIconInfo.h | 15 ++ .../themes/custom/CustomTextElementInfo.h | 21 +++ arm9/source/themes/custom/CustomTheme.cpp | 154 +++++++++++++++++- arm9/source/themes/custom/CustomTheme.h | 17 +- arm9/source/themes/custom/CustomThemeInfo.h | 21 +++ arm9/source/themes/custom/CustomTopIconInfo.h | 17 ++ docs/Themes.md | 70 ++++++++ 17 files changed, 494 insertions(+), 56 deletions(-) create mode 100644 arm9/source/themes/custom/CustomBannerListTextElementInfo.h create mode 100644 arm9/source/themes/custom/CustomBottomIconInfo.h create mode 100644 arm9/source/themes/custom/CustomTextElementInfo.h create mode 100644 arm9/source/themes/custom/CustomThemeInfo.h create mode 100644 arm9/source/themes/custom/CustomTopIconInfo.h diff --git a/_pico/themes/raspberry/theme.json b/_pico/themes/raspberry/theme.json index 70c8774..d4f1323 100644 --- a/_pico/themes/raspberry/theme.json +++ b/_pico/themes/raspberry/theme.json @@ -8,5 +8,119 @@ "g": 217, "b": 255 }, - "darkTheme": false + "darkTheme": false, + "topIcon": { + "position": { + "x": 24, + "y": 132 + }, + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "topBannerTextLine0": { + "position": { + "x": 70, + "y": 126 + }, + "width": 176, + "textColor": { + "r": 30, + "g": 30, + "b": 30 + }, + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "topBannerTextLine1": { + "position": { + "x": 70, + "y": 141 + }, + "width": 176, + "textColor": { + "r": 30, + "g": 30, + "b": 30 + }, + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "topBannerTextLine2": { + "position": { + "x": 70, + "y": 155 + }, + "width": 176, + "textColor": { + "r": 30, + "g": 30, + "b": 30 + }, + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "topFileNameText": { + "position": { + "x": 18, + "y": 170 + }, + "width": 220, + "textColor": { + "r": 30, + "g": 30, + "b": 30 + }, + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "gridIcon": { + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "bannerListIcon": { + "blendColor": { + "r": 200, + "g": 200, + "b": 200 + } + }, + "bannerListTextLine0": { + "textColor": { + "r": 30, + "g": 30, + "b": 30 + } + }, + "bannerListTextLine1": { + "textColor": { + "r": 30, + "g": 30, + "b": 30 + } + }, + "bannerListTextLine2": { + "textColor": { + "r": 30, + "g": 30, + "b": 30 + } + } } \ No newline at end of file diff --git a/arm9/source/core/math/Rgb.h b/arm9/source/core/math/Rgb.h index cdb10bb..6673f0b 100644 --- a/arm9/source/core/math/Rgb.h +++ b/arm9/source/core/math/Rgb.h @@ -74,4 +74,6 @@ public: { return Rgb(r + other.r, g + other.g, b + other.b); } -}; \ No newline at end of file +}; + +using Rgb8 = Rgb<8, 8, 8>; diff --git a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp index 6572dc5..2c03c06 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp +++ b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp @@ -12,6 +12,7 @@ #include "core/math/RgbMixer.h" #include "themes/material/MaterialColorScheme.h" #include "themes/IFontRepository.h" +#include "themes/custom/CustomThemeInfo.h" #include "bannerListItemBg0.h" #include "bannerListItemBg1.h" #include "bannerListItemBg2.h" @@ -30,9 +31,10 @@ #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) +CustomBannerListItemView::CustomBannerListItemView(const CustomThemeInfo* customThemeInfo, + const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository, + u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset, + VBlankTextureLoader* vblankTextureLoader) : BannerListItemView( std::make_unique(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH, fontRepository->GetFont(FontType::Medium10), vblankTextureLoader), @@ -40,6 +42,7 @@ CustomBannerListItemView::CustomBannerListItemView(const MaterialColorScheme* ma fontRepository->GetFont(FontType::Regular10), vblankTextureLoader), std::make_unique(LINE_WIDTH, LINE_HEIGHT, MAX_LINE_STRING_LENGTH, fontRepository->GetFont(FontType::Regular10), vblankTextureLoader)) + , _customThemeInfo(customThemeInfo) , _materialColorScheme(materialColorScheme) , _texVramOffset(texVramOffset) , _plttVramOffset(plttVramOffset) @@ -53,8 +56,6 @@ void CustomBannerListItemView::Draw(GraphicsContext& graphicsContext) 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); @@ -82,9 +83,9 @@ void CustomBannerListItemView::Draw(GraphicsContext& graphicsContext) 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)); + _firstLine->SetForegroundColor(_customThemeInfo->bannerListTextLine0Info.GetTextColor()); + _secondLine->SetForegroundColor(_customThemeInfo->bannerListTextLine1Info.GetTextColor()); + _thirdLine->SetForegroundColor(_customThemeInfo->bannerListTextLine2Info.GetTextColor()); if (_lines == 1) { @@ -118,6 +119,6 @@ void CustomBannerListItemView::Draw(GraphicsContext& graphicsContext) if (_icon) { _icon->SetPosition(6 + _position.x, 6 + _position.y); - _icon->Draw(graphicsContext, backgroundColor); + _icon->Draw(graphicsContext, _customThemeInfo->bannerListIconInfo.GetBlendColor()); } } diff --git a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h index 944818c..b3a40bf 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h @@ -4,11 +4,12 @@ class MaterialColorScheme; class IFontRepository; +class CustomThemeInfo; class CustomBannerListItemView : public BannerListItemView { public: - CustomBannerListItemView(const MaterialColorScheme* materialColorScheme, + CustomBannerListItemView(const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset, VBlankTextureLoader* vblankTextureLoader); @@ -20,6 +21,7 @@ public: } private: + const CustomThemeInfo* _customThemeInfo; const MaterialColorScheme* _materialColorScheme; u32 _texVramOffset = 0; u32 _plttVramOffset = 0; diff --git a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp index a910316..dc8eab5 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp +++ b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp @@ -2,14 +2,15 @@ #include "gui/GraphicsContext.h" #include "gui/IVramManager.h" #include "themes/IFontRepository.h" +#include "themes/custom/CustomThemeInfo.h" #include "CustomFileInfoView.h" -CustomFileInfoView::CustomFileInfoView(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)) - , _backgroundColor(200, 200, 200), _textColor(30, 30, 30) +CustomFileInfoView::CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository) + : _firstLine(customThemeInfo->topBannerTextLine0Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Medium11)) + , _secondLine(customThemeInfo->topBannerTextLine1Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)) + , _thirdLine(customThemeInfo->topBannerTextLine2Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10)) + , _filenameLabelView(customThemeInfo->topFileNameTextInfo.GetWidth(), 16, 256, fontRepository->GetFont(FontType::Medium7_5)) + , _customThemeInfo(customThemeInfo) { AddChildTail(&_firstLine); AddChildTail(&_secondLine); @@ -21,32 +22,32 @@ CustomFileInfoView::CustomFileInfoView(const IFontRepository* fontRepository) void CustomFileInfoView::Update() { BannerView::Update(); - _firstLine.SetPosition(_position.x + 70, _position.y + 130 - 4); - _secondLine.SetPosition(_position.x + 70, _position.y + 145 - 4); - _thirdLine.SetPosition(_position.x + 70, _position.y + 159 - 4); - _filenameLabelView.SetPosition(_position.x + 18, _position.y + 170); + _firstLine.SetPosition(_customThemeInfo->topBannerTextLine0Info.GetPosition()); + _secondLine.SetPosition(_customThemeInfo->topBannerTextLine1Info.GetPosition()); + _thirdLine.SetPosition(_customThemeInfo->topBannerTextLine2Info.GetPosition()); + _filenameLabelView.SetPosition(_customThemeInfo->topFileNameTextInfo.GetPosition()); if (_icon) { - _icon->SetPosition(_position.x + 24, _position.y + 136 - 4); + _icon->SetPosition(_customThemeInfo->topIconInfo.GetPosition()); _icon->Update(); } } void CustomFileInfoView::Draw(GraphicsContext& graphicsContext) { - _firstLine.SetBackgroundColor(_backgroundColor); - _firstLine.SetForegroundColor(_textColor); - _secondLine.SetBackgroundColor(_backgroundColor); - _secondLine.SetForegroundColor(_textColor); - _thirdLine.SetBackgroundColor(_backgroundColor); - _thirdLine.SetForegroundColor(_textColor); - _filenameLabelView.SetBackgroundColor(_backgroundColor); - _filenameLabelView.SetForegroundColor(_textColor); + _firstLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine0Info.GetBlendColor()); + _firstLine.SetForegroundColor(_customThemeInfo->topBannerTextLine0Info.GetTextColor()); + _secondLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine1Info.GetBlendColor()); + _secondLine.SetForegroundColor(_customThemeInfo->topBannerTextLine1Info.GetTextColor()); + _thirdLine.SetBackgroundColor(_customThemeInfo->topBannerTextLine2Info.GetBlendColor()); + _thirdLine.SetForegroundColor(_customThemeInfo->topBannerTextLine2Info.GetTextColor()); + _filenameLabelView.SetBackgroundColor(_customThemeInfo->topFileNameTextInfo.GetBlendColor()); + _filenameLabelView.SetForegroundColor(_customThemeInfo->topFileNameTextInfo.GetTextColor()); BannerView::Draw(graphicsContext); if (_icon) { - _icon->Draw(graphicsContext, _backgroundColor); + _icon->Draw(graphicsContext, _customThemeInfo->topIconInfo.GetBlendColor()); } } diff --git a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h index 46457df..9676cc7 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h @@ -5,11 +5,12 @@ class FileIcon; class IFontRepository; +class CustomThemeInfo; class CustomFileInfoView : public BannerView { public: - explicit CustomFileInfoView(const IFontRepository* fontRepository); + CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository); void Update() override; void Draw(GraphicsContext& graphicsContext) override; @@ -67,6 +68,5 @@ private: Label2DView _secondLine; Label2DView _thirdLine; Label2DView _filenameLabelView; - Rgb<8, 8, 8> _backgroundColor; - Rgb<8, 8, 8> _textColor; + const CustomThemeInfo* _customThemeInfo; }; diff --git a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.cpp b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.cpp index 23cf1a6..0b6de73 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.cpp +++ b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.cpp @@ -5,6 +5,7 @@ #include "gui/OamBuilder.h" #include "gui/IVramManager.h" #include "gui/GraphicsContext.h" +#include "themes/custom/CustomThemeInfo.h" #include "CustomIconGridItemView.h" #define X_OFFSET (-2) @@ -48,6 +49,6 @@ void CustomIconGridItemView::Draw(GraphicsContext& graphicsContext) if (_icon) { _icon->SetPosition(6 + _position.x, 6 + _position.y); - _icon->Draw(graphicsContext, Rgb<8, 8, 8>(200, 200, 200)); + _icon->Draw(graphicsContext, _customThemeInfo->gridIconInfo.GetBlendColor()); } } diff --git a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h index db89e0a..f3a817b 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h @@ -1,12 +1,14 @@ #pragma once #include "../../views/IconGridItemView.h" +class CustomThemeInfo; + class CustomIconGridItemView : public IconGridItemView { public: - CustomIconGridItemView(u32 texVramOffset, u32 plttVramOffset, + CustomIconGridItemView(const CustomThemeInfo* customThemeInfo, u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset) - : _texVramOffset(texVramOffset), _plttVramOffset(plttVramOffset) + : _customThemeInfo(customThemeInfo), _texVramOffset(texVramOffset), _plttVramOffset(plttVramOffset) , _selectedTexVramOffset(selectedTexVramOffset), _selectedPlttVramOffset(selectedPlttVramOffset) { } void Draw(GraphicsContext& graphicsContext) override; @@ -17,8 +19,9 @@ public: } private: - u32 _texVramOffset = 0; - u32 _plttVramOffset = 0; - u32 _selectedTexVramOffset = 0; - u32 _selectedPlttVramOffset = 0; + const CustomThemeInfo* _customThemeInfo; + u32 _texVramOffset; + u32 _plttVramOffset; + u32 _selectedTexVramOffset; + u32 _selectedPlttVramOffset; }; \ No newline at end of file diff --git a/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h b/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h index ea1310d..4e3d539 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h +++ b/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h @@ -12,23 +12,24 @@ class MaterialColorScheme; class ITheme; class VramContext; class IFontRepository; +class CustomThemeInfo; class CustomRomBrowserViewFactory : public IRomBrowserViewFactory { public: - CustomRomBrowserViewFactory(const MaterialColorScheme* materialColorScheme, + CustomRomBrowserViewFactory(const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository) - : _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } + : _customThemeInfo(customThemeInfo), _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } IconGridItemView* CreateIconGridItemView() const override { - return new CustomIconGridItemView(_gridCellTexVramOffset, _gridCellPlttVramOffset, + return new CustomIconGridItemView(_customThemeInfo, _gridCellTexVramOffset, _gridCellPlttVramOffset, _gridCellSelectedTexVramOffset, _gridCellSelectedPlttVramOffset); } BannerListItemView* CreateBannerListItemView(VBlankTextureLoader* vblankTextureLoader) const override { - return new CustomBannerListItemView(_materialColorScheme, _fontRepository, + return new CustomBannerListItemView(_customThemeInfo, _materialColorScheme, _fontRepository, _bannerListCellTexVramOffset, _bannerListCellPlttVramOffset, _bannerListCellSelectedTexVramOffset, _bannerListCellSelectedPlttVramOffset, vblankTextureLoader); } @@ -47,7 +48,7 @@ public: std::unique_ptr CreateFileInfoView() const override { - return std::make_unique(_fontRepository); + return std::make_unique(_customThemeInfo, _fontRepository); } std::unique_ptr CreateCoverFlowRecyclerView() const override @@ -77,6 +78,7 @@ private: u32 _bannerListCellSelectedPlttVramOffset; u32 _scrimTexVramOffset; u32 _scrimPlttVramOffset; + const CustomThemeInfo* _customThemeInfo; const MaterialColorScheme* _materialColorScheme; const IFontRepository* _fontRepository; }; diff --git a/arm9/source/themes/custom/CustomBannerListTextElementInfo.h b/arm9/source/themes/custom/CustomBannerListTextElementInfo.h new file mode 100644 index 0000000..49ef4b0 --- /dev/null +++ b/arm9/source/themes/custom/CustomBannerListTextElementInfo.h @@ -0,0 +1,15 @@ +#pragma once +#include "core/math/Point.h" +#include "core/math/Rgb.h" + +class CustomBannerListTextElementInfo +{ +public: + CustomBannerListTextElementInfo(const Rgb8& textColor) + : _textColor(textColor) { } + + const Rgb8& GetTextColor() const { return _textColor; } + +private: + Rgb8 _textColor; +}; diff --git a/arm9/source/themes/custom/CustomBottomIconInfo.h b/arm9/source/themes/custom/CustomBottomIconInfo.h new file mode 100644 index 0000000..f44c619 --- /dev/null +++ b/arm9/source/themes/custom/CustomBottomIconInfo.h @@ -0,0 +1,15 @@ +#pragma once +#include "core/math/Point.h" +#include "core/math/Rgb.h" + +class CustomBottomIconInfo +{ +public: + CustomBottomIconInfo(const Rgb8& blendColor) + : _blendColor(blendColor) { } + + const Rgb8& GetBlendColor() const { return _blendColor; } + +private: + Rgb8 _blendColor; +}; diff --git a/arm9/source/themes/custom/CustomTextElementInfo.h b/arm9/source/themes/custom/CustomTextElementInfo.h new file mode 100644 index 0000000..3b1efa2 --- /dev/null +++ b/arm9/source/themes/custom/CustomTextElementInfo.h @@ -0,0 +1,21 @@ +#pragma once +#include "core/math/Point.h" +#include "core/math/Rgb.h" + +class CustomTopTextElementInfo +{ +public: + CustomTopTextElementInfo(const Point& position, u32 width, const Rgb8& textColor, const Rgb8& blendColor) + : _position(position), _width(width), _textColor(textColor), _blendColor(blendColor) { } + + const Point& GetPosition() const { return _position; } + const u32 GetWidth() const { return _width; } + const Rgb8& GetTextColor() const { return _textColor; } + const Rgb8& GetBlendColor() const { return _blendColor; } + +private: + Point _position; + u32 _width; + Rgb8 _textColor; + Rgb8 _blendColor; +}; diff --git a/arm9/source/themes/custom/CustomTheme.cpp b/arm9/source/themes/custom/CustomTheme.cpp index 6ee4a28..4ceee5f 100644 --- a/arm9/source/themes/custom/CustomTheme.cpp +++ b/arm9/source/themes/custom/CustomTheme.cpp @@ -11,13 +11,164 @@ #include "romBrowser/views/IconButton3DView.h" #include "CustomTheme.h" -#define JSON_RESERVED_SIZE 2048 +#define JSON_RESERVED_SIZE 4096 + +#define KEY_COLOR_R "r" +#define KEY_COLOR_G "g" +#define KEY_COLOR_B "b" + +#define KEY_POINT_X "x" +#define KEY_POINT_Y "y" + +#define KEY_TOP_ICON "topIcon" +#define KEY_TOP_BANNER_TEXT_LINE_0 "topBannerTextLine0" +#define KEY_TOP_BANNER_TEXT_LINE_1 "topBannerTextLine1" +#define KEY_TOP_BANNER_TEXT_LINE_2 "topBannerTextLine2" +#define KEY_TOP_FILE_NAME_TEXT "topFileNameText" +#define KEY_GRID_ICON "gridIcon" +#define KEY_BANNER_LIST_ICON "bannerListIcon" +#define KEY_BANNER_LIST_TEXT_LINE_0 "bannerListTextLine0" +#define KEY_BANNER_LIST_TEXT_LINE_1 "bannerListTextLine1" +#define KEY_BANNER_LIST_TEXT_LINE_2 "bannerListTextLine2" + +#define KEY_ELEMENT_POSITION "position" +#define KEY_ELEMENT_WIDTH "width" +#define KEY_ELEMENT_TEXT_COLOR "textColor" +#define KEY_ELEMENT_BLEND_COLOR "blendColor" + +static const CustomThemeInfo sDefaultCustomThemeInfo +{ + .topIconInfo = CustomTopIconInfo(Point(24, 132), Rgb8(200, 200, 200)), + .topBannerTextLine0Info = CustomTopTextElementInfo(Point(70, 126), 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)), + .topFileNameTextInfo = CustomTopTextElementInfo(Point(18, 170), 220, Rgb8(30, 30, 30), Rgb8(200, 200, 200)), + + .gridIconInfo = CustomBottomIconInfo(Rgb8(200, 200, 200)), + + .bannerListIconInfo = CustomBottomIconInfo(Rgb8(200, 200, 200)), + .bannerListTextLine0Info = CustomBannerListTextElementInfo(Rgb8(30, 30, 30)), + .bannerListTextLine1Info = CustomBannerListTextElementInfo(Rgb8(30, 30, 30)), + .bannerListTextLine2Info = CustomBannerListTextElementInfo(Rgb8(30, 30, 30)) +}; static CustomTopBackgroundType parseTopBackgroundType(const char* topBackgroundTypeString) { return CustomTopBackgroundType::Bitmap; } +static Rgb8 parseColor(const JsonObjectConst& json, const Rgb8& defaultColor) +{ + if (json.isNull()) + { + return defaultColor; + } + + return Rgb8( + json[KEY_COLOR_R] | 0, + json[KEY_COLOR_G] | 0, + json[KEY_COLOR_B] | 0 + ); +} + +static Point parsePoint(const JsonObjectConst& json, const Point& defaultPoint) +{ + if (json.isNull()) + { + return defaultPoint; + } + + return Point( + json[KEY_POINT_X] | 0, + json[KEY_POINT_Y] | 0 + ); +} + +static CustomBannerListTextElementInfo parseCustomBannerListTextElementInfo( + const JsonObjectConst& json, const CustomBannerListTextElementInfo& defaultInfo) +{ + if (json.isNull()) + { + return defaultInfo; + } + + return CustomBannerListTextElementInfo( + parseColor(json[KEY_ELEMENT_TEXT_COLOR], defaultInfo.GetTextColor()) + ); +} + +static CustomBottomIconInfo parseCustomBottomIconInfo(const JsonObjectConst& json, const CustomBottomIconInfo& defaultInfo) +{ + if (json.isNull()) + { + return defaultInfo; + } + + return CustomBottomIconInfo( + parseColor(json[KEY_ELEMENT_BLEND_COLOR], defaultInfo.GetBlendColor()) + ); +} + +static CustomTopIconInfo parseCustomTopIconInfo(const JsonObjectConst& json, const CustomTopIconInfo& defaultInfo) +{ + if (json.isNull()) + { + return defaultInfo; + } + + return CustomTopIconInfo( + parsePoint(json[KEY_ELEMENT_POSITION], defaultInfo.GetPosition()), + parseColor(json[KEY_ELEMENT_BLEND_COLOR], defaultInfo.GetBlendColor()) + ); +} + +static CustomTopTextElementInfo parseCustomTextElementInfo( + const JsonObjectConst& json, const CustomTopTextElementInfo& defaultInfo) +{ + if (json.isNull()) + { + return defaultInfo; + } + + return CustomTopTextElementInfo( + parsePoint(json[KEY_ELEMENT_POSITION], defaultInfo.GetPosition()), + json[KEY_ELEMENT_WIDTH] | defaultInfo.GetWidth(), + parseColor(json[KEY_ELEMENT_TEXT_COLOR], defaultInfo.GetTextColor()), + parseColor(json[KEY_ELEMENT_BLEND_COLOR], defaultInfo.GetBlendColor()) + ); +} + +static CustomThemeInfo parseCustomThemeInfo(const JsonDocument& json) +{ + return CustomThemeInfo + { + .topIconInfo = parseCustomTopIconInfo(json[KEY_TOP_ICON], sDefaultCustomThemeInfo.topIconInfo), + .topBannerTextLine0Info = parseCustomTextElementInfo( + json[KEY_TOP_BANNER_TEXT_LINE_0], sDefaultCustomThemeInfo.topBannerTextLine0Info), + .topBannerTextLine1Info = parseCustomTextElementInfo( + json[KEY_TOP_BANNER_TEXT_LINE_1], sDefaultCustomThemeInfo.topBannerTextLine1Info), + .topBannerTextLine2Info = parseCustomTextElementInfo( + json[KEY_TOP_BANNER_TEXT_LINE_2], sDefaultCustomThemeInfo.topBannerTextLine2Info), + .topFileNameTextInfo = parseCustomTextElementInfo( + json[KEY_TOP_FILE_NAME_TEXT], sDefaultCustomThemeInfo.topFileNameTextInfo), + + .gridIconInfo = parseCustomBottomIconInfo(json[KEY_GRID_ICON], sDefaultCustomThemeInfo.gridIconInfo), + + .bannerListIconInfo = parseCustomBottomIconInfo(json[KEY_BANNER_LIST_ICON], sDefaultCustomThemeInfo.bannerListIconInfo), + .bannerListTextLine0Info = parseCustomBannerListTextElementInfo( + json[KEY_BANNER_LIST_TEXT_LINE_0], sDefaultCustomThemeInfo.bannerListTextLine0Info), + .bannerListTextLine1Info = parseCustomBannerListTextElementInfo( + json[KEY_BANNER_LIST_TEXT_LINE_1], sDefaultCustomThemeInfo.bannerListTextLine1Info), + .bannerListTextLine2Info = parseCustomBannerListTextElementInfo( + json[KEY_BANNER_LIST_TEXT_LINE_2], sDefaultCustomThemeInfo.bannerListTextLine2Info) + }; +} + +CustomTheme::CustomTheme(const TCHAR* folderName, const Rgb<8, 8, 8>& primaryColor, bool darkMode) + : Theme(folderName, primaryColor, darkMode) + , _customThemeInfo(sDefaultCustomThemeInfo) + , _romBrowserViewFactory(&_customThemeInfo, &_materialColorScheme, &_fontRepository) { } + void CustomTheme::LoadRomBrowserResources(const VramContext& mainVramContext, const VramContext& subVramContext) { const auto file = std::make_unique(); @@ -39,6 +190,7 @@ void CustomTheme::LoadRomBrowserResources(const VramContext& mainVramContext, co return; _topBackgroundType = parseTopBackgroundType(json["topBackgroundType"].as()); + _customThemeInfo = parseCustomThemeInfo(json); mem_setVramDMapping(MEM_VRAM_D_LCDC); mem_setVramEMapping(MEM_VRAM_E_LCDC); diff --git a/arm9/source/themes/custom/CustomTheme.h b/arm9/source/themes/custom/CustomTheme.h index 82766bc..3d7d0f2 100644 --- a/arm9/source/themes/custom/CustomTheme.h +++ b/arm9/source/themes/custom/CustomTheme.h @@ -7,19 +7,13 @@ #include "romBrowser/Theme/custom/CustomRomBrowserViewFactory.h" #include "CustomTopBackgroundType.h" #include "../DefaultFontRepository.h" +#include "CustomThemeInfo.h" #include "../Theme.h" class CustomTheme : public Theme { - String _folderName; - CustomRomBrowserViewFactory _romBrowserViewFactory; - CustomTopBackgroundType _topBackgroundType; - DefaultFontRepository _fontRepository; - public: - CustomTheme(const TCHAR* folderName, const Rgb<8, 8, 8>& primaryColor, bool darkMode) - : Theme(folderName, primaryColor, darkMode) - , _romBrowserViewFactory(&_materialColorScheme, &_fontRepository) { } + CustomTheme(const TCHAR* folderName, const Rgb<8, 8, 8>& primaryColor, bool darkMode); const IFontRepository* GetFontRepository() const override { @@ -47,4 +41,11 @@ public: } void LoadRomBrowserResources(const VramContext& mainVramContext, const VramContext& subVramContext) override; + +private: + String _folderName; + CustomThemeInfo _customThemeInfo; + CustomRomBrowserViewFactory _romBrowserViewFactory; + CustomTopBackgroundType _topBackgroundType; + DefaultFontRepository _fontRepository; }; diff --git a/arm9/source/themes/custom/CustomThemeInfo.h b/arm9/source/themes/custom/CustomThemeInfo.h new file mode 100644 index 0000000..032c168 --- /dev/null +++ b/arm9/source/themes/custom/CustomThemeInfo.h @@ -0,0 +1,21 @@ +#pragma once +#include "CustomBannerListTextElementInfo.h" +#include "CustomBottomIconInfo.h" +#include "CustomTopIconInfo.h" +#include "CustomTextElementInfo.h" + +struct CustomThemeInfo +{ + CustomTopIconInfo topIconInfo; + CustomTopTextElementInfo topBannerTextLine0Info; + CustomTopTextElementInfo topBannerTextLine1Info; + CustomTopTextElementInfo topBannerTextLine2Info; + CustomTopTextElementInfo topFileNameTextInfo; + + CustomBottomIconInfo gridIconInfo; + + CustomBottomIconInfo bannerListIconInfo; + CustomBannerListTextElementInfo bannerListTextLine0Info; + CustomBannerListTextElementInfo bannerListTextLine1Info; + CustomBannerListTextElementInfo bannerListTextLine2Info; +}; diff --git a/arm9/source/themes/custom/CustomTopIconInfo.h b/arm9/source/themes/custom/CustomTopIconInfo.h new file mode 100644 index 0000000..326e3d6 --- /dev/null +++ b/arm9/source/themes/custom/CustomTopIconInfo.h @@ -0,0 +1,17 @@ +#pragma once +#include "core/math/Point.h" +#include "core/math/Rgb.h" + +class CustomTopIconInfo +{ +public: + CustomTopIconInfo(const Point& position, const Rgb8& blendColor) + : _position(position), _blendColor(blendColor) { } + + const Point& GetPosition() const { return _position; } + const Rgb8& GetBlendColor() const { return _blendColor; } + +private: + Point _position; + Rgb8 _blendColor; +}; diff --git a/docs/Themes.md b/docs/Themes.md index 778d73b..c0dc3a2 100644 --- a/docs/Themes.md +++ b/docs/Themes.md @@ -53,5 +53,75 @@ These files can be created, for example, using [NitroPaint](https://github.com/G The top screen background should include a box in which the banner text and icon of the selected item will be shown. +### Additional JSON properties +Custom themes support additional properties in the `theme.json` file to allow for more customization. + +- **topIcon** - Properties of the icon displayed on the top screen. +- **topBannerTextLine0** - Properties of the first 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. +- **topFileNameText** - Properties of the file name text displayed on the top screen. +- **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. +- **bannerListTextLine0** - Properties of the first banner text line displayed on the bottom screen in banner list display mode. +- **bannerListTextLine1** - Properties of the second banner text line displayed on the bottom screen in banner list display mode. +- **bannerListTextLine2** - Properties of the third banner text line displayed on the bottom screen in banner list display mode. + +Blend colors are used to fake translucency. They should be set to an approximation of the background color. + +```json +{ + "type": "custom", + "name": "Raspberry", + "description": "Theme based on raspberries.", + "author": "Gericom", + "primaryColor": { "r": 138, "g": 217, "b": 255 }, + "darkTheme": false, + "topIcon": { + "position": { "x": 24, "y": 132 }, + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "topBannerTextLine0": { + "position": { "x": 70, "y": 126 }, + "width": 176, + "textColor": { "r": 30, "g": 30, "b": 30 }, + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "topBannerTextLine1": { + "position": { "x": 70, "y": 141 }, + "width": 176, + "textColor": { "r": 30, "g": 30, "b": 30 }, + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "topBannerTextLine2": { + "position": { "x": 70, "y": 155 }, + "width": 176, + "textColor": { "r": 30, "g": 30, "b": 30 }, + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "topFileNameText": { + "position": { "x": 18, "y": 170 }, + "width": 220, + "textColor": { "r": 30, "g": 30, "b": 30 }, + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "gridIcon": { + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "bannerListIcon": { + "blendColor": { "r": 200, "g": 200, "b": 200 } + }, + "bannerListTextLine0": { + "textColor": { "r": 30, "g": 30, "b": 30 } + }, + "bannerListTextLine1": { + "textColor": { "r": 30, "g": 30, "b": 30 } + }, + "bannerListTextLine2": { + "textColor": { "r": 30, "g": 30, "b": 30 } + } +} +``` + ## Background music All themes support background music by placing DSP-ADPCM encoded `.bcstm` files in a `bgm` folder inside the theme folder. Looping is supported. When multiple `.bcstm` files are provided, the background music will be selected at random each time Pico Launcher is started.