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
|