Change menu text from gray to white
This commit is contained in:
+102
-50
@@ -16,7 +16,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#ifndef APP_VERSION
|
#ifndef APP_VERSION
|
||||||
#define APP_VERSION "unknown"
|
#define APP_VERSION "dev"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static TextLine renderText(SDL_Renderer *renderer, TTF_Font *font, const char *text, SDL_Color color)
|
static TextLine renderText(SDL_Renderer *renderer, TTF_Font *font, const char *text, SDL_Color color)
|
||||||
@@ -47,12 +47,10 @@ void Home::onPush(AppState &state)
|
|||||||
refreshStatus();
|
refreshStatus();
|
||||||
state.licenseTracker.refresh();
|
state.licenseTracker.refresh();
|
||||||
|
|
||||||
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
|
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
|
||||||
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
|
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
|
||||||
});
|
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
|
||||||
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
|
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
|
||||||
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Home::onResume(AppState &state)
|
void Home::onResume(AppState &state)
|
||||||
@@ -63,12 +61,10 @@ void Home::onResume(AppState &state)
|
|||||||
refreshStatus();
|
refreshStatus();
|
||||||
state.licenseTracker.refresh();
|
state.licenseTracker.refresh();
|
||||||
|
|
||||||
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
|
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
|
||||||
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
|
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
|
||||||
});
|
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
|
||||||
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
|
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
|
||||||
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Home::onPause(AppState &state)
|
void Home::onPause(AppState &state)
|
||||||
@@ -85,15 +81,22 @@ void Home::onPop(AppState &state)
|
|||||||
|
|
||||||
void Home::handleEvent(const SDL_Event &event)
|
void Home::handleEvent(const SDL_Event &event)
|
||||||
{
|
{
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN) {
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN)
|
||||||
if (state_->currentMenuItem == 0) {
|
{
|
||||||
|
if (state_->currentMenuItem == 0)
|
||||||
|
{
|
||||||
// Only a confirmed-valid license unlocks the scroller.
|
// Only a confirmed-valid license unlocks the scroller.
|
||||||
if (state_->licenseTracker.isValid()) {
|
if (state_->licenseTracker.isValid())
|
||||||
|
{
|
||||||
state_->pages.push(*state_, std::make_unique<ScrollerPage>());
|
state_->pages.push(*state_, std::make_unique<ScrollerPage>());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
state_->pages.push(*state_, std::make_unique<LicenseBlockedPage>());
|
state_->pages.push(*state_, std::make_unique<LicenseBlockedPage>());
|
||||||
}
|
}
|
||||||
} else if (state_->currentMenuItem == 1) {
|
}
|
||||||
|
else if (state_->currentMenuItem == 1)
|
||||||
|
{
|
||||||
state_->pages.replace(*state_, std::make_unique<Settings>());
|
state_->pages.replace(*state_, std::make_unique<Settings>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +105,8 @@ void Home::handleEvent(const SDL_Event &event)
|
|||||||
void Home::update(float dt)
|
void Home::update(float dt)
|
||||||
{
|
{
|
||||||
internetRefreshTimer_ -= dt;
|
internetRefreshTimer_ -= dt;
|
||||||
if (internetRefreshTimer_ <= 0.0f) {
|
if (internetRefreshTimer_ <= 0.0f)
|
||||||
|
{
|
||||||
internetRefreshTimer_ = 5.0f;
|
internetRefreshTimer_ = 5.0f;
|
||||||
refreshStatus();
|
refreshStatus();
|
||||||
}
|
}
|
||||||
@@ -133,7 +137,8 @@ void Home::render(SDL_Renderer *renderer)
|
|||||||
SDL_FRect overlay{0, 0, fw, fh};
|
SDL_FRect overlay{0, 0, fw, fh};
|
||||||
SDL_RenderFillRect(renderer, &overlay);
|
SDL_RenderFillRect(renderer, &overlay);
|
||||||
|
|
||||||
if (!title_.texture) return;
|
if (!title_.texture)
|
||||||
|
return;
|
||||||
|
|
||||||
float titleX = (fw - title_.width) / 2.0f;
|
float titleX = (fw - title_.width) / 2.0f;
|
||||||
float titleY = fh / 3.0f - 60.0f;
|
float titleY = fh / 3.0f - 60.0f;
|
||||||
@@ -194,7 +199,8 @@ void Home::render(SDL_Renderer *renderer)
|
|||||||
std::string licenseValue;
|
std::string licenseValue;
|
||||||
SDL_Color licenseColor = footerColor;
|
SDL_Color licenseColor = footerColor;
|
||||||
bool licenseBold = false;
|
bool licenseBold = false;
|
||||||
switch (licenseStatus) {
|
switch (licenseStatus)
|
||||||
|
{
|
||||||
case radiantwave::license::Status::Valid:
|
case radiantwave::license::Status::Valid:
|
||||||
licenseValue = "OK";
|
licenseValue = "OK";
|
||||||
licenseColor = okGreen;
|
licenseColor = okGreen;
|
||||||
@@ -250,23 +256,32 @@ void Home::render(SDL_Renderer *renderer)
|
|||||||
valueColors[1] = licenseColor;
|
valueColors[1] = licenseColor;
|
||||||
valueBold[1] = licenseBold;
|
valueBold[1] = licenseBold;
|
||||||
|
|
||||||
if (footerNames_.size() != names.size()) footerNames_.resize(names.size());
|
if (footerNames_.size() != names.size())
|
||||||
if (footerValues_.size() != values.size()) footerValues_.resize(values.size());
|
footerNames_.resize(names.size());
|
||||||
for (size_t i = 0; i < names.size(); ++i) {
|
if (footerValues_.size() != values.size())
|
||||||
|
footerValues_.resize(values.size());
|
||||||
|
for (size_t i = 0; i < names.size(); ++i)
|
||||||
|
{
|
||||||
footerNames_[i].ensure(renderer, footerFont_, names[i], footerColor);
|
footerNames_[i].ensure(renderer, footerFont_, names[i], footerColor);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < values.size(); ++i) {
|
for (size_t i = 0; i < values.size(); ++i)
|
||||||
if (valueBold[i]) TTF_SetFontStyle(footerFont_, TTF_STYLE_BOLD);
|
{
|
||||||
|
if (valueBold[i])
|
||||||
|
TTF_SetFontStyle(footerFont_, TTF_STYLE_BOLD);
|
||||||
footerValues_[i].ensure(renderer, footerFont_, values[i], valueColors[i],
|
footerValues_[i].ensure(renderer, footerFont_, values[i], valueColors[i],
|
||||||
valueBold[i] ? TTF_STYLE_BOLD : TTF_STYLE_NORMAL);
|
valueBold[i] ? TTF_STYLE_BOLD : TTF_STYLE_NORMAL);
|
||||||
if (valueBold[i]) TTF_SetFontStyle(footerFont_, TTF_STYLE_NORMAL);
|
if (valueBold[i])
|
||||||
|
TTF_SetFontStyle(footerFont_, TTF_STYLE_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
float maxNameW = 0.0f;
|
float maxNameW = 0.0f;
|
||||||
float maxValueW = 0.0f;
|
float maxValueW = 0.0f;
|
||||||
for (size_t i = 0; i < footerNames_.size(); ++i) {
|
for (size_t i = 0; i < footerNames_.size(); ++i)
|
||||||
if (footerNames_[i].width > maxNameW) maxNameW = footerNames_[i].width;
|
{
|
||||||
if (footerValues_[i].width > maxValueW) maxValueW = footerValues_[i].width;
|
if (footerNames_[i].width > maxNameW)
|
||||||
|
maxNameW = footerNames_[i].width;
|
||||||
|
if (footerValues_[i].width > maxValueW)
|
||||||
|
maxValueW = footerValues_[i].width;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedText fourSpaces;
|
CachedText fourSpaces;
|
||||||
@@ -283,11 +298,13 @@ void Home::render(SDL_Renderer *renderer)
|
|||||||
for (size_t i = footerNames_.size(); i-- > 0;)
|
for (size_t i = footerNames_.size(); i-- > 0;)
|
||||||
{
|
{
|
||||||
float h = std::max(footerNames_[i].height, footerValues_[i].height);
|
float h = std::max(footerNames_[i].height, footerValues_[i].height);
|
||||||
if (footerNames_[i].texture) {
|
if (footerNames_[i].texture)
|
||||||
|
{
|
||||||
SDL_FRect dst{rectLeft, lineY - h, footerNames_[i].width, footerNames_[i].height};
|
SDL_FRect dst{rectLeft, lineY - h, footerNames_[i].width, footerNames_[i].height};
|
||||||
SDL_RenderTexture(renderer, footerNames_[i].texture, nullptr, &dst);
|
SDL_RenderTexture(renderer, footerNames_[i].texture, nullptr, &dst);
|
||||||
}
|
}
|
||||||
if (footerValues_[i].texture) {
|
if (footerValues_[i].texture)
|
||||||
|
{
|
||||||
SDL_FRect dst{rectRight - footerValues_[i].width, lineY - h, footerValues_[i].width, footerValues_[i].height};
|
SDL_FRect dst{rectRight - footerValues_[i].width, lineY - h, footerValues_[i].width, footerValues_[i].height};
|
||||||
SDL_RenderTexture(renderer, footerValues_[i].texture, nullptr, &dst);
|
SDL_RenderTexture(renderer, footerValues_[i].texture, nullptr, &dst);
|
||||||
}
|
}
|
||||||
@@ -309,7 +326,8 @@ void Home::createTextures(AppState &state)
|
|||||||
TextLine textWidthRef = renderText(state.renderer, font, "Radiant Wave", white);
|
TextLine textWidthRef = renderText(state.renderer, font, "Radiant Wave", white);
|
||||||
float targetWidth = textWidthRef.width * 1.5f;
|
float targetWidth = textWidthRef.width * 1.5f;
|
||||||
|
|
||||||
if (textWidthRef.texture) SDL_DestroyTexture(textWidthRef.texture);
|
if (textWidthRef.texture)
|
||||||
|
SDL_DestroyTexture(textWidthRef.texture);
|
||||||
|
|
||||||
TTF_CloseFont(font);
|
TTF_CloseFont(font);
|
||||||
|
|
||||||
@@ -338,9 +356,8 @@ void Home::createTextures(AppState &state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Color gray = {180, 180, 180, 255};
|
play_ = renderText(state.renderer, font, "Play", white);
|
||||||
play_ = renderText(state.renderer, font, "Play", gray);
|
settings_ = renderText(state.renderer, font, "Settings", white);
|
||||||
settings_ = renderText(state.renderer, font, "Settings", gray);
|
|
||||||
|
|
||||||
TTF_CloseFont(font);
|
TTF_CloseFont(font);
|
||||||
|
|
||||||
@@ -356,16 +373,26 @@ void Home::createTextures(AppState &state)
|
|||||||
|
|
||||||
footerFont_ = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 20);
|
footerFont_ = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 20);
|
||||||
const std::vector<std::string> footerNames = {
|
const std::vector<std::string> footerNames = {
|
||||||
"Version:", "License:", "Key:", "Email:", "Subscription:", "WiFi:",
|
"Version:",
|
||||||
"Internet:", "Audio:", "Date:", "Time:",
|
"License:",
|
||||||
|
"Key:",
|
||||||
|
"Email:",
|
||||||
|
"Subscription:",
|
||||||
|
"WiFi:",
|
||||||
|
"Internet:",
|
||||||
|
"Audio:",
|
||||||
|
"Date:",
|
||||||
|
"Time:",
|
||||||
};
|
};
|
||||||
footerNames_.clear();
|
footerNames_.clear();
|
||||||
footerValues_.clear();
|
footerValues_.clear();
|
||||||
footerNames_.resize(footerNames.size());
|
footerNames_.resize(footerNames.size());
|
||||||
footerValues_.resize(footerNames.size());
|
footerValues_.resize(footerNames.size());
|
||||||
SDL_Color footerColor = {200, 200, 200, 255};
|
SDL_Color footerColor = {200, 200, 200, 255};
|
||||||
if (footerFont_) {
|
if (footerFont_)
|
||||||
for (size_t i = 0; i < footerNames.size(); ++i) {
|
{
|
||||||
|
for (size_t i = 0; i < footerNames.size(); ++i)
|
||||||
|
{
|
||||||
footerNames_[i].ensure(state.renderer, footerFont_, footerNames[i], footerColor);
|
footerNames_[i].ensure(state.renderer, footerFont_, footerNames[i], footerColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -373,20 +400,43 @@ void Home::createTextures(AppState &state)
|
|||||||
|
|
||||||
void Home::destroyTextures()
|
void Home::destroyTextures()
|
||||||
{
|
{
|
||||||
if (bg_.texture) { SDL_DestroyTexture(bg_.texture); bg_.texture = nullptr; }
|
if (bg_.texture)
|
||||||
if (title_.texture) { SDL_DestroyTexture(title_.texture); title_.texture = nullptr; }
|
{
|
||||||
if (play_.texture) { SDL_DestroyTexture(play_.texture); play_.texture = nullptr; }
|
SDL_DestroyTexture(bg_.texture);
|
||||||
if (settings_.texture) { SDL_DestroyTexture(settings_.texture); settings_.texture = nullptr; }
|
bg_.texture = nullptr;
|
||||||
for (auto& t : footerNames_) t.destroy();
|
}
|
||||||
for (auto& t : footerValues_) t.destroy();
|
if (title_.texture)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(title_.texture);
|
||||||
|
title_.texture = nullptr;
|
||||||
|
}
|
||||||
|
if (play_.texture)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(play_.texture);
|
||||||
|
play_.texture = nullptr;
|
||||||
|
}
|
||||||
|
if (settings_.texture)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(settings_.texture);
|
||||||
|
settings_.texture = nullptr;
|
||||||
|
}
|
||||||
|
for (auto &t : footerNames_)
|
||||||
|
t.destroy();
|
||||||
|
for (auto &t : footerValues_)
|
||||||
|
t.destroy();
|
||||||
footerNames_.clear();
|
footerNames_.clear();
|
||||||
footerValues_.clear();
|
footerValues_.clear();
|
||||||
if (footerFont_) { TTF_CloseFont(footerFont_); footerFont_ = nullptr; }
|
if (footerFont_)
|
||||||
|
{
|
||||||
|
TTF_CloseFont(footerFont_);
|
||||||
|
footerFont_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Home::refreshStatus()
|
void Home::refreshStatus()
|
||||||
{
|
{
|
||||||
if (!state_) return;
|
if (!state_)
|
||||||
|
return;
|
||||||
email_ = state_->db.getKV(radiantwave::db::KV_EMAIL_ADDRESS);
|
email_ = state_->db.getKV(radiantwave::db::KV_EMAIL_ADDRESS);
|
||||||
license_ = state_->db.getKV(radiantwave::db::KV_LICENSE_KEY);
|
license_ = state_->db.getKV(radiantwave::db::KV_LICENSE_KEY);
|
||||||
dateFormat_ = state_->db.getKV("date_format", radiantwave::datetime::DEFAULT_DATE_FORMAT);
|
dateFormat_ = state_->db.getKV("date_format", radiantwave::datetime::DEFAULT_DATE_FORMAT);
|
||||||
@@ -401,7 +451,8 @@ void Home::syncProclamationsIfEmpty(AppState &state)
|
|||||||
// Proclamation options. Skipped once the database has content so a
|
// Proclamation options. Skipped once the database has content so a
|
||||||
// blocking sync never runs on every Home push. The API call is also
|
// blocking sync never runs on every Home push. The API call is also
|
||||||
// skipped when the database is closed (fallback path in provisioning).
|
// skipped when the database is closed (fallback path in provisioning).
|
||||||
if (state.db.isOpen() && state.db.getActiveProclamations().empty()) {
|
if (state.db.isOpen() && state.db.getActiveProclamations().empty())
|
||||||
|
{
|
||||||
// TODO(portal #4/#5): once the portal exposes color palettes, sync them
|
// TODO(portal #4/#5): once the portal exposes color palettes, sync them
|
||||||
// alongside proclamations here (sync::syncColorPalettesFromApi) so Play's
|
// alongside proclamations here (sync::syncColorPalettesFromApi) so Play's
|
||||||
// scroller has portal colors from the very first run.
|
// scroller has portal colors from the very first run.
|
||||||
@@ -411,7 +462,8 @@ void Home::syncProclamationsIfEmpty(AppState &state)
|
|||||||
|
|
||||||
std::string Home::audioStatus() const
|
std::string Home::audioStatus() const
|
||||||
{
|
{
|
||||||
if (!state_) return "Idle";
|
if (!state_)
|
||||||
|
return "Idle";
|
||||||
std::string status = state_->audioDownloader.statusString();
|
std::string status = state_->audioDownloader.statusString();
|
||||||
return status.empty() ? "Idle" : status;
|
return status.empty() ? "Idle" : status;
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-47
@@ -14,7 +14,8 @@
|
|||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
constexpr int MENU_ITEM_COUNT = 9;
|
constexpr int MENU_ITEM_COUNT = 9;
|
||||||
// 0 = WiFi Setup, 1 = Audio Options, 2 = Time Zone Setup, 3 = Proclamations,
|
// 0 = WiFi Setup, 1 = Audio Options, 2 = Time Zone Setup, 3 = Proclamations,
|
||||||
@@ -40,12 +41,10 @@ void Settings::onPush(AppState& state)
|
|||||||
TTF_Init();
|
TTF_Init();
|
||||||
createTextures(state);
|
createTextures(state);
|
||||||
|
|
||||||
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
|
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
|
||||||
selectedItem_ = (selectedItem_ - 1 + MENU_ITEM_COUNT) % MENU_ITEM_COUNT;
|
{ selectedItem_ = (selectedItem_ - 1 + MENU_ITEM_COUNT) % MENU_ITEM_COUNT; });
|
||||||
});
|
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
|
||||||
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
|
{ selectedItem_ = (selectedItem_ + 1) % MENU_ITEM_COUNT; });
|
||||||
selectedItem_ = (selectedItem_ + 1) % MENU_ITEM_COUNT;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::onResume(AppState &state)
|
void Settings::onResume(AppState &state)
|
||||||
@@ -53,12 +52,10 @@ void Settings::onResume(AppState& state)
|
|||||||
state_ = &state;
|
state_ = &state;
|
||||||
createTextures(state);
|
createTextures(state);
|
||||||
|
|
||||||
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
|
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
|
||||||
selectedItem_ = (selectedItem_ - 1 + MENU_ITEM_COUNT) % MENU_ITEM_COUNT;
|
{ selectedItem_ = (selectedItem_ - 1 + MENU_ITEM_COUNT) % MENU_ITEM_COUNT; });
|
||||||
});
|
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
|
||||||
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
|
{ selectedItem_ = (selectedItem_ + 1) % MENU_ITEM_COUNT; });
|
||||||
selectedItem_ = (selectedItem_ + 1) % MENU_ITEM_COUNT;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::onPause(AppState &state)
|
void Settings::onPause(AppState &state)
|
||||||
@@ -75,27 +72,51 @@ void Settings::onPop(AppState& state)
|
|||||||
|
|
||||||
void Settings::handleEvent(const SDL_Event &event)
|
void Settings::handleEvent(const SDL_Event &event)
|
||||||
{
|
{
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN) {
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN)
|
||||||
switch (selectedItem_) {
|
{
|
||||||
case 0: state_->pages.push(*state_, std::make_unique<WiFiSetupPage>()); break;
|
switch (selectedItem_)
|
||||||
case 1: state_->pages.push(*state_, std::make_unique<AudioSettingsPage>()); break;
|
{
|
||||||
case 2: state_->pages.push(*state_, std::make_unique<TimeZonePage>()); break;
|
case 0:
|
||||||
|
state_->pages.push(*state_, std::make_unique<WiFiSetupPage>());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state_->pages.push(*state_, std::make_unique<AudioSettingsPage>());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state_->pages.push(*state_, std::make_unique<TimeZonePage>());
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// The Proclamation list is license-gated like Play.
|
// The Proclamation list is license-gated like Play.
|
||||||
if (state_->licenseTracker.isValid()) {
|
if (state_->licenseTracker.isValid())
|
||||||
|
{
|
||||||
state_->pages.push(*state_, std::make_unique<ProclamationOptionsPage>());
|
state_->pages.push(*state_, std::make_unique<ProclamationOptionsPage>());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
state_->pages.push(*state_, std::make_unique<LicenseBlockedPage>());
|
state_->pages.push(*state_, std::make_unique<LicenseBlockedPage>());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: state_->pages.push(*state_, std::make_unique<EmailAddressPage>()); break;
|
case 4:
|
||||||
case 5: state_->pages.push(*state_, std::make_unique<LicenseKeyPage>()); break;
|
state_->pages.push(*state_, std::make_unique<EmailAddressPage>());
|
||||||
case 6: state_->pages.push(*state_, std::make_unique<DateFormatPage>()); break;
|
break;
|
||||||
case 7: state_->pages.push(*state_, std::make_unique<LogViewerPage>()); break;
|
case 5:
|
||||||
case 8: state_->pages.replace(*state_, std::make_unique<Home>()); break;
|
state_->pages.push(*state_, std::make_unique<LicenseKeyPage>());
|
||||||
default: break;
|
break;
|
||||||
|
case 6:
|
||||||
|
state_->pages.push(*state_, std::make_unique<DateFormatPage>());
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
state_->pages.push(*state_, std::make_unique<LogViewerPage>());
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
state_->pages.replace(*state_, std::make_unique<Home>());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (event.type == SDL_EVENT_KEY_DOWN && (event.key.key == SDLK_ESCAPE || event.key.key == SDLK_TAB)) {
|
}
|
||||||
|
else if (event.type == SDL_EVENT_KEY_DOWN && (event.key.key == SDLK_ESCAPE || event.key.key == SDLK_TAB))
|
||||||
|
{
|
||||||
state_->pages.replace(*state_, std::make_unique<Home>());
|
state_->pages.replace(*state_, std::make_unique<Home>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +133,8 @@ void Settings::render(SDL_Renderer* renderer)
|
|||||||
float fh = static_cast<float>(winH);
|
float fh = static_cast<float>(winH);
|
||||||
|
|
||||||
// 1. Logo Background Image
|
// 1. Logo Background Image
|
||||||
if (bgTexture_) {
|
if (bgTexture_)
|
||||||
|
{
|
||||||
float scaleX = fw / bgWidth_;
|
float scaleX = fw / bgWidth_;
|
||||||
float scaleY = fh / bgHeight_;
|
float scaleY = fh / bgHeight_;
|
||||||
float scale = std::min(scaleX, scaleY);
|
float scale = std::min(scaleX, scaleY);
|
||||||
@@ -132,7 +154,8 @@ void Settings::render(SDL_Renderer* renderer)
|
|||||||
|
|
||||||
// 3. Title Text
|
// 3. Title Text
|
||||||
float titleY = 60.0f;
|
float titleY = 60.0f;
|
||||||
if (titleTexture_) {
|
if (titleTexture_)
|
||||||
|
{
|
||||||
float x = (fw - titleWidth_) / 2.0f;
|
float x = (fw - titleWidth_) / 2.0f;
|
||||||
SDL_FRect dst{x, titleY, titleWidth_, titleHeight_};
|
SDL_FRect dst{x, titleY, titleWidth_, titleHeight_};
|
||||||
SDL_RenderTexture(renderer, titleTexture_, nullptr, &dst);
|
SDL_RenderTexture(renderer, titleTexture_, nullptr, &dst);
|
||||||
@@ -140,7 +163,8 @@ void Settings::render(SDL_Renderer* renderer)
|
|||||||
|
|
||||||
// Compute bounding box for all menu items
|
// Compute bounding box for all menu items
|
||||||
float maxWidth = 0.0f;
|
float maxWidth = 0.0f;
|
||||||
for (const auto& item : items_) {
|
for (const auto &item : items_)
|
||||||
|
{
|
||||||
maxWidth = std::max(maxWidth, item.width);
|
maxWidth = std::max(maxWidth, item.width);
|
||||||
}
|
}
|
||||||
float margin = 12.0f; // 12px vertical margin rule
|
float margin = 12.0f; // 12px vertical margin rule
|
||||||
@@ -151,9 +175,11 @@ void Settings::render(SDL_Renderer* renderer)
|
|||||||
// Start menu list exactly 24 pixels below title text
|
// Start menu list exactly 24 pixels below title text
|
||||||
float currentY = titleY + titleHeight_ + 24.0f;
|
float currentY = titleY + titleHeight_ + 24.0f;
|
||||||
|
|
||||||
for (auto& item : items_) {
|
for (auto &item : items_)
|
||||||
|
{
|
||||||
item.y = currentY;
|
item.y = currentY;
|
||||||
if (item.texture) {
|
if (item.texture)
|
||||||
|
{
|
||||||
SDL_FRect dst{sharedX, item.y, item.width, item.height};
|
SDL_FRect dst{sharedX, item.y, item.width, item.height};
|
||||||
SDL_RenderTexture(renderer, item.texture, nullptr, &dst);
|
SDL_RenderTexture(renderer, item.texture, nullptr, &dst);
|
||||||
}
|
}
|
||||||
@@ -161,9 +187,11 @@ void Settings::render(SDL_Renderer* renderer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 6px Underline for selected item occupying half of the 12px margin space
|
// 6px Underline for selected item occupying half of the 12px margin space
|
||||||
if (selectedItem_ >= 0 && selectedItem_ < static_cast<int>(items_.size())) {
|
if (selectedItem_ >= 0 && selectedItem_ < static_cast<int>(items_.size()))
|
||||||
|
{
|
||||||
const auto &item = items_[selectedItem_];
|
const auto &item = items_[selectedItem_];
|
||||||
if (item.texture) {
|
if (item.texture)
|
||||||
|
{
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
SDL_FRect line{sharedX, item.y + item.height + 2.0f, item.width, 6.0f};
|
SDL_FRect line{sharedX, item.y + item.height + 2.0f, item.width, 6.0f};
|
||||||
SDL_RenderFillRect(renderer, &line);
|
SDL_RenderFillRect(renderer, &line);
|
||||||
@@ -177,7 +205,8 @@ void Settings::createTextures(AppState& state)
|
|||||||
|
|
||||||
// Background Image
|
// Background Image
|
||||||
SDL_Surface *bgSurface = IMG_Load("assets/images/RWT-Circular-Color-ForOnDark-NoText.png");
|
SDL_Surface *bgSurface = IMG_Load("assets/images/RWT-Circular-Color-ForOnDark-NoText.png");
|
||||||
if (bgSurface) {
|
if (bgSurface)
|
||||||
|
{
|
||||||
bgTexture_ = SDL_CreateTextureFromSurface(state.renderer, bgSurface);
|
bgTexture_ = SDL_CreateTextureFromSurface(state.renderer, bgSurface);
|
||||||
bgWidth_ = static_cast<float>(bgSurface->w);
|
bgWidth_ = static_cast<float>(bgSurface->w);
|
||||||
bgHeight_ = static_cast<float>(bgSurface->h);
|
bgHeight_ = static_cast<float>(bgSurface->h);
|
||||||
@@ -185,12 +214,14 @@ void Settings::createTextures(AppState& state)
|
|||||||
SDL_SetTextureAlphaMod(bgTexture_, 204);
|
SDL_SetTextureAlphaMod(bgTexture_, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_Color white = {255, 255, 255, 255};
|
||||||
// Title Font
|
// Title Font
|
||||||
TTF_Font *fontLarge = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 64);
|
TTF_Font *fontLarge = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 64);
|
||||||
if (fontLarge) {
|
if (fontLarge)
|
||||||
SDL_Color white = {255, 255, 255, 255};
|
{
|
||||||
SDL_Surface *surface = TTF_RenderText_Blended(fontLarge, "Settings", 0, white);
|
SDL_Surface *surface = TTF_RenderText_Blended(fontLarge, "Settings", 0, white);
|
||||||
if (surface) {
|
if (surface)
|
||||||
|
{
|
||||||
titleTexture_ = SDL_CreateTextureFromSurface(state.renderer, surface);
|
titleTexture_ = SDL_CreateTextureFromSurface(state.renderer, surface);
|
||||||
titleWidth_ = static_cast<float>(surface->w);
|
titleWidth_ = static_cast<float>(surface->w);
|
||||||
titleHeight_ = static_cast<float>(surface->h);
|
titleHeight_ = static_cast<float>(surface->h);
|
||||||
@@ -201,17 +232,19 @@ void Settings::createTextures(AppState& state)
|
|||||||
|
|
||||||
// Item Font
|
// Item Font
|
||||||
TTF_Font *fontItem = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 36);
|
TTF_Font *fontItem = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 36);
|
||||||
if (!fontItem) return;
|
if (!fontItem)
|
||||||
|
return;
|
||||||
|
|
||||||
SDL_Color gray = {200, 200, 200, 255};
|
|
||||||
items_.reserve(MENU_ITEM_COUNT);
|
items_.reserve(MENU_ITEM_COUNT);
|
||||||
|
|
||||||
for (int i = 0; i < MENU_ITEM_COUNT; ++i) {
|
for (int i = 0; i < MENU_ITEM_COUNT; ++i)
|
||||||
|
{
|
||||||
MenuItem item;
|
MenuItem item;
|
||||||
item.label = MENU_LABELS[i];
|
item.label = MENU_LABELS[i];
|
||||||
|
|
||||||
SDL_Surface* surface = TTF_RenderText_Blended(fontItem, MENU_LABELS[i], 0, gray);
|
SDL_Surface *surface = TTF_RenderText_Blended(fontItem, MENU_LABELS[i], 0, white);
|
||||||
if (surface) {
|
if (surface)
|
||||||
|
{
|
||||||
item.texture = SDL_CreateTextureFromSurface(state.renderer, surface);
|
item.texture = SDL_CreateTextureFromSurface(state.renderer, surface);
|
||||||
item.width = static_cast<float>(surface->w);
|
item.width = static_cast<float>(surface->w);
|
||||||
item.height = static_cast<float>(surface->h);
|
item.height = static_cast<float>(surface->h);
|
||||||
@@ -225,10 +258,23 @@ void Settings::createTextures(AppState& state)
|
|||||||
|
|
||||||
void Settings::destroyTextures()
|
void Settings::destroyTextures()
|
||||||
{
|
{
|
||||||
if (bgTexture_) { SDL_DestroyTexture(bgTexture_); bgTexture_ = nullptr; }
|
if (bgTexture_)
|
||||||
if (titleTexture_) { SDL_DestroyTexture(titleTexture_); titleTexture_ = nullptr; }
|
{
|
||||||
for (auto& item : items_) {
|
SDL_DestroyTexture(bgTexture_);
|
||||||
if (item.texture) { SDL_DestroyTexture(item.texture); item.texture = nullptr; }
|
bgTexture_ = nullptr;
|
||||||
|
}
|
||||||
|
if (titleTexture_)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(titleTexture_);
|
||||||
|
titleTexture_ = nullptr;
|
||||||
|
}
|
||||||
|
for (auto &item : items_)
|
||||||
|
{
|
||||||
|
if (item.texture)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(item.texture);
|
||||||
|
item.texture = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
items_.clear();
|
items_.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user