settings app

This commit is contained in:
2025-10-12 16:57:40 +02:00
parent c64f03a09f
commit 1b6e9a0f78
6 changed files with 157 additions and 0 deletions

View File

@@ -3,6 +3,7 @@
#include "cardboy/apps/clock_app.hpp" #include "cardboy/apps/clock_app.hpp"
#include "cardboy/apps/gameboy_app.hpp" #include "cardboy/apps/gameboy_app.hpp"
#include "cardboy/apps/menu_app.hpp" #include "cardboy/apps/menu_app.hpp"
#include "cardboy/apps/settings_app.hpp"
#include "cardboy/apps/tetris_app.hpp" #include "cardboy/apps/tetris_app.hpp"
#include "cardboy/backend/esp_backend.hpp" #include "cardboy/backend/esp_backend.hpp"
#include "cardboy/sdk/app_system.hpp" #include "cardboy/sdk/app_system.hpp"
@@ -222,6 +223,7 @@ extern "C" void app_main() {
context.system = &system; context.system = &system;
system.registerApp(apps::createMenuAppFactory()); system.registerApp(apps::createMenuAppFactory());
system.registerApp(apps::createSettingsAppFactory());
system.registerApp(apps::createClockAppFactory()); system.registerApp(apps::createClockAppFactory());
system.registerApp(apps::createTetrisAppFactory()); system.registerApp(apps::createTetrisAppFactory());
system.registerApp(apps::createGameboyAppFactory()); system.registerApp(apps::createGameboyAppFactory());

View File

@@ -14,5 +14,6 @@ target_compile_features(cardboy_apps PUBLIC cxx_std_20)
add_subdirectory(menu) add_subdirectory(menu)
add_subdirectory(clock) add_subdirectory(clock)
add_subdirectory(settings)
add_subdirectory(gameboy) add_subdirectory(gameboy)
add_subdirectory(tetris) add_subdirectory(tetris)

View File

@@ -0,0 +1,9 @@
target_sources(cardboy_apps
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/settings_app.cpp
)
target_include_directories(cardboy_apps
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)

View File

@@ -0,0 +1,13 @@
#pragma once
#include "cardboy/sdk/app_framework.hpp"
#include <memory>
namespace apps {
inline constexpr char kSettingsAppName[] = "Settings";
std::unique_ptr<cardboy::sdk::IAppFactory> createSettingsAppFactory();
} // namespace apps

View File

@@ -0,0 +1,130 @@
#include "cardboy/apps/settings_app.hpp"
#include "cardboy/apps/menu_app.hpp"
#include "cardboy/gfx/font16x8.hpp"
#include "cardboy/sdk/app_framework.hpp"
#include <memory>
#include <string>
#include <string_view>
namespace apps {
namespace {
using cardboy::sdk::AppContext;
using Framebuffer = typename AppContext::Framebuffer;
class SettingsApp final : public cardboy::sdk::IApp {
public:
explicit SettingsApp(AppContext& ctx) : context(ctx), framebuffer(ctx.framebuffer) {}
void onStart() override {
refreshState();
dirty = true;
renderIfNeeded();
}
void handleEvent(const cardboy::sdk::AppEvent& event) override {
if (event.type != cardboy::sdk::AppEventType::Button)
return;
const auto& current = event.button.current;
const auto& previous = event.button.previous;
const bool prevAvailable = buzzerAvailable;
const bool prevMuted = muted;
refreshState();
if (prevAvailable != buzzerAvailable || prevMuted != muted)
dirty = true;
if (current.b && !previous.b) {
context.requestAppSwitchByName(kMenuAppName);
return;
}
const bool togglePressed = (current.a && !previous.a) || (current.select && !previous.select) ||
(current.start && !previous.start);
if (togglePressed)
toggleMute();
renderIfNeeded();
}
private:
AppContext& context;
Framebuffer& framebuffer;
bool buzzerAvailable = false;
bool muted = false;
bool dirty = false;
void refreshState() {
if (auto* buzzer = context.buzzer()) {
buzzerAvailable = true;
muted = buzzer->isMuted();
} else {
buzzerAvailable = false;
muted = false;
}
}
void toggleMute() {
auto* buzzer = context.buzzer();
if (!buzzer)
return;
const bool targetMuted = !muted;
buzzer->setMuted(targetMuted);
muted = buzzer->isMuted();
if (!muted)
buzzer->beepMove();
dirty = true;
}
static void drawCenteredText(Framebuffer& fb, int y, std::string_view text, int scale, int letterSpacing = 1) {
const int width = font16x8::measureText(text, scale, letterSpacing);
const int x = (fb.width() - width) / 2;
font16x8::drawText(fb, x, y, text, scale, true, letterSpacing);
}
void renderIfNeeded() {
if (!dirty)
return;
dirty = false;
framebuffer.frameReady();
framebuffer.clear(false);
drawCenteredText(framebuffer, 24, "SETTINGS", 1, 1);
const int centerY = framebuffer.height() / 2;
if (!buzzerAvailable) {
drawCenteredText(framebuffer, centerY - 12, "BUZZER SERVICE", 1, 1);
drawCenteredText(framebuffer, centerY + 8, "UNAVAILABLE", 1, 1);
} else {
const char* stateText = muted ? "ON" : "OFF";
std::string line = std::string("MUTE: ") + stateText;
drawCenteredText(framebuffer, centerY - 20, line, 2, 0);
drawCenteredText(framebuffer, centerY + 26, "A TOGGLE", 1, 1);
drawCenteredText(framebuffer, centerY + 44, "START/SELECT ALSO", 1, 1);
}
drawCenteredText(framebuffer, framebuffer.height() - 28, "B BACK", 1, 1);
framebuffer.sendFrame();
}
};
class SettingsAppFactory final : public cardboy::sdk::IAppFactory {
public:
const char* name() const override { return kSettingsAppName; }
std::unique_ptr<cardboy::sdk::IApp> create(cardboy::sdk::AppContext& context) override {
return std::make_unique<SettingsApp>(context);
}
};
} // namespace
std::unique_ptr<cardboy::sdk::IAppFactory> createSettingsAppFactory() { return std::make_unique<SettingsAppFactory>(); }
} // namespace apps

View File

@@ -1,6 +1,7 @@
#include "cardboy/apps/clock_app.hpp" #include "cardboy/apps/clock_app.hpp"
#include "cardboy/apps/gameboy_app.hpp" #include "cardboy/apps/gameboy_app.hpp"
#include "cardboy/apps/menu_app.hpp" #include "cardboy/apps/menu_app.hpp"
#include "cardboy/apps/settings_app.hpp"
#include "cardboy/apps/tetris_app.hpp" #include "cardboy/apps/tetris_app.hpp"
#include "cardboy/backend/desktop_backend.hpp" #include "cardboy/backend/desktop_backend.hpp"
#include "cardboy/sdk/app_system.hpp" #include "cardboy/sdk/app_system.hpp"
@@ -19,6 +20,7 @@ int main() {
cardboy::sdk::AppSystem system(context); cardboy::sdk::AppSystem system(context);
system.registerApp(apps::createMenuAppFactory()); system.registerApp(apps::createMenuAppFactory());
system.registerApp(apps::createSettingsAppFactory());
system.registerApp(apps::createClockAppFactory()); system.registerApp(apps::createClockAppFactory());
system.registerApp(apps::createGameboyAppFactory()); system.registerApp(apps::createGameboyAppFactory());
system.registerApp(apps::createTetrisAppFactory()); system.registerApp(apps::createTetrisAppFactory());