LCOV - code coverage report
Current view: top level - src/gui/theme - theme.h (source / functions) Coverage Total Hit
Test: merged.info Lines: 100.0 % 89 89
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 12 12

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <imgui.h>
       4              : 
       5              : #include <cmath>
       6              : #include <cstdio>
       7              : #include <cstring>
       8              : #include <string>
       9              : 
      10              : namespace Amplitron {
      11              : 
      12              : // ============================================================
      13              : // AMPLITRON Design System
      14              : // Color palette extracted from icon.svg
      15              : // Warm vintage amp aesthetic: dark browns, golds, muted metals
      16              : // ============================================================
      17              : 
      18              : namespace Theme {
      19              : 
      20              : // --- Brand ---
      21              : constexpr const char* APP_NAME = "Amplitron";
      22              : constexpr const char* WINDOW_TITLE = "Amplitron - Guitar Amp Simulator";
      23              : 
      24              : // --- Core Palette (from icon.svg) ---
      25              : // Cabinet / background tones
      26              : constexpr ImU32 BG_DARKEST = IM_COL32(20, 18, 16, 255);  // #141210  app bg
      27              : constexpr ImU32 BG_DARK = IM_COL32(28, 26, 24, 255);     // #1c1a18  cabinet body
      28              : constexpr ImU32 BG_PANEL = IM_COL32(42, 38, 32, 255);    // #2a2620  top panel
      29              : constexpr ImU32 BG_SURFACE = IM_COL32(50, 46, 38, 255);  // #322e26  elevated surfaces
      30              : constexpr ImU32 BG_GRILLE = IM_COL32(26, 18, 16, 255);   // #1a1210  speaker grille
      31              : 
      32              : // Metal / borders
      33              : constexpr ImU32 BORDER_DARK = IM_COL32(58, 54, 48, 255);   // #3a3630  subtle border
      34              : constexpr ImU32 BORDER_MID = IM_COL32(68, 68, 68, 255);    // #444444  medium border
      35              : constexpr ImU32 BORDER_LIGHT = IM_COL32(85, 85, 85, 255);  // #555555  bright border
      36              : constexpr ImU32 METAL_STRIP = IM_COL32(61, 56, 48, 255);   // #3d3830  brushed metal
      37              : 
      38              : // Gold accent (brand color — knob pointers, highlights, brand text)
      39              : constexpr ImU32 ACCENT_GOLD = IM_COL32(200, 168, 74, 255);       // #c8a84a
      40              : constexpr ImU32 ACCENT_GOLD_DIM = IM_COL32(160, 130, 55, 255);   // dimmed gold
      41              : constexpr ImU32 ACCENT_GOLD_HOT = IM_COL32(230, 200, 100, 255);  // bright gold
      42              : 
      43              : // Power LED green
      44              : constexpr ImU32 LED_GREEN = IM_COL32(45, 110, 45, 255);         // #2d6e2d
      45              : constexpr ImU32 LED_GREEN_GLOW = IM_COL32(127, 255, 127, 200);  // #7fff7f
      46              : 
      47              : // Text
      48              : constexpr ImU32 TEXT_PRIMARY = IM_COL32(220, 215, 205, 255);    // warm white
      49              : constexpr ImU32 TEXT_SECONDARY = IM_COL32(136, 136, 136, 255);  // #888
      50              : constexpr ImU32 TEXT_DIM = IM_COL32(102, 102, 102, 255);        // #666
      51              : constexpr ImU32 TEXT_MUTED = IM_COL32(80, 76, 68, 255);         // very dim
      52              : 
      53              : // Knobs (from icon: dark circles with gold pointers)
      54              : constexpr ImU32 KNOB_BG = IM_COL32(26, 26, 26, 255);         // #1a1a1a
      55              : constexpr ImU32 KNOB_RING = IM_COL32(34, 34, 34, 255);       // #222222
      56              : constexpr ImU32 KNOB_FACE = IM_COL32(42, 42, 42, 255);       // #2a2a2a
      57              : constexpr ImU32 KNOB_HOVER = IM_COL32(55, 52, 46, 255);      // warm hover
      58              : constexpr ImU32 KNOB_ACTIVE = IM_COL32(68, 64, 56, 255);     // warm active
      59              : constexpr ImU32 KNOB_TRACK_OFF = IM_COL32(36, 34, 30, 255);  // unfilled arc
      60              : 
      61              : // Status
      62              : constexpr ImU32 STATUS_LIVE = IM_COL32(50, 200, 80, 255);
      63              : constexpr ImU32 STATUS_STOPPED = IM_COL32(200, 50, 50, 255);
      64              : constexpr ImU32 STATUS_REC = IM_COL32(255, 40, 40, 255);
      65              : 
      66              : // Meters
      67              : constexpr ImU32 METER_BG = IM_COL32(26, 22, 18, 255);
      68              : constexpr ImU32 METER_GREEN = IM_COL32(50, 180, 70, 255);
      69              : constexpr ImU32 METER_YELLOW = IM_COL32(210, 170, 50, 255);
      70              : constexpr ImU32 METER_RED = IM_COL32(220, 50, 40, 255);
      71              : 
      72              : // Signal chain
      73              : constexpr ImU32 CHAIN_LINE = IM_COL32(58, 54, 48, 150);     // matches border
      74              : constexpr ImU32 CHAIN_JACK = IM_COL32(160, 150, 130, 255);  // warm metal
      75              : constexpr ImU32 CHAIN_DOT = IM_COL32(120, 110, 95, 200);
      76              : 
      77              : // Pedal chrome
      78              : constexpr ImU32 PEDAL_SHADOW = IM_COL32(0, 0, 0, 120);
      79              : constexpr ImU32 PEDAL_BORDER = IM_COL32(70, 66, 58, 255);  // warm grey
      80              : constexpr ImU32 PEDAL_PLATE = IM_COL32(46, 42, 36, 200);   // top plate
      81              : constexpr ImU32 SWITCH_BODY = IM_COL32(38, 36, 32, 255);
      82              : constexpr ImU32 SWITCH_RING = IM_COL32(68, 64, 56, 255);
      83              : constexpr ImU32 SWITCH_ACTIVE = IM_COL32(72, 65, 42, 255);  // gold-tinted = enabled
      84              : constexpr ImU32 SWITCH_IDLE = IM_COL32(28, 26, 22, 255);    // dark = bypassed
      85              : constexpr ImU32 LED_OFF = IM_COL32(36, 34, 30, 255);
      86              : constexpr ImU32 PEDAL_BYPASS_OVERLAY = IM_COL32(0, 0, 0, 90);  // dim overlay when bypassed
      87              : 
      88              : // --- ImVec4 helpers (for ImGui style and TextColored) ---
      89           80 : inline ImVec4 Gold() { return ImVec4(0.78f, 0.66f, 0.29f, 1.0f); }
      90            3 : inline ImVec4 GoldDim() { return ImVec4(0.63f, 0.51f, 0.22f, 1.0f); }
      91           73 : inline ImVec4 GoldHot() { return ImVec4(0.90f, 0.78f, 0.39f, 1.0f); }
      92          183 : inline ImVec4 TextPrimary() { return ImVec4(0.86f, 0.84f, 0.80f, 1.0f); }
      93          789 : inline ImVec4 TextSecondary() { return ImVec4(0.53f, 0.53f, 0.53f, 1.0f); }
      94          885 : inline ImVec4 TextDim() { return ImVec4(0.40f, 0.40f, 0.40f, 1.0f); }
      95           11 : inline ImVec4 Live() { return ImVec4(0.20f, 0.78f, 0.31f, 1.0f); }
      96            8 : inline ImVec4 Stopped() { return ImVec4(0.78f, 0.20f, 0.20f, 1.0f); }
      97           28 : inline ImVec4 RecBlink(float t) {
      98           28 :     float a = (std::sin(t * 4.0f) > 0.0f) ? 1.0f : 0.3f;
      99           28 :     return ImVec4(1.0f, 0.1f, 0.1f, a);
     100              : }
     101              : 
     102              : // --- Parameter value formatter ---
     103              : // Produces human-readable display strings with unit-aware formatting:
     104              : //   Hz  -> "440 Hz" or "1.5 kHz" (>=1000)
     105              : //   dB  -> "-6.0 dB"
     106              : //   %   -> "75%"
     107              : //   ms  -> "250 ms"
     108              : //   s   -> "1.20 s"
     109              : //   other / none -> "1.5" or "1.5 unit"
     110         4386 : inline std::string formatParameterValue(float value, const std::string& unit) {
     111         1462 :     char buf[64];
     112         4386 :     if (unit == "Hz") {
     113          384 :         if (value >= 1000.0f)
     114          192 :             snprintf(buf, sizeof(buf), "%.1f kHz", value / 1000.0f);
     115              :         else
     116          192 :             snprintf(buf, sizeof(buf), "%.0f Hz", value);
     117         4130 :     } else if (unit == "dB") {
     118         1524 :         snprintf(buf, sizeof(buf), "%.1f dB", value);
     119         2986 :     } else if (unit == "%" || unit == "pct") {
     120            6 :         snprintf(buf, sizeof(buf), "%.0f%%", value);
     121         2474 :     } else if (unit == "ms") {
     122         1083 :         snprintf(buf, sizeof(buf), "%.1f ms", value);
     123         1750 :     } else if (unit == "s") {
     124            3 :         snprintf(buf, sizeof(buf), "%.2f s", value);
     125         1387 :     } else if (!unit.empty()) {
     126          711 :         snprintf(buf, sizeof(buf), "%.1f %s", value, unit.c_str());
     127          237 :     } else {
     128          675 :         snprintf(buf, sizeof(buf), "%.1f", value);
     129              :     }
     130         5848 :     return std::string(buf);
     131              : }
     132              : 
     133              : // --- Spacing / Layout ---
     134              : constexpr float PEDAL_WIDTH = 190.0f;
     135              : constexpr float PEDAL_HEIGHT = 360.0f;
     136              : constexpr float KNOB_RADIUS = 20.0f;
     137              : constexpr float KNOB_HIT_MULT = 2.2f;
     138              : constexpr float KNOB_SPACING_X = 85.0f;        // horizontal distance between knob columns
     139              : constexpr float KNOB_SPACING_Y = 95.0f;        // vertical distance between knob rows
     140              : constexpr float KNOB_Y_START = 70.0f;          // knob area top offset from pedal top
     141              : constexpr float SWITCH_BOTTOM_OFFSET = 55.0f;  // footswitch distance from pedal bottom
     142              : constexpr float ROUNDING_SM = 4.0f;
     143              : constexpr float ROUNDING_MD = 8.0f;
     144              : constexpr float ROUNDING_LG = 12.0f;
     145              : 
     146              : // --- Apply the full ImGui style ---
     147            3 : inline void ApplyStyle() {
     148            3 :     ImGuiStyle& style = ImGui::GetStyle();
     149              : 
     150              :     // Rounding
     151            3 :     style.WindowRounding = ROUNDING_MD;
     152            3 :     style.ChildRounding = ROUNDING_SM;
     153            3 :     style.FrameRounding = ROUNDING_SM;
     154            3 :     style.PopupRounding = ROUNDING_SM;
     155            3 :     style.ScrollbarRounding = ROUNDING_SM;
     156            3 :     style.GrabRounding = ROUNDING_SM;
     157            3 :     style.TabRounding = ROUNDING_SM;
     158              : 
     159              :     // Spacing
     160            3 :     style.WindowPadding = ImVec2(8, 8);
     161            3 :     style.FramePadding = ImVec2(6, 4);
     162            3 :     style.ItemSpacing = ImVec2(8, 5);
     163            3 :     style.ScrollbarSize = 12;
     164            3 :     style.GrabMinSize = 10;
     165              : 
     166              :     // Borders
     167            3 :     style.WindowBorderSize = 1.0f;
     168            3 :     style.ChildBorderSize = 1.0f;
     169            3 :     style.FrameBorderSize = 0.0f;
     170              : 
     171              :     // Colors
     172            3 :     ImVec4* c = style.Colors;
     173              : 
     174              :     // Window
     175            3 :     c[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.10f, 0.09f, 1.00f);  // #1c1a18
     176            3 :     c[ImGuiCol_ChildBg] = ImVec4(0.08f, 0.07f, 0.06f, 0.40f);
     177            3 :     c[ImGuiCol_PopupBg] = ImVec4(0.14f, 0.13f, 0.11f, 0.95f);
     178              : 
     179              :     // Borders
     180            3 :     c[ImGuiCol_Border] = ImVec4(0.23f, 0.21f, 0.19f, 0.60f);
     181            3 :     c[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
     182              : 
     183              :     // Title / Menu
     184            3 :     c[ImGuiCol_TitleBg] = ImVec4(0.12f, 0.11f, 0.10f, 1.00f);
     185            3 :     c[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.15f, 0.13f, 1.00f);
     186            3 :     c[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.13f, 0.11f, 1.00f);
     187              : 
     188              :     // Text
     189            3 :     c[ImGuiCol_Text] = TextPrimary();
     190            3 :     c[ImGuiCol_TextDisabled] = TextDim();
     191              : 
     192              :     // Frame (input fields, sliders)
     193            3 :     c[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.15f, 0.13f, 1.00f);
     194            3 :     c[ImGuiCol_FrameBgHovered] = ImVec4(0.22f, 0.20f, 0.17f, 1.00f);
     195            3 :     c[ImGuiCol_FrameBgActive] = ImVec4(0.27f, 0.25f, 0.22f, 1.00f);
     196              : 
     197              :     // Buttons — gold tinted
     198            3 :     c[ImGuiCol_Button] = ImVec4(0.22f, 0.20f, 0.16f, 1.00f);
     199            3 :     c[ImGuiCol_ButtonHovered] = ImVec4(0.35f, 0.30f, 0.18f, 1.00f);
     200            3 :     c[ImGuiCol_ButtonActive] = ImVec4(0.50f, 0.42f, 0.20f, 1.00f);
     201              : 
     202              :     // Header / selectable
     203            3 :     c[ImGuiCol_Header] = ImVec4(0.22f, 0.20f, 0.16f, 1.00f);
     204            3 :     c[ImGuiCol_HeaderHovered] = ImVec4(0.35f, 0.30f, 0.18f, 1.00f);
     205            3 :     c[ImGuiCol_HeaderActive] = ImVec4(0.50f, 0.42f, 0.20f, 1.00f);
     206              : 
     207              :     // Slider grab — gold
     208            3 :     c[ImGuiCol_SliderGrab] = Gold();
     209            3 :     c[ImGuiCol_SliderGrabActive] = GoldHot();
     210              : 
     211              :     // Scrollbar
     212            3 :     c[ImGuiCol_ScrollbarBg] = ImVec4(0.08f, 0.07f, 0.06f, 0.50f);
     213            3 :     c[ImGuiCol_ScrollbarGrab] = ImVec4(0.25f, 0.23f, 0.20f, 1.00f);
     214            3 :     c[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.35f, 0.30f, 0.25f, 1.00f);
     215            3 :     c[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.45f, 0.38f, 0.28f, 1.00f);
     216              : 
     217              :     // Checkbox / radio
     218            3 :     c[ImGuiCol_CheckMark] = Gold();
     219              : 
     220              :     // Separator
     221            3 :     c[ImGuiCol_Separator] = ImVec4(0.23f, 0.21f, 0.19f, 0.50f);
     222            3 :     c[ImGuiCol_SeparatorHovered] = ImVec4(0.50f, 0.42f, 0.20f, 0.70f);
     223            3 :     c[ImGuiCol_SeparatorActive] = ImVec4(0.78f, 0.66f, 0.29f, 1.00f);
     224              : 
     225              :     // Tab
     226            3 :     c[ImGuiCol_Tab] = ImVec4(0.16f, 0.15f, 0.13f, 1.00f);
     227            3 :     c[ImGuiCol_TabHovered] = ImVec4(0.35f, 0.30f, 0.18f, 1.00f);
     228              : 
     229              :     // Resize grip
     230            3 :     c[ImGuiCol_ResizeGrip] = ImVec4(0.50f, 0.42f, 0.20f, 0.20f);
     231            3 :     c[ImGuiCol_ResizeGripHovered] = ImVec4(0.50f, 0.42f, 0.20f, 0.60f);
     232            3 :     c[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.66f, 0.29f, 0.90f);
     233            3 : }
     234              : 
     235              : }  // namespace Theme
     236              : 
     237              : // --- Effect Color Scheme (SOLID: Open/Closed — extend by adding entries, not modifying) ---
     238              : struct EffectColorEntry {
     239              :     const char* name;
     240              :     ImVec4 pedal_color;
     241              :     ImVec4 led_color;
     242              : };
     243              : 
     244          549 : inline const EffectColorEntry* get_effect_color(const char* effect_name) {
     245              :     // Warm-toned pedal colors that complement the Amplitron palette
     246          183 :     static const EffectColorEntry table[] = {
     247              :         {"Distortion", ImVec4(0.45f, 0.14f, 0.10f, 1.0f), ImVec4(1.0f, 0.30f, 0.20f, 1.0f)},
     248              :         {"Overdrive", ImVec4(0.45f, 0.34f, 0.12f, 1.0f), ImVec4(0.95f, 0.75f, 0.20f, 1.0f)},
     249              :         {"Delay", ImVec4(0.12f, 0.22f, 0.38f, 1.0f), ImVec4(0.35f, 0.60f, 0.95f, 1.0f)},
     250              :         {"Reverb", ImVec4(0.14f, 0.28f, 0.36f, 1.0f), ImVec4(0.25f, 0.72f, 0.85f, 1.0f)},
     251              :         {"Looper", ImVec4(0.16f, 0.16f, 0.22f, 1.0f), ImVec4(0.78f, 0.66f, 0.29f, 1.0f)},
     252              :         {"Chorus", ImVec4(0.26f, 0.14f, 0.38f, 1.0f), ImVec4(0.65f, 0.35f, 0.95f, 1.0f)},
     253              :         {"Phaser", ImVec4(0.22f, 0.10f, 0.34f, 1.0f), ImVec4(0.80f, 0.25f, 0.90f, 1.0f)},
     254              :         {"Flanger", ImVec4(0.14f, 0.20f, 0.36f, 1.0f), ImVec4(0.30f, 0.70f, 1.00f, 1.0f)},
     255              :         {"Equalizer", ImVec4(0.14f, 0.32f, 0.18f, 1.0f), ImVec4(0.25f, 0.90f, 0.40f, 1.0f)},
     256              :         {"Noise Gate", ImVec4(0.20f, 0.19f, 0.22f, 1.0f), ImVec4(0.70f, 0.70f, 0.80f, 1.0f)},
     257              :         {"Compressor", ImVec4(0.34f, 0.26f, 0.14f, 1.0f), ImVec4(0.95f, 0.65f, 0.25f, 1.0f)},
     258              :         {"MultiBand Compressor", ImVec4(0.24f, 0.30f, 0.28f, 1.0f),
     259              :          ImVec4(0.40f, 0.85f, 0.70f, 1.0f)},
     260              :         {"Cabinet", ImVec4(0.26f, 0.18f, 0.10f, 1.0f), ImVec4(0.85f, 0.55f, 0.30f, 1.0f)},
     261              :         {"Octaver", ImVec4(0.36f, 0.14f, 0.28f, 1.0f), ImVec4(0.90f, 0.35f, 0.60f, 1.0f)},
     262              :         {"Pitch Shifter", ImVec4(0.32f, 0.12f, 0.32f, 1.0f), ImVec4(0.85f, 0.40f, 0.85f, 1.0f)},
     263              :         {"Tuner", ImVec4(0.12f, 0.24f, 0.30f, 1.0f), ImVec4(0.40f, 0.85f, 0.95f, 1.0f)},
     264              :     };
     265         4026 :     for (const auto& entry : table) {
     266         3993 :         if (std::strcmp(effect_name, entry.name) == 0) return &entry;
     267              :     }
     268              :     // Default fallback
     269              :     static const EffectColorEntry fallback = {"Default", ImVec4(0.20f, 0.19f, 0.17f, 1.0f),
     270              :                                               ImVec4(0.78f, 0.66f, 0.29f, 1.0f)};
     271           22 :     return &fallback;
     272          183 : }
     273              : 
     274              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1