Skip to content

Commit 55ef2ff

Browse files
authored
Merge pull request #113 from ford442/claude/claude-md-mmjcy56af36o5864-0PP8n
Claude/claude md mmjcy56af36o5864 0 pp8n
2 parents 4e301cd + 70ecaca commit 55ef2ff

4 files changed

Lines changed: 51 additions & 40 deletions

File tree

components/PatternDisplay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ export const PatternDisplay: React.FC<PatternDisplayProps> = ({
12661266
textureResourcesRef.current = null;
12671267
bezelTextureResourcesRef.current = null;
12681268

1269-
const shaderBase = './';
1269+
const shaderBase = import.meta.env.BASE_URL;
12701270
const shaderSource = await fetch(`${shaderBase}shaders/${shaderFile}`).then(res => res.text());
12711271
if (cancelled) return;
12721272
const module = device.createShaderModule({ code: shaderSource });

hooks/useLibOpenMPT.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ interface SyncDebugInfo {
1414
// Constants
1515
const DEFAULT_ROWS = 64;
1616
const DEFAULT_CHANNELS = 4;
17-
// Use './' so the URL resolves relative to the page, correct in any deployment path
18-
const DEFAULT_MODULE_URL = './4-mat_madness.mod';
17+
// Use Vite BASE_URL for correct resolution under subdirectory deployment
18+
const DEFAULT_MODULE_URL = `${import.meta.env.BASE_URL}4-mat_madness.mod`;
1919

2020
// Runtime base URL detection for subdirectory deployment (e.g., /xm-player/)
2121
// Vite's BASE_URL may be '/' at build time, so we detect actual path from window.location

public/shaders/patternv0.50.wgsl

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
// patternv0.50.wgsl
2-
// Three-Emitter LED Indicator System with Unified Lens Cap
3-
// Top: Blue Note-On | Middle: Steady Note Color | Bottom: Amber Control
4-
// Based on v0.49 (circular layout with padTopChannel=true)
5-
// Note: Requires padTopChannel=true in PatternDisplay to shift music channels 1-32.
2+
// Frosted Glass Circular – Vibrant Note Colours + Blue LED Indicator + Full-Height Caps
3+
//
4+
// Hybrid composition combining v0.48 (vibrant note-data colours from neonPalette)
5+
// and v0.49 (blue LED indicator ring, solid housing, frosted glass caps).
6+
//
7+
// Per-step layering:
8+
// 1. HOUSING (BEHINDS) — Solid dark-metallic body lit with vibrant neonPalette
9+
// colours driven by real note pitch (purple, teal, green,
10+
// orange, red, cyan). Activity from v0.48's distance-based
11+
// energy sweep + trail + noteAge + tickOffset sub-step.
12+
// 2. CAP — Full-height frosted acrylic glass (0.88 × 0.88) in the same vibrant
13+
// hue as the housing. LED-under-glass model with white bevel rim.
14+
// 3. DEPRESSION — On playhead hit: cap scales 4 % smaller + top inner-shadow.
15+
//
16+
// Channel 0: Blue LED indicator ring shows playhead proximity (from v0.49).
17+
//
18+
// Background: bezel.wgsl (hardware photo with dark centre + white frame).
19+
// Transparent gaps + centre circle allow bezel to show through.
620

721
struct Uniforms {
822
numRows: u32,
@@ -37,11 +51,11 @@ struct ChannelState { volume: f32, pan: f32, freq: f32, trigger: u32, noteAge: f
3751

3852
struct VertexOut {
3953
@builtin(position) position: vec4<f32>,
40-
@location(0) @interpolate(flat) row: u32,
41-
@location(1) @interpolate(flat) channel: u32,
42-
@location(2) @interpolate(linear) uv: vec2<f32>,
43-
@location(3) @interpolate(flat) packedA: u32,
44-
@location(4) @interpolate(flat) packedB: u32,
54+
@location(0) @interpolate(flat) row: u32,
55+
@location(1) @interpolate(flat) channel: u32,
56+
@location(2) @interpolate(linear) uv: vec2<f32>,
57+
@location(3) @interpolate(flat) packedA: u32,
58+
@location(4) @interpolate(flat) packedB: u32,
4559
};
4660

4761
@vertex
@@ -52,38 +66,33 @@ fn vs(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instance
5266
);
5367

5468
let numChannels = uniforms.numChannels;
55-
let row = instanceIndex / numChannels;
56-
let channel = instanceIndex % numChannels;
69+
let row = instanceIndex / numChannels;
70+
let channel = instanceIndex % numChannels;
5771

5872
let invertedChannel = numChannels - 1u - channel;
59-
let ringIndex = select(invertedChannel, channel, (uniforms.invertChannels == 1u));
60-
61-
let center = vec2<f32>(uniforms.canvasW * 0.5, uniforms.canvasH * 0.5);
62-
let minDim = min(uniforms.canvasW, uniforms.canvasH);
73+
let ringIndex = select(invertedChannel, channel, uniforms.invertChannels == 1u);
6374

75+
let center = vec2<f32>(uniforms.canvasW * 0.5, uniforms.canvasH * 0.5);
76+
let minDim = min(uniforms.canvasW, uniforms.canvasH);
6477
let maxRadius = minDim * 0.45;
6578
let minRadius = minDim * 0.15;
6679
let ringDepth = (maxRadius - minRadius) / f32(numChannels);
80+
let radius = minRadius + f32(ringIndex) * ringDepth;
6781

68-
let radius = minRadius + f32(ringIndex) * ringDepth;
69-
70-
let totalSteps = 64.0;
82+
let totalSteps = 64.0;
7183
let anglePerStep = 6.2831853 / totalSteps;
72-
let theta = -1.570796 + f32(row % 64u) * anglePerStep;
84+
let theta = -1.570796 + f32(row % 64u) * anglePerStep;
7385

7486
let circumference = 2.0 * 3.14159265 * radius;
75-
let arcLength = circumference / totalSteps;
76-
77-
let btnW = arcLength * 0.95;
78-
let btnH = ringDepth * 0.95;
87+
let arcLength = circumference / totalSteps;
88+
let btnW = arcLength * 0.95;
89+
let btnH = ringDepth * 0.95;
7990

80-
let lp = quad[vertexIndex];
91+
let lp = quad[vertexIndex];
8192
let localPos = (lp - 0.5) * vec2<f32>(btnW, btnH);
8293

8394
let rotAng = theta + 1.570796;
84-
let cA = cos(rotAng);
85-
let sA = sin(rotAng);
86-
95+
let cA = cos(rotAng); let sA = sin(rotAng);
8796
let rotX = localPos.x * cA - localPos.y * sA;
8897
let rotY = localPos.x * sA + localPos.y * cA;
8998

@@ -94,25 +103,27 @@ fn vs(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instance
94103
let clipY = 1.0 - (worldY / uniforms.canvasH) * 2.0;
95104

96105
let idx = instanceIndex * 2u;
97-
let a = cells[idx];
98-
let b = cells[idx + 1u];
106+
let a = cells[idx];
107+
let b = cells[idx + 1u];
99108

100109
var out: VertexOut;
101110
out.position = vec4<f32>(clipX, clipY, 0.0, 1.0);
102-
out.row = row;
103-
out.channel = channel;
104-
out.uv = lp;
105-
out.packedA = a;
106-
out.packedB = b;
111+
out.row = row;
112+
out.channel = channel;
113+
out.uv = lp;
114+
out.packedA = a;
115+
out.packedB = b;
107116
return out;
108117
}
109118

119+
// ── Helpers ───────────────────────────────────────────────────────────────────
120+
110121
fn neonPalette(t: f32) -> vec3<f32> {
111122
let a = vec3<f32>(0.5, 0.5, 0.5);
112123
let b = vec3<f32>(0.5, 0.5, 0.5);
113124
let c = vec3<f32>(1.0, 1.0, 1.0);
114125
let d = vec3<f32>(0.0, 0.33, 0.67);
115-
let beatDrift = uniforms.beatPhase * 0.1;
126+
let beatDrift = uniforms.beatPhase * 0.08;
116127
return a + b * cos(6.28318 * (c * (t + beatDrift) + d));
117128
}
118129

@@ -467,4 +478,4 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
467478

468479
if (housingMask < 0.5) { return vec4<f32>(fs.borderColor, 0.0); }
469480
return vec4<f32>(finalColor, 1.0);
470-
}
481+
}

utils/remoteMedia.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { MediaItem } from '../types';
22

33
// Adjust this path to match where you drop your files on the FTP
4-
const REMOTE_MEDIA_BASE_URL = './media/';
4+
const REMOTE_MEDIA_BASE_URL = `${import.meta.env.BASE_URL}media/`;
55

66
export const fetchRemoteMedia = async (): Promise<MediaItem[]> => {
77
try {

0 commit comments

Comments
 (0)