Skip to content

Commit db48bea

Browse files
committed
UI: Start overlay becomes blurred overlay over live visuals; bring back 'h' to toggle hint; document modes clearly; improved layout and readability.
1 parent 9de3bb0 commit db48bea

File tree

4 files changed

+118
-30
lines changed

4 files changed

+118
-30
lines changed

crates/app-native/src/main.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use winit::{event::*, event_loop::EventLoop, window::WindowBuilder};
88
use app_core::{
99
z_offset_vec3, EngineParams, MusicEngine, VoiceConfig, Waveform, AEOLIAN, BASE_SCALE,
1010
C_MAJOR_PENTATONIC, DEFAULT_VOICE_COLORS, DEFAULT_VOICE_POSITIONS, DORIAN, IONIAN, LOCRIAN,
11-
LYDIAN, MIXOLYDIAN, PICK_SPHERE_RADIUS, PHRYGIAN, SPREAD,
11+
LYDIAN, MIXOLYDIAN, PHRYGIAN, PICK_SPHERE_RADIUS, SPREAD,
1212
};
1313
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
1414
use glam::{Mat4, Vec3, Vec4};
@@ -544,8 +544,9 @@ fn main() {
544544
// Randomize root+mode
545545
KeyCode::KeyT => {
546546
let roots: [i32; 7] = [60, 62, 64, 65, 67, 69, 71];
547-
let modes: [&'static [i32]; 7] =
548-
[IONIAN, DORIAN, PHRYGIAN, LYDIAN, MIXOLYDIAN, AEOLIAN, LOCRIAN];
547+
let modes: [&'static [i32]; 7] = [
548+
IONIAN, DORIAN, PHRYGIAN, LYDIAN, MIXOLYDIAN, AEOLIAN, LOCRIAN,
549+
];
549550
let ix = (Instant::now().elapsed().as_nanos() as u64) as usize;
550551
eng.params.root_midi = roots[ix % roots.len()];
551552
eng.params.scale = modes[(ix / 7) % modes.len()];
@@ -561,7 +562,11 @@ fn main() {
561562
}
562563
if tone_changed {
563564
let eng = engine.lock().unwrap();
564-
log::info!("[keys] root={} mode_len={}", eng.params.root_midi, eng.params.scale.len());
565+
log::info!(
566+
"[keys] root={} mode_len={}",
567+
eng.params.root_midi,
568+
eng.params.scale.len()
569+
);
565570
}
566571
}
567572
Event::WindowEvent {

crates/app-web/index.html

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
display: flex;
3232
align-items: center;
3333
justify-content: center;
34-
background: rgba(2, 3, 8, 0.66);
35-
backdrop-filter: blur(2px);
34+
background: rgba(2, 3, 8, 0.25);
35+
backdrop-filter: blur(6px) saturate(1.1);
3636
z-index: 10;
3737
}
3838
#start-content {
@@ -44,13 +44,58 @@
4444
color: #cfe7ff;
4545
}
4646
#start-keys {
47-
color: #9bb;
48-
font: 12px/1.4 monospace;
49-
max-width: 560px;
50-
background: rgba(20, 20, 30, 0.55);
51-
padding: 10px 12px;
47+
color: #cfe7ff;
48+
font:
49+
13px/1.55 system-ui,
50+
-apple-system,
51+
Segoe UI,
52+
Roboto,
53+
Ubuntu,
54+
Cantarell,
55+
Noto Sans,
56+
Arial,
57+
sans-serif;
58+
max-width: 760px;
59+
background: rgba(10, 14, 24, 0.7);
60+
padding: 16px 18px;
5261
border: 1px solid rgba(80, 110, 150, 0.35);
53-
border-radius: 8px;
62+
border-radius: 10px;
63+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
64+
text-align: left;
65+
}
66+
#start-keys h3 {
67+
margin: 0 0 8px 0;
68+
font-size: 13px;
69+
font-weight: 700;
70+
color: #a9c6ff;
71+
letter-spacing: 0.02em;
72+
text-transform: uppercase;
73+
}
74+
#start-keys .grid {
75+
display: grid;
76+
grid-template-columns: 1fr 1fr;
77+
gap: 8px 18px;
78+
}
79+
#start-keys ul {
80+
list-style: none;
81+
margin: 6px 0 10px 0;
82+
padding: 0;
83+
color: #9bb;
84+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
85+
font-size: 12px;
86+
}
87+
#start-keys li {
88+
margin: 4px 0;
89+
}
90+
.kbd {
91+
display: inline-block;
92+
padding: 1px 6px;
93+
border-radius: 6px;
94+
border: 1px solid rgba(120, 150, 190, 0.35);
95+
background: rgba(18, 24, 38, 0.8);
96+
color: #cfe7ff;
97+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
98+
font-size: 12px;
5499
}
55100
#start-btn {
56101
appearance: none;
@@ -96,11 +141,45 @@
96141
<div id="start-content">
97142
<button id="start-btn">Start</button>
98143
<div id="start-keys">
99-
Click Start to begin<br />
100-
Click canvas: play a note • Mouse position affects sound<br />
101-
Keys: A..F (root) • 1..7 (mode) • R (new seq) • T (random key+mode) •
102-
Space (pause) • ArrowLeft/Right (tempo) • ArrowUp/Down (volume) •
103-
Enter (fullscreen) • Esc (exit)
144+
<h3>Welcome</h3>
145+
<ul>
146+
<li>
147+
Click <span class="kbd">Start</span>, then click the canvas to
148+
play a note. Mouse position shapes the sound.
149+
</li>
150+
</ul>
151+
<div class="grid">
152+
<div>
153+
<h3>Keys</h3>
154+
<ul>
155+
<li><span class="kbd">A..F</span>: set root note</li>
156+
<li><span class="kbd">1..7</span>: set mode (see right)</li>
157+
<li><span class="kbd">R</span>: new sequence</li>
158+
<li><span class="kbd">T</span>: random root + mode</li>
159+
<li><span class="kbd">Space</span>: pause/resume</li>
160+
<li>
161+
<span class="kbd">Enter</span>/<span class="kbd">Esc</span>:
162+
full/exit screen
163+
</li>
164+
<li>
165+
<span class="kbd">←/→</span>: tempo •
166+
<span class="kbd">↑/↓</span>: volume
167+
</li>
168+
</ul>
169+
</div>
170+
<div>
171+
<h3>Modes (1..7)</h3>
172+
<ul>
173+
<li><span class="kbd">1</span>: Ionian (major)</li>
174+
<li><span class="kbd">2</span>: Dorian</li>
175+
<li><span class="kbd">3</span>: Phrygian</li>
176+
<li><span class="kbd">4</span>: Lydian</li>
177+
<li><span class="kbd">5</span>: Mixolydian</li>
178+
<li><span class="kbd">6</span>: Aeolian (natural minor)</li>
179+
<li><span class="kbd">7</span>: Locrian</li>
180+
</ul>
181+
</div>
182+
</div>
104183
</div>
105184
</div>
106185
</div>

crates/app-web/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,22 @@ async fn init() -> anyhow::Result<()> {
5050
.dyn_into::<web::HtmlCanvasElement>()
5151
.map_err(|e| anyhow::anyhow!(format!("{:?}", e)))?;
5252

53-
// Removed 'h' help toggle; key mapping is shown on the Start overlay instead.
53+
// Bring back 'h' help toggle to show/hide hint overlay
54+
{
55+
let window = web::window().unwrap();
56+
let document = document.clone();
57+
let closure = Closure::wrap(Box::new(move |ev: web::KeyboardEvent| {
58+
let key = ev.key();
59+
if key == "h" || key == "H" {
60+
ui::toggle_hint_visibility(&document);
61+
ev.prevent_default();
62+
}
63+
}) as Box<dyn FnMut(_)>);
64+
window
65+
.add_event_listener_with_callback("keydown", closure.as_ref().unchecked_ref())
66+
.ok();
67+
closure.forget();
68+
}
5469

5570
// Note: we will query the optional hint element lazily inside event handlers to avoid
5671
// capturing it here and forcing closures to be FnOnce.

crates/app-web/src/ui.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,7 @@ pub fn toggle_hint_visibility(document: &web::Document) {
1111
};
1212
let _ = el.set_attribute("data-visible", if show { "1" } else { "0" });
1313
if let Some(div) = el.dyn_ref::<web::HtmlElement>() {
14-
if show {
15-
// Default content (before full engine/UI attach)
16-
div.set_inner_html(
17-
"Click Start to begin • Drag to move a voice<br/>\
18-
Click: mute • Shift+Click: reseed • Alt+Click: solo<br/>\
19-
R: reseed all • Space: pause/resume • +/-: tempo • F: fullscreen<br/>\
20-
BPM: 110 • Paused: no",
21-
);
22-
let _ = el.set_attribute("style", "");
23-
} else {
24-
let _ = el.set_attribute("style", "display:none");
25-
}
14+
if show { let _ = el.set_attribute("style", ""); } else { let _ = el.set_attribute("style", "display:none"); }
2615
}
2716
}
2817
}

0 commit comments

Comments
 (0)