diff --git a/Makefile b/Makefile index 62fbfa3..1c97fc2 100755 --- a/Makefile +++ b/Makefile @@ -39,6 +39,13 @@ filesystem/%.sprite: assets/%.png filesystem/Arial.font64: MKFONT_FLAGS+=--size 11 --outline 1.0 --char-spacing 1.0 --range 20-E9 filesystem/Arial-small.font64: MKFONT_FLAGS+=--size 10 --outline 1.0 --char-spacing 1.0 --range 20-E9 +filesystem/logo-libdragon.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-bulbagarden.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-retrogamemechanicsexplained.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-datacrystal.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-pkhex.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-gbdevio.sprite: MKSPRITE_FLAGS += -f RGBA32 +filesystem/logo-nesdevwiki.sprite: MKSPRITE_FLAGS += -f RGBA32 filesystem/menu-bg-9slice.sprite: MKSPRITE_FLAGS += -f RGBA16 pokemegb: diff --git a/assets/logo-bulbagarden.png b/assets/logo-bulbagarden.png new file mode 100644 index 0000000..821767a Binary files /dev/null and b/assets/logo-bulbagarden.png differ diff --git a/assets/logo-datacrystal.png b/assets/logo-datacrystal.png new file mode 100644 index 0000000..ab3ed0e Binary files /dev/null and b/assets/logo-datacrystal.png differ diff --git a/assets/logo-gbdevio.png b/assets/logo-gbdevio.png new file mode 100644 index 0000000..1d47126 Binary files /dev/null and b/assets/logo-gbdevio.png differ diff --git a/assets/logo-libdragon.png b/assets/logo-libdragon.png new file mode 100644 index 0000000..0f25baa Binary files /dev/null and b/assets/logo-libdragon.png differ diff --git a/assets/logo-nesdevwiki.png b/assets/logo-nesdevwiki.png new file mode 100644 index 0000000..e613fd8 Binary files /dev/null and b/assets/logo-nesdevwiki.png differ diff --git a/assets/logo-pkhex.png b/assets/logo-pkhex.png new file mode 100644 index 0000000..8393877 Binary files /dev/null and b/assets/logo-pkhex.png differ diff --git a/assets/logo-retrogamemechanicsexplained.png b/assets/logo-retrogamemechanicsexplained.png new file mode 100644 index 0000000..4f10951 Binary files /dev/null and b/assets/logo-retrogamemechanicsexplained.png differ diff --git a/assets/oak.png b/assets/oak.png deleted file mode 100755 index bc08c45..0000000 Binary files a/assets/oak.png and /dev/null differ diff --git a/assets/pokeball.png b/assets/pokeball.png deleted file mode 100755 index d61f8af..0000000 Binary files a/assets/pokeball.png and /dev/null differ diff --git a/include/core/RDPQGraphics.h b/include/core/RDPQGraphics.h index 2182df4..0c68c52 100755 --- a/include/core/RDPQGraphics.h +++ b/include/core/RDPQGraphics.h @@ -8,10 +8,24 @@ typedef struct TextRenderSettings { + /** + * @brief The libdragon font id (used as handle) as known by libdragon. FontManager manages the various fonts + */ uint8_t fontId; + /** + * @brief The style id used to render the text. (this is a handle/id to a previously registered rdpq_fontstyle_t struct for the fontId specified earlier) + */ uint8_t fontStyleId; int16_t charSpacing; ///< Extra spacing between chars (in addition to glyph width and kerning) int16_t lineSpacing; ///< Extra spacing between lines (in addition to font height) + /** + * @brief The horizontal alignment of the text + */ + rdpq_align_t halign; + /** + * @brief The vertical alignment of the text + */ + rdpq_valign_t valign; } TextRenderSettings; typedef struct SpriteRenderSettings SpriteRenderSettings; diff --git a/include/menu/MenuFunctions.h b/include/menu/MenuFunctions.h index 15e8a8e..c07468b 100755 --- a/include/menu/MenuFunctions.h +++ b/include/menu/MenuFunctions.h @@ -17,6 +17,7 @@ void activateFrameLog(void* context, const void* param); void advanceDialog(void* context, const void* param); void goToTestScene(void* context, const void* param); +void goToAboutScene(void* context, const void* param); void goToGen1DistributionPokemonMenu(void* context, const void* param); void goToGen2DistributionPokemonMenu(void* context, const void* param); diff --git a/include/scenes/AboutScene.h b/include/scenes/AboutScene.h new file mode 100644 index 0000000..f81708a --- /dev/null +++ b/include/scenes/AboutScene.h @@ -0,0 +1,52 @@ +#ifndef _ABOUTSCENE_H +#define _ABOUTSCENE_H + +#include "scenes/AbstractUIScene.h" +#include "widget/ScrollWidget.h" +#include "widget/ImageWidget.h" +#include "widget/TextWidget.h" + +/** + * @brief This scene shows the version number and credits of the PokeMe64 project. + */ +class AboutScene : public AbstractUIScene +{ +public: + AboutScene(SceneDependencies& deps, void* context); + virtual ~AboutScene(); + + void init() override; + void destroy() override; + + bool handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs) override; + void render(RDPQGraphics& gfx, const Rectangle& sceneBounds) override; +protected: +private: + uint8_t fontIdArial_; + uint8_t fontArialStyleWhiteId_; + sprite_t* logoLibDragon_; + sprite_t* logoBulbagarden_; + sprite_t* logoRetroGameMechanicsExplained_; + sprite_t* logoDataCrystal_; + sprite_t* logoPKHEX_; + sprite_t* logoGBDevIO_; + sprite_t* logoNESDevWiki_; + ScrollWidget scrollWidget_; + TextWidget headerText_; + ImageWidget imgDragonWidget_; + ImageWidget imgBulbagardenWidget_; + ImageWidget imgRetroGameMechanicsExplained_; + ImageWidget imgDataCrystal_; + TextWidget dataCrystalText_; + ImageWidget imgPKHEX_; + TextWidget PKHEXText_; + TextWidget pretPokeCrystalText_; + ImageWidget imgGBDevIO_; + TextWidget gbDevIOText_; + ImageWidget imgNESDevWiki_; + TextWidget otherCreditsText_; + WidgetFocusChainSegment scrollFocusSegment_; + bool bButtonPressed_; +}; + +#endif \ No newline at end of file diff --git a/include/scenes/IScene.h b/include/scenes/IScene.h index 07ff4c7..55b826a 100755 --- a/include/scenes/IScene.h +++ b/include/scenes/IScene.h @@ -18,7 +18,8 @@ enum class SceneType MENU, DISTRIBUTION_POKEMON_LIST, STATS, - TEST + TEST, + ABOUT }; typedef struct SceneDependencies diff --git a/include/widget/ImageWidget.h b/include/widget/ImageWidget.h index 4a14765..2b5b8de 100644 --- a/include/widget/ImageWidget.h +++ b/include/widget/ImageWidget.h @@ -7,7 +7,6 @@ typedef struct ImageWidgetStyle { - Dimensions size; struct { /** * (optional) background sprite diff --git a/include/widget/TextWidget.h b/include/widget/TextWidget.h index 3cc0f4d..4c5c632 100644 --- a/include/widget/TextWidget.h +++ b/include/widget/TextWidget.h @@ -6,9 +6,9 @@ typedef struct TextWidgetStyle { - Dimensions size; TextRenderSettings renderSettingsFocused; TextRenderSettings renderSettingsNotFocused; + uint16_t backgroundColor_; // RGBA16 } TextWidgetStyle; /** diff --git a/src/core/RDPQGraphics.cpp b/src/core/RDPQGraphics.cpp index d75b2da..168fdc6 100755 --- a/src/core/RDPQGraphics.cpp +++ b/src/core/RDPQGraphics.cpp @@ -261,8 +261,8 @@ void RDPQGraphics::drawText(const Rectangle &dstRect, const char *text, const Te .style_id = renderSettings.fontStyleId, .width = static_cast(dstRect.width), .height = static_cast(dstRect.height), - .align = ALIGN_LEFT, - .valign = VALIGN_TOP, + .align = renderSettings.halign, + .valign = renderSettings.valign, .char_spacing = renderSettings.charSpacing, .line_spacing = renderSettings.lineSpacing, .wrap = WRAP_WORD, diff --git a/src/menu/MenuEntries.cpp b/src/menu/MenuEntries.cpp index 7a5c3c4..856665f 100755 --- a/src/menu/MenuEntries.cpp +++ b/src/menu/MenuEntries.cpp @@ -15,6 +15,10 @@ MenuItemData gen1MenuEntries[] = { .title = "Teach Pikachu Fly", .onConfirmAction = gen1PrepareToTeachPikachu, .itemParam = &MOVE_FLY + }, + { + .title = "About", + .onConfirmAction = goToAboutScene } }; @@ -32,6 +36,10 @@ MenuItemData gen2MenuEntries[] = { { .title = "Unlock Decoration", .onConfirmAction = goToGen2DecorationMenu + }, + { + .title = "About", + .onConfirmAction = goToAboutScene } }; @@ -53,6 +61,10 @@ MenuItemData gen2CrystalMenuEntries[] = { { .title = "Unlock Decoration", .onConfirmAction = goToGen2DecorationMenu + }, + { + .title = "About", + .onConfirmAction = goToAboutScene } }; diff --git a/src/menu/MenuFunctions.cpp b/src/menu/MenuFunctions.cpp index 2e0c2fe..e57b22d 100755 --- a/src/menu/MenuFunctions.cpp +++ b/src/menu/MenuFunctions.cpp @@ -113,6 +113,14 @@ void goToTestScene(void* context, const void* param) sceneManager.switchScene(SceneType::TEST); } +void goToAboutScene(void* context, const void* param) +{ + MenuScene* scene = static_cast(context); + SceneManager& sceneManager = scene->getDependencies().sceneManager; + + sceneManager.switchScene(SceneType::ABOUT); +} + void goToGen1DistributionPokemonMenu(void* context, const void*) { goToDistributionPokemonListMenu(context, DistributionPokemonListType::GEN1); diff --git a/src/scenes/AboutScene.cpp b/src/scenes/AboutScene.cpp new file mode 100644 index 0000000..fbfb800 --- /dev/null +++ b/src/scenes/AboutScene.cpp @@ -0,0 +1,272 @@ +#include "scenes/AboutScene.h" +#include "core/FontManager.h" +#include "scenes/SceneManager.h" + +static const ScrollWidgetStyle scrollWidgetStyle = { + .scrollStep = 15, + .marginRight = 0, + .marginBottom = 0 +}; + +static const Rectangle scrollWidgetBounds = {0, 0, 320, 240}; +static const Rectangle headerTextBounds = {10, 10, 300, 70}; +static const Rectangle imgDragonBounds = {5, 80, 133, 78}; +static const Rectangle imgBulbagardenBounds = {163, 121, 134, 17}; +static const Rectangle imgRetroGameMechanicsExplainedBounds = {5, 173, 133, 39}; +static const Rectangle imgDataCrystalBounds = {153, 163, 60, 60}; +static const Rectangle dataCrystalTextBounds = {215, 185, 100, 16}; +static const Rectangle imgPKHEXBounds = {25, 233, 38, 37}; +static const Rectangle PKHEXTextBounds = {68, 248, 50, 16}; +static const Rectangle pretPokeCrystalTextBounds = {153, 248, 175, 16}; +static const Rectangle imgGBDevIoBounds = {28, 280, 34, 55}; +static const Rectangle gbDevIOTextBounds = {68, 300, 75, 16}; +static const Rectangle imgNESDevWikiBounds = {163, 280, 96, 60}; +static const Rectangle otherCreditsTextBounds = {5, 350, 310, 80}; + +static const char* otherCreditsString = R"delim(github.com/magical/pokemon-sprites-rby +glitchcity.wiki +github.com/seanmorris/pokemon-parser +github.com/LinusU/pokemon-sprite-compression +github.com/xvillaneau/poke-sprite-python +)delim"; + +static const char* headerTextString = R"delim(PokeMe64 Version 0.1 +by risingPhil + +SPECIAL THANKS TO: +(For docs, tools and/or inspiration) +)delim"; + +AboutScene::AboutScene(SceneDependencies& deps, void*) + : AbstractUIScene(deps) + , fontIdArial_(1) + , fontArialStyleWhiteId_(0) + , logoLibDragon_(nullptr) + , logoBulbagarden_(nullptr) + , logoRetroGameMechanicsExplained_(nullptr) + , logoDataCrystal_(nullptr) + , logoPKHEX_(nullptr) + , logoGBDevIO_(nullptr) + , logoNESDevWiki_(nullptr) + , scrollWidget_(deps.animationManager) + , headerText_() + , imgDragonWidget_() + , imgBulbagardenWidget_() + , imgRetroGameMechanicsExplained_() + , imgDataCrystal_() + , dataCrystalText_() + , imgPKHEX_() + , PKHEXText_() + , pretPokeCrystalText_() + , imgGBDevIO_() + , gbDevIOText_() + , imgNESDevWiki_() + , otherCreditsText_() + , scrollFocusSegment_(WidgetFocusChainSegment{ + .current = &scrollWidget_ + }) + , bButtonPressed_(false) +{ + fontIdArial_ = deps.fontManager.getFont("rom://Arial.font64"); + + const rdpq_fontstyle_t arialWhite = { + .color = RGBA32(0xFF, 0xFF, 0xFF, 0xFF), + .outline_color = RGBA32(0, 0, 0, 0xFF) + }; + + deps.fontManager.registerFontStyle(fontIdArial_, fontArialStyleWhiteId_, arialWhite); +} + +AboutScene::~AboutScene() +{ +} + +void AboutScene::init() +{ + logoLibDragon_ = sprite_load("rom://logo-libdragon.sprite"); + logoBulbagarden_ = sprite_load("rom://logo-bulbagarden.sprite"); + logoRetroGameMechanicsExplained_ = sprite_load("rom://logo-retrogamemechanicsexplained.sprite"); + logoDataCrystal_ = sprite_load("rom://logo-datacrystal.sprite"); + logoPKHEX_ = sprite_load("rom://logo-pkhex.sprite"); + logoGBDevIO_ = sprite_load("rom://logo-gbdevio.sprite"); + logoNESDevWiki_ = sprite_load("rom://logo-nesdevwiki.sprite"); + scrollWidget_.setBounds(scrollWidgetBounds); + scrollWidget_.setStyle(scrollWidgetStyle); + + const TextWidgetStyle headerTextStyle = { + .renderSettingsNotFocused = { + .fontId = fontIdArial_, + .fontStyleId = fontArialStyleWhiteId_, + .halign = ALIGN_CENTER + } + // ,.backgroundColor_ = 0xF801 + }; + + const TextWidgetStyle commonLeftAlignedTextStyle = { + .renderSettingsNotFocused = { + .fontId = fontIdArial_, + .fontStyleId = fontArialStyleWhiteId_, + .halign = ALIGN_LEFT + } + }; + const TextWidgetStyle commonCenterAlignedTextStyle = { + .renderSettingsNotFocused = { + .fontId = fontIdArial_, + .fontStyleId = fontArialStyleWhiteId_, + .halign = ALIGN_CENTER + } + }; + + headerText_.setBounds(headerTextBounds); + headerText_.setStyle(headerTextStyle); + headerText_.setData(headerTextString); + scrollWidget_.addWidget(&headerText_); + + const ImageWidgetStyle imgDragonStyle = { + .image = { + .sprite = logoLibDragon_, + .spriteBounds = Rectangle{0, 0, imgDragonBounds.width, imgDragonBounds.height} + } + }; + + imgDragonWidget_.setBounds(imgDragonBounds); + imgDragonWidget_.setStyle(imgDragonStyle); + scrollWidget_.addWidget(&imgDragonWidget_); + + const ImageWidgetStyle imgBulbaStyle = { + .image = { + .sprite = logoBulbagarden_, + .spriteBounds = Rectangle{0, 0, imgBulbagardenBounds.width, imgBulbagardenBounds.height} + } + }; + + imgBulbagardenWidget_.setBounds(imgBulbagardenBounds); + imgBulbagardenWidget_.setStyle(imgBulbaStyle); + scrollWidget_.addWidget(&imgBulbagardenWidget_); + + + const ImageWidgetStyle imgRetroGameMechanicsExplainedStyle = { + .image = { + .sprite = logoRetroGameMechanicsExplained_, + .spriteBounds = Rectangle{0, 0, imgRetroGameMechanicsExplainedBounds.width, imgRetroGameMechanicsExplainedBounds.height} + } + }; + + imgRetroGameMechanicsExplained_.setBounds(imgRetroGameMechanicsExplainedBounds); + imgRetroGameMechanicsExplained_.setStyle(imgRetroGameMechanicsExplainedStyle); + scrollWidget_.addWidget(&imgRetroGameMechanicsExplained_); + + const ImageWidgetStyle imgDataCrystalStyle = { + .image = { + .sprite = logoDataCrystal_, + .spriteBounds = Rectangle{0, 0, imgDataCrystalBounds.width, imgDataCrystalBounds.height} + } + }; + + imgDataCrystal_.setBounds(imgDataCrystalBounds); + imgDataCrystal_.setStyle(imgDataCrystalStyle); + scrollWidget_.addWidget(&imgDataCrystal_); + + dataCrystalText_.setBounds(dataCrystalTextBounds); + dataCrystalText_.setStyle(commonLeftAlignedTextStyle); + dataCrystalText_.setData("Datacrystal"); + scrollWidget_.addWidget(&dataCrystalText_); + + const ImageWidgetStyle imgPKHEXStyle = { + .image = { + .sprite = logoPKHEX_, + .spriteBounds = Rectangle{0, 0, imgPKHEXBounds.width, imgPKHEXBounds.height} + } + }; + + imgPKHEX_.setBounds(imgPKHEXBounds); + imgPKHEX_.setStyle(imgPKHEXStyle); + scrollWidget_.addWidget(&imgPKHEX_); + + PKHEXText_.setBounds(PKHEXTextBounds); + PKHEXText_.setStyle(commonLeftAlignedTextStyle); + PKHEXText_.setData("PKHeX"); + scrollWidget_.addWidget(&PKHEXText_); + + pretPokeCrystalText_.setBounds(pretPokeCrystalTextBounds); + pretPokeCrystalText_.setStyle(commonLeftAlignedTextStyle); + pretPokeCrystalText_.setData("github.com/pret/pokecrystal"); + scrollWidget_.addWidget(&pretPokeCrystalText_); + + const ImageWidgetStyle imgGBDevIOStyle = { + .image = { + .sprite = logoGBDevIO_, + .spriteBounds = Rectangle{0, 0, imgGBDevIoBounds.width, imgGBDevIoBounds.height} + } + }; + + imgGBDevIO_.setBounds(imgGBDevIoBounds); + imgGBDevIO_.setStyle(imgGBDevIOStyle); + scrollWidget_.addWidget(&imgGBDevIO_); + + gbDevIOText_.setBounds(gbDevIOTextBounds); + gbDevIOText_.setStyle(commonLeftAlignedTextStyle); + gbDevIOText_.setData("gbdev.io"); + scrollWidget_.addWidget(&gbDevIOText_); + + const ImageWidgetStyle imgNESDevWikiStyle = { + .image = { + .sprite = logoNESDevWiki_, + .spriteBounds = Rectangle{0, 0, imgNESDevWikiBounds.width, imgNESDevWikiBounds.height} + } + }; + + imgNESDevWiki_.setBounds(imgNESDevWikiBounds); + imgNESDevWiki_.setStyle(imgNESDevWikiStyle); + scrollWidget_.addWidget(&imgNESDevWiki_); + + otherCreditsText_.setBounds(otherCreditsTextBounds); + otherCreditsText_.setStyle(commonCenterAlignedTextStyle); + otherCreditsText_.setData(otherCreditsString); + scrollWidget_.addWidget(&otherCreditsText_); + + setFocusChain(&scrollFocusSegment_); +} + +void AboutScene::destroy() +{ + sprite_free(logoLibDragon_); + logoLibDragon_ = nullptr; + sprite_free(logoBulbagarden_); + logoBulbagarden_ = nullptr; + sprite_free(logoRetroGameMechanicsExplained_); + logoRetroGameMechanicsExplained_ = nullptr; + sprite_free(logoDataCrystal_); + logoDataCrystal_ = nullptr; + sprite_free(logoPKHEX_); + logoPKHEX_ = nullptr; + sprite_free(logoGBDevIO_); + logoGBDevIO_ = nullptr; + sprite_free(logoNESDevWiki_); + logoNESDevWiki_ = nullptr; +} + +bool AboutScene::handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs) +{ + if(AbstractUIScene::handleUserInput(port, inputs)) + { + return true; + } + + if(inputs.btn.b && !bButtonPressed_) + { + bButtonPressed_ = true; + return true; + } + else if(!inputs.btn.b && bButtonPressed_) + { + deps_.sceneManager.goBackToPreviousScene(); + return true; + } + return false; +} + +void AboutScene::render(RDPQGraphics& gfx, const Rectangle& sceneBounds) +{ + scrollWidget_.render(gfx, sceneBounds); +} \ No newline at end of file diff --git a/src/scenes/MenuScene.cpp b/src/scenes/MenuScene.cpp index 96afdc0..fcee981 100755 --- a/src/scenes/MenuScene.cpp +++ b/src/scenes/MenuScene.cpp @@ -90,13 +90,13 @@ bool MenuScene::handleUserInput(joypad_port_t port, const joypad_inputs_t& input return true; } - if(inputs.btn.b) + if(inputs.btn.b && !bButtonPressed_) { // we will only handle b button release. bButtonPressed_ = true; return true; } - else if(bButtonPressed_) + else if(!inputs.btn.b && bButtonPressed_) { // b button release occurred. Switch back to previous scene. bButtonPressed_ = false; diff --git a/src/scenes/SceneManager.cpp b/src/scenes/SceneManager.cpp index b87a96b..25dea55 100755 --- a/src/scenes/SceneManager.cpp +++ b/src/scenes/SceneManager.cpp @@ -1,6 +1,7 @@ #include "scenes/SceneManager.h" #include "scenes/TestScene.h" #include "scenes/StatsScene.h" +#include "scenes/AboutScene.h" #include "scenes/InitTransferPakScene.h" #include "scenes/DistributionPokemonListScene.h" @@ -135,6 +136,9 @@ void SceneManager::loadScene() case SceneType::TEST: scene_ = new TestScene(sceneDeps_, newSceneContext_); break; + case SceneType::ABOUT: + scene_ = new AboutScene(sceneDeps_, newSceneContext_); + break; default: break; } diff --git a/src/scenes/TestScene.cpp b/src/scenes/TestScene.cpp index 0b1fd9e..82cb81c 100755 --- a/src/scenes/TestScene.cpp +++ b/src/scenes/TestScene.cpp @@ -62,14 +62,12 @@ void TestScene::init() const Dimensions pokeballDimensions = {.width = pokeballSprite_->width, .height = pokeballSprite_->height}; TextWidgetStyle type1Style = { - .size = {textDimensions.width, textDimensions.height}, .renderSettingsNotFocused = { .fontId = fontId } }; ImageWidgetStyle type2Style = { - .size = oakDimensions, .image = { .sprite = oakSprite_, .spriteBounds = {0, 0, oakDimensions.width, oakDimensions.height} @@ -77,7 +75,6 @@ void TestScene::init() }; ImageWidgetStyle type3Style = { - .size = pokeballDimensions, .image = { .sprite = pokeballSprite_, .spriteBounds = {0, 0, pokeballDimensions.width, pokeballDimensions.height} diff --git a/src/widget/ImageWidget.cpp b/src/widget/ImageWidget.cpp index 27507a9..7c07dcc 100644 --- a/src/widget/ImageWidget.cpp +++ b/src/widget/ImageWidget.cpp @@ -57,7 +57,10 @@ void ImageWidget::setBounds(const Rectangle& bounds) Dimensions ImageWidget::getSize() const { - return style_.size; + return Dimensions{ + .width = bounds_.width, + .height = bounds_.height + }; } void ImageWidget::setConfirmAction(void (*onConfirmAction)(void*), void* context) diff --git a/src/widget/TextWidget.cpp b/src/widget/TextWidget.cpp index 5e7b135..d4724e6 100644 --- a/src/widget/TextWidget.cpp +++ b/src/widget/TextWidget.cpp @@ -105,5 +105,11 @@ void TextWidget::render(RDPQGraphics& gfx, const Rectangle& parentBounds) TextRenderSettings& renderSettings = (focused_) ? style_.renderSettingsFocused : style_.renderSettingsNotFocused; const Rectangle absoluteBounds = addOffset(bounds_, parentBounds); + + if((style_.backgroundColor_ & 0x1)) + { + gfx.fillRectangle(absoluteBounds, color_from_packed16(style_.backgroundColor_)); + } + gfx.drawText(absoluteBounds, text_, renderSettings); } \ No newline at end of file