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