mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-24 05:41:53 +00:00
- BG_STYLES port (off/particles/lights/geometric; lights use the pitch-class palette) mounted behind the scene; _bgGetAnalyser/ _bgReadBands (stems-first, one-shot #audio fallback, permanent-failure latch); Ambience intensity + Audio-reactive settings; remounts on style/intensity change - Score-FX overlay canvas (drum_highway_3d pattern): +1 pops at the scored key, ring pulse every 10-combo, milestone bursts at 25/50/100, red wash on 3+ streak break (wrong notes AND swept misses); cleared when idle, removed in teardown - Tests: style id validation + FX defaults (30 total) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
209 lines
11 KiB
HTML
209 lines
11 KiB
HTML
<div role="group" aria-labelledby="keysh3d-heading">
|
|
<h3 id="keysh3d-heading" class="text-sm font-medium text-gray-400 mb-2">3D Keys Highway</h3>
|
|
<p class="text-xs text-gray-500 mb-3">
|
|
Pick a song with keys notation (sloppak-spec §5.3) and choose
|
|
<em>Keys Highway 3D</em> from the viz picker (Auto selects it for
|
|
notation charts). The plugin auto-attaches to your MIDI keyboard;
|
|
device, channel and transpose are configured from the player for
|
|
now — this panel holds the graphics controls.
|
|
</p>
|
|
|
|
<!-- Graphics -->
|
|
<div class="mt-3">
|
|
<h4 class="text-xs font-medium text-gray-300 mb-2">Graphics</h4>
|
|
|
|
<label for="keysh3d-fx-theme" class="text-xs font-medium text-gray-400 mb-1 block">Scene theme</label>
|
|
<select id="keysh3d-fx-theme"
|
|
onchange="window.keys3dSetTheme && window.keys3dSetTheme(this.value)"
|
|
class="w-full bg-dark-700 border border-gray-800 rounded-lg px-3 py-2 text-xs text-gray-300 outline-none">
|
|
<option value="default">Default (original)</option>
|
|
<option value="midnight">Midnight</option>
|
|
<option value="charcoal">Charcoal</option>
|
|
<option value="deeppurple">Deep Purple</option>
|
|
<option value="forest">Forest</option>
|
|
<option value="warmslate">Warm Slate</option>
|
|
<option value="deepfocus">Deep Focus</option>
|
|
<option value="deepsea">Deep Sea</option>
|
|
<option value="cathode">Cathode</option>
|
|
<option value="cathodegreen">Cathode Green</option>
|
|
<option value="hearth">Hearth</option>
|
|
</select>
|
|
<p class="text-xs text-gray-500 mt-1 mb-3">
|
|
Background gradient, floor and lane rails — the same theme names
|
|
as the guitar highway. Pitch-class note colours never change.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-cinematic" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer">
|
|
<input type="checkbox" id="keysh3d-fx-cinematic" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('cinematic', this.checked)">
|
|
Cinematic lighting
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Dimmer ambience, stronger key light — deeper shading on the keys
|
|
and gems.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-glow" class="text-xs font-medium text-gray-400 mb-1 mt-3 block">
|
|
Glow strength <span id="keysh3d-fx-glow-val" class="text-gray-500 font-mono">0.50</span>
|
|
</label>
|
|
<input type="range" id="keysh3d-fx-glow"
|
|
min="0" max="1" step="0.05" value="0.5"
|
|
oninput="window.keys3dSetFx && window.keys3dSetFx('glow', this.value); document.getElementById('keysh3d-fx-glow-val').textContent = parseFloat(this.value).toFixed(2)"
|
|
class="w-full">
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
How hard the notes, key glow and sustain consume-flash
|
|
self-illuminate (0.5 = stock). Pairs with bloom.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-bgstyle" class="text-xs font-medium text-gray-400 mb-1 mt-3 block">Background ambience</label>
|
|
<select id="keysh3d-fx-bgstyle"
|
|
onchange="window.keys3dSetBgStyle && window.keys3dSetBgStyle(this.value)"
|
|
class="w-full bg-dark-700 border border-gray-800 rounded-lg px-3 py-2 text-xs text-gray-300 outline-none">
|
|
<option value="off">Off</option>
|
|
<option value="particles" selected>Particles</option>
|
|
<option value="lights">Stage lights</option>
|
|
<option value="geometric">Geometric</option>
|
|
</select>
|
|
<label for="keysh3d-fx-bgintensity" class="text-xs font-medium text-gray-400 mb-1 mt-2 block">
|
|
Ambience intensity <span id="keysh3d-fx-bgintensity-val" class="text-gray-500 font-mono">0.50</span>
|
|
</label>
|
|
<input type="range" id="keysh3d-fx-bgintensity"
|
|
min="0" max="1" step="0.05" value="0.5"
|
|
oninput="window.keys3dSetFx && window.keys3dSetFx('bgIntensity', this.value); document.getElementById('keysh3d-fx-bgintensity-val').textContent = parseFloat(this.value).toFixed(2)"
|
|
class="w-full">
|
|
<label for="keysh3d-fx-bgreactive" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-2">
|
|
<input type="checkbox" id="keysh3d-fx-bgreactive" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('bgReactive', this.checked)">
|
|
Audio-reactive ambience
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
The backdrop pulses with the mix (stems analyser when a sloppak
|
|
is loaded). Off = it animates on time only.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-scorefx" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-3">
|
|
<input type="checkbox" id="keysh3d-fx-scorefx" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('scoreFx', this.checked)">
|
|
Score effects
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
+1 pops on scored presses, a ring pulse every 10-combo,
|
|
milestone bursts at 25/50/100, and a brief red flicker when a
|
|
streak breaks.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-bloom" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-3">
|
|
<input type="checkbox" id="keysh3d-fx-bloom" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('bloom', this.checked)">
|
|
Glow (bloom)
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Soft light-bleed around the hit line, hit flames and consumed
|
|
sustains. Applies live; turn off to reclaim GPU headroom on
|
|
weak machines.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-sparks" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-3">
|
|
<input type="checkbox" id="keysh3d-fx-sparks" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('sparks', this.checked)">
|
|
Hit sparks
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
A small particle burst on every scored key press, beside the
|
|
pitch-colored flame.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-timing" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-3">
|
|
<input type="checkbox" id="keysh3d-fx-timing" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('timingFx', this.checked)">
|
|
Timing colours
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Tint the sparks by timing — on-time green, early cyan, late
|
|
amber. Off = always green.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-streak" class="flex items-center gap-2 text-xs text-gray-300 cursor-pointer mt-3">
|
|
<input type="checkbox" id="keysh3d-fx-streak" checked
|
|
onchange="window.keys3dSetFx && window.keys3dSetFx('streakFx', this.checked)">
|
|
Streak feedback
|
|
</label>
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Spark bursts grow with your combo.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-hitfx" class="text-xs font-medium text-gray-400 mb-1 mt-3 block">
|
|
Hit feedback intensity <span id="keysh3d-fx-hitfx-val" class="text-gray-500 font-mono">0.70</span>
|
|
</label>
|
|
<input type="range" id="keysh3d-fx-hitfx"
|
|
min="0" max="1" step="0.05" value="0.7"
|
|
oninput="window.keys3dSetFx && window.keys3dSetFx('hitFx', this.value); document.getElementById('keysh3d-fx-hitfx-val').textContent = parseFloat(this.value).toFixed(2)"
|
|
class="w-full">
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Drives the hit-line brightness kick on scored presses. 0 turns
|
|
it off.
|
|
</p>
|
|
|
|
<label for="keysh3d-fx-vibrancy" class="text-xs font-medium text-gray-400 mb-1 mt-3 block">
|
|
Note vibrancy <span id="keysh3d-fx-vibrancy-val" class="text-gray-500 font-mono">0.85</span>
|
|
</label>
|
|
<input type="range" id="keysh3d-fx-vibrancy"
|
|
min="0" max="1" step="0.05" value="0.85"
|
|
oninput="window.keys3dSetFx && window.keys3dSetFx('vibrancy', this.value); document.getElementById('keysh3d-fx-vibrancy-val').textContent = parseFloat(this.value).toFixed(2)"
|
|
class="w-full">
|
|
<p class="text-xs text-gray-500 mt-1">
|
|
Note-gem solidity and lane-guide strength — lower to see more of
|
|
the keyboard through the notes.
|
|
</p>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
'use strict';
|
|
// Hydrate controls from stored config on first paint. Narrow the
|
|
// try/catch to just the localStorage reads (drum_highway_3d
|
|
// settings-hydration convention).
|
|
try {
|
|
// FX toggles (keys3d_bg_* — guitar-parity graphics controls).
|
|
// Only explicit values override; absent/corrupt keys keep the
|
|
// default (ON), matching screen.js readFxSettings.
|
|
const hydrateFxBool = (key, elId) => {
|
|
const raw = localStorage.getItem('keys3d_bg_' + key);
|
|
if (raw === '1' || raw === 'true') document.getElementById(elId).checked = true;
|
|
else if (raw === '0' || raw === 'false') document.getElementById(elId).checked = false;
|
|
};
|
|
hydrateFxBool('bloom', 'keysh3d-fx-bloom');
|
|
hydrateFxBool('sparks', 'keysh3d-fx-sparks');
|
|
hydrateFxBool('timingFx', 'keysh3d-fx-timing');
|
|
hydrateFxBool('streakFx', 'keysh3d-fx-streak');
|
|
hydrateFxBool('cinematic', 'keysh3d-fx-cinematic');
|
|
hydrateFxBool('bgReactive', 'keysh3d-fx-bgreactive');
|
|
hydrateFxBool('scoreFx', 'keysh3d-fx-scorefx');
|
|
const hydrateFxRange = (key, elId, valId) => {
|
|
const n = parseFloat(localStorage.getItem('keys3d_bg_' + key));
|
|
if (!Number.isFinite(n)) return;
|
|
const v = Math.min(1, Math.max(0, n));
|
|
document.getElementById(elId).value = String(v);
|
|
document.getElementById(valId).textContent = v.toFixed(2);
|
|
};
|
|
hydrateFxRange('hitFx', 'keysh3d-fx-hitfx', 'keysh3d-fx-hitfx-val');
|
|
hydrateFxRange('vibrancy', 'keysh3d-fx-vibrancy', 'keysh3d-fx-vibrancy-val');
|
|
hydrateFxRange('glow', 'keysh3d-fx-glow', 'keysh3d-fx-glow-val');
|
|
hydrateFxRange('bgIntensity', 'keysh3d-fx-bgintensity', 'keysh3d-fx-bgintensity-val');
|
|
const storedStyle = localStorage.getItem('keys3d_bg_style');
|
|
const styleSel = document.getElementById('keysh3d-fx-bgstyle');
|
|
if (storedStyle && Array.from(styleSel.options).some(o => o.value === storedStyle)) {
|
|
styleSel.value = storedStyle;
|
|
}
|
|
const storedTheme = localStorage.getItem('keys3d_bg_theme');
|
|
const themeSel = document.getElementById('keysh3d-fx-theme');
|
|
if (storedTheme && Array.from(themeSel.options).some(o => o.value === storedTheme)) {
|
|
themeSel.value = storedTheme;
|
|
}
|
|
} catch (e) {
|
|
console.warn('[Keys-Hwy3D settings] hydration failed:', e);
|
|
}
|
|
})();
|
|
</script>
|
|
</div>
|