Makepad Code (editor layout, selection, sidebar, early yield), the EN/ZH Translator with voice, Weather with a generated offline forecast, Amp playing its offline library, and fixes across the other apps and examples. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
514 lines
27 KiB
Text
514 lines
27 KiB
Text
// title: Soviet Lab
|
|
// Soviet Lab — a 1970s laboratory instrument set into a brutalist wall: a
|
|
// front of raw board-marked concrete with formwork tie holes and rust
|
|
// streaks, heavy grey-green hammertone plates held on by hex bolts, brown
|
|
// bakelite keys and knob, a red PUSK key, orange neon everywhere a light
|
|
// burns: Nixie-mesh displays, IN-9 bargraph tubes for the spectrum, neon
|
|
// indicator lamps, and a mirror-scale ammeter for the level.
|
|
use mod.prelude.widgets_internal.*
|
|
|
|
// ---- palette: neon orange on smoked glass ----
|
|
mod.widgets.hw_palette.screen_bg = #x0d0a08
|
|
mod.widgets.hw_palette.screen_text = #xffa060
|
|
mod.widgets.hw_palette.screen_muted = #x9a6440
|
|
mod.widgets.hw_palette.accent = #xff5a14
|
|
mod.widgets.hw_palette.panel_text = #xd9dccf
|
|
mod.widgets.hw_palette.panel_muted = #x8d968a
|
|
mod.widgets.hw_palette.menu_bg = #x1d221f
|
|
mod.widgets.hw_palette.spill_color = #xff6a20
|
|
mod.widgets.hw_palette.spill_mono = 0.45
|
|
mod.widgets.hw_palette.spill_knee = 1.1
|
|
mod.widgets.hw_palette.caption_bg = #x6e6d68
|
|
mod.widgets.hw_palette.caption_text = #x1a1a18
|
|
|
|
// ---- the front: board-marked cast concrete ----
|
|
mod.widgets.HwChassis.draw_bg.ground = #x72716b
|
|
mod.widgets.HwChassis.draw_bg.light_ink = vec4(0.96, 0.95, 0.90, 1.0)
|
|
mod.widgets.HwChassis.draw_bg.shadow_ink = vec4(0.10, 0.10, 0.09, 1.0)
|
|
mod.widgets.HwChassis.draw_bg.glow_ink = vec4(1.0, 0.36, 0.08, 1.0)
|
|
mod.widgets.HwChassis.draw_bg.spill = vec2(2.8, 0.7)
|
|
mod.widgets.HwChassis.draw_bg.vignette = vec4(0.5, 0.30, 0.30, 1.06)
|
|
mod.widgets.Window.pass.clear_color = #x66655f
|
|
mod.widgets.HwChassis.draw_bg.surface = fn(p: vec2, base: vec3) -> vec3 {
|
|
let w = self.world.xy
|
|
// Formwork boards: wide planks, each poured against a different board.
|
|
let bh = 62.0
|
|
let row = floor(w.y / bh)
|
|
let fy = w.y - row * bh
|
|
let tone = self.hw_hash(vec2(row, 3.0)) - 0.5
|
|
var col = base * (1.0 + tone * 0.06)
|
|
// The board's grain printed faintly into the concrete.
|
|
let grain = self.hw_noise(vec2(w.x * 0.012 + row * 13.0, fy * 0.35 + self.hw_noise(vec2(w.x * 0.008, row)) * 3.0))
|
|
col = col * (1.0 + (grain - 0.5) * 0.05)
|
|
// Blotchy cement: large damp clouds, smaller mottling, sand.
|
|
let cloud = self.hw_noise(w * 0.006) * 0.5 + self.hw_noise(w * 0.021) * 0.3 + self.hw_noise(w * 0.07) * 0.2
|
|
col = col * (0.80 + cloud * 0.36)
|
|
col = mix(col, col * vec3(0.96, 0.99, 1.03), smoothstep(0.4, 0.7, self.hw_noise(w * 0.01 + vec2(40.0, 9.0))))
|
|
col = col * (1.0 + (self.hw_hash(floor(w * 1.7)) - 0.5) * 0.08)
|
|
// Air pits: small dark holes in the pour.
|
|
let pc = floor(w / 5.0)
|
|
let ph = self.hw_hash(pc + vec2(7.0, 1.0))
|
|
let pp = (pc + vec2(0.5, 0.5) + (vec2(self.hw_hash(pc), self.hw_hash(pc + vec2(3.0, 9.0))) - 0.5) * 2.5) * 5.0
|
|
let pr = length(w - pp)
|
|
let pit = (1.0 - smoothstep(0.5, 1.4, pr)) * step(0.91, ph)
|
|
col = col * (1.0 - pit * 0.6) + vec3(0.05, 0.05, 0.05) * (1.0 - smoothstep(0.0, 0.8, abs(pr - 1.7))) * step(0.91, ph) * step(pp.y, w.y)
|
|
// The joint between boards: a thin fin of cement, lit from above.
|
|
let jn = min(fy, bh - fy)
|
|
col = col * (1.0 - (1.0 - smoothstep(0.0, 1.4, jn)) * 0.16)
|
|
col = col + vec3(0.05, 0.05, 0.047) * (1.0 - smoothstep(0.0, 1.0, abs(fy - 1.8)))
|
|
// Precast panel joints: deep grooves, shadowed on the lit side's far wall.
|
|
let pcell = vec2(472.0, 368.0)
|
|
let pf = w - pcell * floor(w / pcell)
|
|
let gx = min(pf.x, pcell.x - pf.x)
|
|
let gy = min(pf.y, pcell.y - pf.y)
|
|
let groove = 1.0 - smoothstep(1.6, 2.6, min(gx, gy))
|
|
let lipd = smoothstep(2.4, 3.2, min(gx, gy)) * (1.0 - smoothstep(3.2, 4.6, min(gx, gy)))
|
|
let gsh = mix(step(pcell.x * 0.5, pf.x), step(pcell.y * 0.5, pf.y), step(gy, gx))
|
|
col = col * (1.0 - groove * 0.62)
|
|
col = col * (1.0 + lipd * (gsh * 0.22 - 0.10))
|
|
// Formwork tie holes on a grid, each weeping a rust streak down the wall.
|
|
let cell = vec2(236.0, 184.0)
|
|
let ci = floor(w / cell)
|
|
let hc = (ci + vec2(0.5, 0.5)) * cell
|
|
let v = w - hc
|
|
let r = length(v)
|
|
let streak = (1.0 - smoothstep(2.0, 6.0, abs(v.x + (self.hw_noise(vec2(w.y * 0.05, ci.x)) - 0.5) * 4.0))) * smoothstep(0.0, 8.0, v.y) * (1.0 - smoothstep(20.0, 130.0, v.y))
|
|
let sn = 0.6 + 0.4 * self.hw_noise(vec2(w.x * 0.4, w.y * 0.03))
|
|
col = mix(col, col * vec3(0.72, 0.56, 0.42), streak * sn * 0.55)
|
|
let cone = (1.0 - smoothstep(6.0, 9.5, r))
|
|
col = col * (1.0 - cone * 0.18 + cone * smoothstep(5.0, 8.0, r) * dot(normalize(v + vec2(0.0001, 0.0001)), vec2(0.5, 0.7)) * 0.25)
|
|
let hole = 1.0 - smoothstep(4.2, 5.2, r)
|
|
col = mix(col, vec3(0.13, 0.12, 0.11) + vec3(0.08, 0.07, 0.06) * clamp(v.y / 5.0, 0.0, 1.0), hole)
|
|
return col
|
|
}
|
|
|
|
// ---- raised plates: grey-green hammertone enamel, hex-bolted ----
|
|
mod.widgets.HwPlate.depth = 3.5
|
|
mod.widgets.HwPlate.radius = 4
|
|
mod.widgets.HwPlate.draw_bg.ground = #x3e5048
|
|
mod.widgets.HwPlate.draw_bg.light_ink = vec4(0.74, 0.80, 0.75, 1.0)
|
|
mod.widgets.HwPlate.draw_bg.shadow_ink = vec4(0.02, 0.03, 0.02, 1.0)
|
|
mod.widgets.HwPlate.draw_bg.relief = vec4(3.0, 0.2, 3.5, 0.35)
|
|
mod.widgets.HwPlate.draw_bg.finish = vec4(0.75, 0.40, 0.18, 0.7)
|
|
mod.widgets.HwPlate.draw_bg.shadow = vec4(0.85, 12.0, 1.0, 0.8)
|
|
mod.widgets.HwPlate.draw_bg.glow_ink = vec4(1.0, 0.36, 0.08, 1.0)
|
|
mod.widgets.HwPlate.draw_bg.spill = vec2(1.7, 0.7)
|
|
// Stencil figures: a seven-segment glyph with the stencil's bridges
|
|
// left in. `q` from the glyph's top-left (pt, 12 x 22), `s1` = segments
|
|
// a b c d, `s2` = e f g.
|
|
mod.widgets.HwPlate.draw_bg.seg_box = fn(q: vec2, c: vec2, h: vec2) -> float {
|
|
let d = abs(q - c) - h
|
|
return 1.0 - smoothstep(-0.35, 0.35, max(d.x, d.y))
|
|
}
|
|
mod.widgets.HwPlate.draw_bg.glyph7 = fn(q: vec2, s1: vec4, s2: vec3) -> float {
|
|
var m = self.seg_box(q, vec2(6.0, 1.5), vec2(3.6, 1.5)) * s1.x
|
|
m = max(m, self.seg_box(q, vec2(10.5, 5.8), vec2(1.5, 3.7)) * s1.y)
|
|
m = max(m, self.seg_box(q, vec2(10.5, 16.2), vec2(1.5, 3.7)) * s1.z)
|
|
m = max(m, self.seg_box(q, vec2(6.0, 20.5), vec2(3.6, 1.5)) * s1.w)
|
|
m = max(m, self.seg_box(q, vec2(1.5, 16.2), vec2(1.5, 3.7)) * s2.x)
|
|
m = max(m, self.seg_box(q, vec2(1.5, 5.8), vec2(1.5, 3.7)) * s2.y)
|
|
m = max(m, self.seg_box(q, vec2(6.0, 11.0), vec2(3.6, 1.5)) * s2.z)
|
|
return m
|
|
}
|
|
mod.widgets.HwPlate.draw_bg.surface = fn(p: vec2, base: vec3) -> vec3 {
|
|
let w = self.world.xy
|
|
// Hammertone: a dimpled metallic enamel, each dimple lit by the key light.
|
|
let lt0 = normalize(self.light.xy + vec2(0.000001, 0.000001))
|
|
let n1 = self.hw_noise(w * 0.16)
|
|
let n1s = self.hw_noise((w - lt0 * 1.6) * 0.16)
|
|
let n2 = self.hw_noise(w * 0.42 + vec2(17.0, 3.0))
|
|
let n2s = self.hw_noise((w - lt0 * 0.8) * 0.42 + vec2(17.0, 3.0))
|
|
var col = base * (0.92 + n1 * 0.12)
|
|
col = col + vec3(0.30, 0.34, 0.31) * ((n1 - n1s) * 0.55 + (n2 - n2s) * 0.25)
|
|
col = col * (1.0 + (self.hw_hash(floor(w * 2.0)) - 0.5) * 0.04)
|
|
// Chips in the enamel near the edges, showing primer red.
|
|
let e = min(min(p.x, p.y), min(self.rect_size.x - p.x, self.rect_size.y - p.y)) - self.inset
|
|
let chip = step(0.82, self.hw_noise(w * 0.22 + vec2(5.0, 11.0))) * (1.0 - smoothstep(2.0, 6.0, e))
|
|
col = mix(col, vec3(0.42, 0.18, 0.12), chip * 0.8)
|
|
// The right wing carries the instrument's type number, stencilled in
|
|
// white paint, and the red OTK inspector's stamp.
|
|
if self.rect_size.y > 380.0 && self.plate_id > 1.5 && self.plate_id < 2.5 {
|
|
let o = vec2(self.rect_size.x * 0.5 - 52.0, self.rect_size.y - self.inset - 88.0)
|
|
let q = (p - o) / 1.35
|
|
var st = self.glyph7(q, vec4(1.0, 0.0, 0.0, 1.0), vec3(1.0, 1.0, 0.0))
|
|
st = max(st, self.glyph7(q - vec2(16.0, 0.0), vec4(0.0, 1.0, 1.0, 0.0), vec3(0.0, 0.0, 0.0)))
|
|
st = max(st, self.glyph7(q - vec2(30.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0)))
|
|
st = max(st, self.glyph7(q - vec2(46.0, 0.0), vec4(1.0, 1.0, 1.0, 0.0), vec3(0.0, 0.0, 0.0)))
|
|
st = max(st, self.glyph7(q - vec2(62.0, 0.0), vec4(1.0, 1.0, 1.0, 1.0), vec3(0.0, 0.0, 1.0)))
|
|
let wear = smoothstep(0.25, 0.45, self.hw_noise(w * 0.9) * 0.5 + self.hw_noise(w * 0.2) * 0.5)
|
|
col = mix(col, vec3(0.86, 0.84, 0.76), st * wear * 0.9)
|
|
// The stamp: an oval ring of red ink with smudged letters inside.
|
|
let sc = vec2(self.rect_size.x * 0.5, self.rect_size.y - self.inset - 30.0)
|
|
let sv = (p - sc) / vec2(22.0, 13.0)
|
|
let sr = length(sv)
|
|
let ring = 1.0 - smoothstep(0.08, 0.14, abs(sr - 0.92))
|
|
let letters = step(abs(sv.y), 0.35) * step(abs(sv.x), 0.62) * step(0.5, fract(p.x / 4.2 + self.hw_noise(p * 0.5) * 0.3)) * step(0.3, self.hw_noise(p * 0.7))
|
|
let ink = clamp(ring + letters * 0.8, 0.0, 1.0) * (0.55 + 0.45 * self.hw_noise(p * 0.6))
|
|
col = mix(col, vec3(0.62, 0.10, 0.08), ink * 0.75)
|
|
}
|
|
// A hex bolt with a washer at each corner.
|
|
let m = self.inset + 12.0
|
|
let qx = mix(m, self.rect_size.x - m, step(self.rect_size.x * 0.5, p.x))
|
|
let qy = mix(m, self.rect_size.y - m, step(self.rect_size.y * 0.5, p.y))
|
|
let v = p - vec2(qx, qy)
|
|
let r = length(v)
|
|
let lt = normalize(self.light.xy + vec2(0.000001, 0.000001))
|
|
// Washer: a turned steel ring.
|
|
let washer = 1.0 - smoothstep(8.0, 8.8, r)
|
|
let wsh = 0.5 + 0.5 * dot(v / max(r, 0.001), -lt)
|
|
col = col * (1.0 - (1.0 - smoothstep(8.6, 11.5, r)) * smoothstep(8.0, 8.6, r) * 0.45)
|
|
col = mix(col, vec3(0.36, 0.37, 0.35) * (0.75 + 0.5 * wsh), washer)
|
|
// The hex head: six facets, each shaded by the key light, a flat top.
|
|
let ang = atan2(v.y, v.x)
|
|
let sec = floor(ang / 1.0472 + 0.5) * 1.0472
|
|
let fn0 = vec2(cos(sec), sin(sec))
|
|
let hd = dot(v, fn0)
|
|
let hexm = 1.0 - smoothstep(5.6, 6.3, hd)
|
|
let top = 1.0 - smoothstep(3.6, 4.4, r)
|
|
let facet = 0.55 + 0.6 * dot(fn0, -lt)
|
|
var bolt = vec3(0.30, 0.31, 0.30) * facet
|
|
bolt = mix(bolt, vec3(0.40, 0.41, 0.39) * (1.0 + dot(v, -lt) * 0.05), top)
|
|
col = mix(col, bolt, hexm)
|
|
return col
|
|
}
|
|
|
|
// ---- recessed panels: a dark green-grey well ----
|
|
mod.widgets.HwPanel.radius = 3
|
|
mod.widgets.HwPanel.depth = -3.5
|
|
mod.widgets.HwPanel.draw_bg.ground = #x2a312c
|
|
mod.widgets.HwPanel.draw_bg.light_ink = vec4(0.70, 0.76, 0.70, 1.0)
|
|
mod.widgets.HwPanel.draw_bg.shadow_ink = vec4(0.0, 0.0, 0.0, 1.0)
|
|
mod.widgets.HwPanel.draw_bg.pattern = vec4(4.0, 0.9, 0.16, 0.0)
|
|
mod.widgets.HwPanel.draw_bg.inner = vec4(0.95, 11.0, 0.0, 0.6)
|
|
mod.widgets.HwPanel.draw_bg.finish = vec4(0.8, 0.3, 0.05, 0.9)
|
|
mod.widgets.HwPanel.draw_bg.glow_ink = vec4(1.0, 0.36, 0.08, 1.0)
|
|
mod.widgets.HwPanel.draw_bg.spill = vec2(1.6, 0.7)
|
|
|
|
// ---- the screen's surround: black crackle paint, very deep ----
|
|
mod.widgets.HwBezel.radius = 6
|
|
mod.widgets.HwBezel.depth = -6.0
|
|
mod.widgets.HwBezel.draw_bg.ground = #x1a1c1a
|
|
mod.widgets.HwBezel.draw_bg.light_ink = vec4(0.60, 0.62, 0.58, 1.0)
|
|
mod.widgets.HwBezel.draw_bg.shadow_ink = vec4(0.0, 0.0, 0.0, 1.0)
|
|
mod.widgets.HwBezel.draw_bg.inner = vec4(1.0, 16.0, 0.0, 0.6)
|
|
mod.widgets.HwBezel.draw_bg.spill = vec2(1.9, 0.5)
|
|
mod.widgets.HwBezel.draw_bg.glow_ink = vec4(1.0, 0.36, 0.08, 1.0)
|
|
mod.widgets.HwBezel.draw_bg.surface = fn(p: vec2, base: vec3) -> vec3 {
|
|
// Crackle finish: wrinkled black paint, lit on its ridges.
|
|
let w = self.world.xy
|
|
let n = self.hw_noise(w * 0.5) * 0.5 + self.hw_noise(w * 1.3) * 0.5
|
|
let ridge = 1.0 - abs(n - 0.5) * 2.0
|
|
return base * (0.8 + 0.5 * smoothstep(0.7, 0.95, ridge))
|
|
}
|
|
|
|
// ---- the glass: a warm smoked pane with the faint mesh of a Nixie anode ----
|
|
mod.widgets.HwGlass.draw_bg.glass = vec4(0.0, 0.10, 0.55, 0.05)
|
|
mod.widgets.HwGlass.draw_bg.tint = vec4(1.0, 0.62, 0.35, 0.0)
|
|
mod.widgets.HwGlass.draw_bg.radius = 4.0
|
|
mod.widgets.HwGlass.draw_bg.pixel = fn() {
|
|
let p = self.pos * self.rect_size
|
|
let c = self.rect_size * 0.5
|
|
let d = Material.sd_box(p, c, c, self.radius)
|
|
let px = 1.0 / max(self.draw_pass.dpi_factor, 0.5)
|
|
let cov = 1.0 - smoothstep(-px, px, d)
|
|
// Rim darkening and the tube's corners.
|
|
let edge = smoothstep(-34.0, 0.0, d) * self.glass.z
|
|
let qq = (self.pos - vec2(0.5, 0.5)) * 2.0
|
|
let bulge = clamp(dot(qq * qq, qq * qq) * self.glass.w, 0.0, 1.0)
|
|
let dark = clamp(edge + bulge, 0.0, 1.0)
|
|
// A reflection of the lab's strip light across the top.
|
|
let rl = (1.0 - smoothstep(0.0, 0.012, abs(self.pos.y - 0.10 + (self.pos.x - 0.5) * 0.06))) * 0.06 * (1.0 - smoothstep(0.3, 0.5, abs(self.pos.x - 0.45))) + smoothstep(0.55, 0.0, self.pos.y) * self.glass.y * 0.5
|
|
let o = vec4(vec3(1.0, 0.92, 0.82) * rl, rl) * cov + vec4(0.0, 0.0, 0.0, dark * cov) * (1.0 - rl)
|
|
return o
|
|
}
|
|
|
|
// ---- keys: brown bakelite, glossy, a red PUSK key ----
|
|
mod.widgets.HwKey.depth = 3.5
|
|
mod.widgets.HwKey.press = -3.0
|
|
mod.widgets.HwKey.radius = 3
|
|
mod.widgets.HwKey.draw_bg.ground = #x3b2519
|
|
mod.widgets.HwKey.draw_bg.light_ink = vec4(1.0, 0.92, 0.82, 1.0)
|
|
mod.widgets.HwKey.draw_bg.shadow_ink = vec4(0.02, 0.01, 0.0, 1.0)
|
|
mod.widgets.HwKey.draw_bg.relief = vec4(3.2, 0.6, 3.0, 0.55)
|
|
mod.widgets.HwKey.draw_bg.finish = vec4(0.7, 0.45, 0.45, 0.35)
|
|
mod.widgets.HwKey.draw_bg.shadow = vec4(0.85, 6.0, 1.0, 0.8)
|
|
mod.widgets.HwKey.draw_bg.glow_ink = vec4(1.0, 0.36, 0.08, 1.0)
|
|
mod.widgets.HwKey.draw_bg.spill = vec2(2.6, 0.6)
|
|
mod.widgets.HwKey.draw_bg.inner = vec4(0.72, 9.0, 0.0, 0.10)
|
|
mod.widgets.HwKey.emissive = vec4(1.0, 0.34, 0.06, 0.35)
|
|
mod.widgets.HwKey.draw_bg.led = vec4(7.0, 7.0, 2.6, 1.0)
|
|
mod.widgets.HwKey.draw_bg.led_off = vec4(0.22, 0.10, 0.05, 1.0)
|
|
mod.widgets.HwKey.draw_bg.critical_ink = vec4(0.62, 0.07, 0.04, 0.0)
|
|
mod.widgets.HwKey.draw_bg.surface = fn(p: vec2, base: vec3) -> vec3 {
|
|
// Bakelite: a mottled, swirled phenolic brown.
|
|
let w = self.world.xy
|
|
let sw = self.hw_noise(w * 0.09 + vec2(self.hw_noise(w * 0.05) * 4.0, 0.0))
|
|
var col = base * (0.82 + sw * 0.36)
|
|
col = col + vec3(0.05, 0.02, 0.0) * smoothstep(0.6, 0.85, self.hw_noise(w * 0.2 + vec2(9.0, 2.0)))
|
|
return col
|
|
}
|
|
mod.widgets.HwKey.draw_bg.pixel = fn() {
|
|
let p = self.pos * self.rect_size
|
|
// Critical keys (play, presets) are cast in red bakelite.
|
|
let g = mix(self.ground.xyz, vec3(0.50, 0.07, 0.04), self.critical)
|
|
var o = self.layer(self.key_face(p, g))
|
|
o = self.key_marks(o, p)
|
|
return vec4(o.xyz + self.dither() * step(0.002, o.w), o.w)
|
|
}
|
|
mod.widgets.HwKeyButton.draw_text.color = #xe6d8b8
|
|
mod.widgets.HwKeyButton.draw_text.color_hover = #xffb080
|
|
mod.widgets.HwKeyButton.draw_text.color_down = #xff7a30
|
|
mod.widgets.HwKeyText.draw_text.color = #xe6d8b8
|
|
mod.widgets.HwKeyText.draw_text.color_hover = #xffb080
|
|
mod.widgets.HwKeyText.draw_text.color_down = #xff7a30
|
|
mod.widgets.HwKeyText.draw_text.text_style = theme.font_bold{font_size: 9.0}
|
|
|
|
// ---- lights: neon glow lamps ----
|
|
mod.widgets.HwDash.emissive = vec4(1.0, 0.34, 0.06, 9.0)
|
|
mod.widgets.HwDash.radius = 6
|
|
mod.widgets.HwDash.draw_bg.glow_ink = vec4(1.0, 0.40, 0.10, 1.0)
|
|
mod.widgets.HwDash.draw_bg.ground = #x1c0f09
|
|
mod.widgets.HwLed.emissive = vec4(1.0, 0.34, 0.06, 4.0)
|
|
mod.widgets.HwLed.draw_bg.glow_ink = vec4(1.0, 0.40, 0.10, 1.0)
|
|
|
|
// ---- knob: a fluted bakelite knob with a cream line, neon dots round it ----
|
|
mod.widgets.HwKnobFace.draw_bg.ground = #x2c1c13
|
|
mod.widgets.HwKnobFace.draw_bg.light_ink = vec4(1.0, 0.90, 0.78, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.shadow_ink = vec4(0.0, 0.0, 0.0, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.relief = vec4(4.0, 0.8, 3.0, 0.55)
|
|
mod.widgets.HwKnobFace.draw_bg.knob = vec4(1.0, 0.66, 16.0, 0.55)
|
|
mod.widgets.HwKnobFace.draw_bg.cap_ink = vec4(0.26, 0.15, 0.09, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.ptr_ink = vec4(0.93, 0.87, 0.72, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.ring = vec4(11.0, 1.30, 2.8, 2.35619)
|
|
mod.widgets.HwKnobFace.draw_bg.led_off = vec4(0.20, 0.10, 0.06, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.glow_ink = vec4(1.0, 0.40, 0.10, 1.0)
|
|
mod.widgets.HwKnobFace.draw_bg.shadow = vec4(0.9, 12.0, 1.0, 0.85)
|
|
mod.widgets.HwKnobFace.emissive = vec4(1.0, 0.34, 0.06, 0.8)
|
|
mod.widgets.HwKnobFace.draw_bg.spill = vec2(0.4, 0.5)
|
|
|
|
// ---- meter: a mirror-scale panel ammeter ----
|
|
mod.widgets.HwMeterFace.depth = -3.0
|
|
mod.widgets.HwMeterFace.radius = 3
|
|
mod.widgets.HwMeterFace.draw_bg.ground = #x1b1d1b
|
|
mod.widgets.HwMeterFace.draw_bg.dial_ink = vec4(0.91, 0.87, 0.76, 1.0)
|
|
mod.widgets.HwMeterFace.draw_bg.glow_ink = vec4(1.0, 0.40, 0.10, 1.0)
|
|
mod.widgets.HwMeterFace.draw_bg.hot_ink = vec4(0.75, 0.08, 0.04, 1.0)
|
|
mod.widgets.HwMeterFace.emissive = vec4(1.0, 0.45, 0.15, 0.35)
|
|
mod.widgets.HwMeterFace.draw_bg.pixel = fn() {
|
|
let p = self.pos * self.rect_size
|
|
let px = 1.0 / max(self.draw_pass.dpi_factor, 0.5)
|
|
var o = self.layer(self.surface(p, self.ground.xyz))
|
|
let a = vec2(6.0, 6.0)
|
|
let b = self.rect_size - a
|
|
let inside = step(a.x, p.x) * step(p.x, b.x) * step(a.y, p.y) * step(p.y, b.y)
|
|
let u = (p - a) / max(b - a, vec2(1.0, 1.0))
|
|
let h = b.y - a.y
|
|
// A yellowed paper dial, lit a little warm from the neon behind.
|
|
var dial = self.dial_ink.xyz * (0.92 + 0.08 * self.hw_noise(p * 0.3))
|
|
dial = dial * (1.0 - 0.18 * u.y)
|
|
// The pivot far below: a long flat arc across the dial.
|
|
let piv = vec2(self.rect_size.x * 0.5, b.y + h * 2.3)
|
|
let q = p - piv
|
|
let rq = length(q)
|
|
let ang = atan2(q.x, -q.y)
|
|
let sw = 0.55
|
|
let rr = piv.y - a.y - h * 0.30
|
|
let insw = step(abs(ang), sw)
|
|
// The mirror band under the scale, for reading without parallax.
|
|
let mirror = step(rr - 7.5, rq) * step(rq, rr - 4.0) * insw
|
|
let mref = 0.35 + 0.5 * smoothstep(-sw, sw, ang + sin(rq * 0.2) * 0.02)
|
|
dial = mix(dial, vec3(0.62, 0.66, 0.68) * mref, mirror)
|
|
// Ticks: fifty minor, ten major, a red zone at the top end.
|
|
let arc = (1.0 - smoothstep(0.3, 0.3 + px, abs(rq - rr))) * insw
|
|
let t = (ang + sw) / (sw * 2.0)
|
|
let tm = abs(fract(t * 50.0 + 0.5) - 0.5) / 50.0 * (sw * 2.0) * rq
|
|
let tM = abs(fract(t * 10.0 + 0.5) - 0.5) / 10.0 * (sw * 2.0) * rq
|
|
let minor = (1.0 - smoothstep(0.35, 0.35 + px, tm)) * step(rr, rq) * step(rq, rr + 4.0) * insw
|
|
let major = (1.0 - smoothstep(0.6, 0.6 + px, tM)) * step(rr - 3.0, rq) * step(rq, rr + 8.0) * insw
|
|
let ink = vec3(0.08, 0.07, 0.06)
|
|
dial = mix(dial, ink, clamp(arc + minor + major, 0.0, 1.0))
|
|
let red = step(0.78, t) * insw * step(rr + 0.5, rq) * step(rq, rr + 3.2)
|
|
dial = mix(dial, self.hot_ink.xyz, red)
|
|
// The ammeter's letter A, printed under the scale.
|
|
let ac = vec2(self.rect_size.x * 0.5, a.y + h * 0.80)
|
|
let aq = p - ac
|
|
let pa1 = aq - vec2(0.0, -5.0)
|
|
let ba1 = vec2(-3.6, 10.0)
|
|
let ba2 = vec2(3.6, 10.0)
|
|
let d1 = length(pa1 - ba1 * clamp(dot(pa1, ba1) / dot(ba1, ba1), 0.0, 1.0))
|
|
let d2 = length(pa1 - ba2 * clamp(dot(pa1, ba2) / dot(ba2, ba2), 0.0, 1.0))
|
|
let d3 = max(abs(aq.y - 1.6) - 0.5, abs(aq.x) - 2.2)
|
|
let glyph = 1.0 - smoothstep(0.65 - px, 0.65 + px, min(min(d1, d2), d3 + 0.65))
|
|
dial = mix(dial, vec3(0.08, 0.07, 0.06), glyph * 0.9)
|
|
// The knife-edge needle, and its shadow on the paper.
|
|
let lv = clamp(max(self.level.x, self.level.y), 0.0, 1.05)
|
|
let na = (lv * 2.0 - 1.0) * sw
|
|
let dir = vec2(sin(na), -cos(na))
|
|
let t0 = rr - h * 0.9
|
|
let qs = q - vec2(2.0, 2.0)
|
|
let ts = clamp(dot(qs, dir), t0, rr + 9.0)
|
|
let sd = length(qs - dir * ts)
|
|
dial = dial * (1.0 - (1.0 - smoothstep(0.0, 2.8, sd)) * 0.28 * inside)
|
|
let tn = clamp(dot(q, dir), t0, rr + 9.0)
|
|
let nd = length(q - dir * tn) - mix(0.9, 0.45, clamp((tn - t0) / (rr + 9.0 - t0), 0.0, 1.0))
|
|
dial = mix(dial, vec3(0.05, 0.04, 0.03), 1.0 - smoothstep(-px, px, nd))
|
|
// Glass: a strip of light across the top, a dark rim.
|
|
dial = dial + vec3(1.0, 0.97, 0.9) * (1.0 - smoothstep(0.0, 0.3, u.y)) * 0.08
|
|
let e = min(min(u.x, 1.0 - u.x) * (b.x - a.x), min(u.y, 1.0 - u.y) * h)
|
|
dial = dial * (0.5 + 0.5 * smoothstep(0.0, 6.0, e))
|
|
dial = dial + self.env_spill(vec3(0.0, 0.0, 1.0)) * 0.15
|
|
o = vec4(mix(o.xyz, dial, inside), o.w)
|
|
return vec4(o.xyz + self.dither() * step(0.002, o.w), o.w)
|
|
}
|
|
|
|
// ---- displays: Nixie windows, orange digits behind a hex mesh ----
|
|
mod.widgets.HwDisplay.radius = 3
|
|
mod.widgets.HwDisplay.draw_bg.ground = #x120c09
|
|
mod.widgets.HwDisplay.draw_bg.light_ink = vec4(0.60, 0.62, 0.58, 1.0)
|
|
mod.widgets.HwDisplay.draw_bg.shadow_ink = vec4(0.0, 0.0, 0.0, 1.0)
|
|
mod.widgets.HwDisplay.draw_bg.inner = vec4(1.0, 10.0, 0.0, 0.6)
|
|
mod.widgets.HwDisplay.draw_bg.spill = vec2(0.9, 0.4)
|
|
mod.widgets.HwDisplay.draw_bg.surface = fn(p: vec2, base: vec3) -> vec3 {
|
|
let q = p / 4.0
|
|
let s = vec2(1.0, 1.732)
|
|
let a = q - s * floor(q / s) - s * 0.5
|
|
let q2 = q - s * 0.5
|
|
let b = q2 - s * floor(q2 / s) - s * 0.5
|
|
let g = mix(a, b, step(dot(b, b), dot(a, a)))
|
|
let ag = abs(g)
|
|
let hd = max(ag.x * 0.5 + ag.y * 0.866, ag.x)
|
|
let wire = 1.0 - smoothstep(0.04, 0.12, 0.5 - hd)
|
|
return base + vec3(0.07, 0.035, 0.018) * wire
|
|
}
|
|
mod.widgets.HwDisplayText.draw_text.color = #xff7a2a
|
|
mod.widgets.HwDisplayText.draw_text.text_style = theme.font_code{font_size: 10.5}
|
|
|
|
// ---- the spectrum: a row of IN-9 neon bargraph tubes ----
|
|
mod.widgets.HwSpectrum.light = 9.0
|
|
// Parts by `self.part` (1 well, 2 rule, 3 slot, 4 bar, 5 peak, 6 midline).
|
|
mod.widgets.HwSpectrum.draw_round.pixel = fn() {
|
|
let p = self.pos * self.rect_size
|
|
let s = self.rect_size
|
|
let px = 1.0 / max(self.draw_pass.dpi_factor, 0.5)
|
|
if self.part > 0.5 && self.part < 1.5 {
|
|
// The well: smoked glass behind the tubes.
|
|
let sdf = Sdf2d.viewport(p)
|
|
sdf.box(0.0, 0.0, s.x, s.y, 4.0)
|
|
let v = (self.pos.y - 0.5)
|
|
let haze = vec3(0.06, 0.018, 0.002) * smoothstep(0.1, 0.75, self.pos.y) * (1.0 - smoothstep(0.75, 1.0, self.pos.y))
|
|
sdf.fill(vec4(self.color.xyz * (1.0 - v * 0.3) + haze, self.color.w))
|
|
return sdf.result
|
|
}
|
|
if (self.part > 1.5 && self.part < 2.5) || self.part > 4.5 {
|
|
if self.part < 4.5 || self.part > 5.5 {
|
|
// Graticule rules: dashed, like a printed scale.
|
|
let dash = step(0.5, fract(p.x / 6.0))
|
|
let ra = self.color.w * 1.8 * dash
|
|
return vec4(self.color.xyz * ra, ra)
|
|
}
|
|
// Peak marks: the glowing cathode tip, left behind.
|
|
let c = abs(p.x - s.x * 0.5) / max(s.x * 0.5, 0.5)
|
|
let a = (1.0 - c * c) * 0.9
|
|
return vec4(vec3(1.0, 0.62, 0.30) * a, a)
|
|
}
|
|
let x = abs(p.x - s.x * 0.5) / max(s.x * 0.5, 0.5)
|
|
let base_h = 5.0
|
|
if self.part > 2.5 && self.part < 3.5 {
|
|
// An unlit IN-9 tube: a glass cylinder with a bright rim, a glint
|
|
// down one side, the cathode wire in its axis, a round top and a
|
|
// black socket at the foot.
|
|
let top = clamp(1.0 - (p.y - s.x * 0.5) / max(s.x * 0.5, 0.5), 0.0, 1.0)
|
|
let rr = length(vec2(x, max(top, 0.0)))
|
|
let inside = 1.0 - smoothstep(0.92, 1.0, rr)
|
|
let rim = smoothstep(0.55, 0.95, rr) * inside
|
|
let glint = (1.0 - smoothstep(0.0, 0.12, abs(p.x - s.x * 0.28) / max(s.x, 1.0) * 2.0)) * inside
|
|
let wire = (1.0 - smoothstep(0.0, 0.14, x)) * inside
|
|
let gl = rim * 0.30 + glint * 0.22 + 0.05
|
|
var col = vec3(0.70, 0.64, 0.56) * gl + vec3(0.55, 0.28, 0.12) * wire * 0.25
|
|
var al = clamp(gl + wire * 0.2, 0.0, 1.0) * inside
|
|
let sock = step(s.y - base_h, p.y)
|
|
col = mix(col, vec3(0.13, 0.12, 0.11) * (0.6 + 0.6 * (1.0 - x)) + vec3(0.25, 0.22, 0.2) * (1.0 - smoothstep(0.0, 1.2, p.y - (s.y - base_h))), sock)
|
|
al = mix(al, 1.0, sock)
|
|
return vec4(col * al, al)
|
|
}
|
|
// A lit column of neon: a white-hot core in a saturated orange sheath
|
|
// that fades to the glass, brightest at the glowing end.
|
|
if p.y > s.y - base_h {
|
|
return vec4(0.0, 0.0, 0.0, 0.0)
|
|
}
|
|
let neon = mix(vec3(1.0, 0.27, 0.04), self.color.xyz, 0.15)
|
|
let core = exp(-x * x * 14.0)
|
|
let sheath = exp(-x * x * 4.0)
|
|
let tip = exp(-p.y / 3.0)
|
|
let hot = clamp(core * 0.55 + tip * 0.9, 0.0, 1.0)
|
|
let col = neon * (0.45 + sheath * 0.8) + vec3(1.0, 0.78, 0.50) * hot * 0.5
|
|
let al = clamp(sheath * 0.92 + tip * 0.4 + 0.08, 0.0, 1.0)
|
|
return vec4(col * al, al)
|
|
}
|
|
mod.widgets.HwSpectrum.draw_line.pixel = fn() {
|
|
// The waveform: an oscilloscope trace with a neon bloom.
|
|
let p = self.pos * self.rect_size
|
|
let a = self.seg_a
|
|
let b = self.seg_b
|
|
let pa = p - a
|
|
let ba = b - a
|
|
let h = clamp(dot(pa, ba) / max(dot(ba, ba), 0.0001), 0.0, 1.0)
|
|
let d = length(pa - ba * h)
|
|
let core = 1.0 - smoothstep(0.2, 1.0, d)
|
|
let glow = exp(-d * d / 3.0) * 0.55
|
|
let al = clamp(core + glow, 0.0, 1.0)
|
|
let col = mix(self.color.rgb, vec3(1.0, 0.86, 0.66), core * 0.6)
|
|
return vec4(col * al, al)
|
|
}
|
|
|
|
// ---- the picture lights the front ----
|
|
mod.widgets.HwMilk.light = 2.0
|
|
mod.widgets.HwMilk.light_knee = 0.95
|
|
|
|
// ---- stencilled type ----
|
|
mod.widgets.HwCaption.draw_text.color = #x1d1e1c
|
|
mod.widgets.HwCaption.draw_text.text_style = theme.font_bold{font_size: 8.5}
|
|
mod.widgets.HwTitle.draw_text.color = #x151614
|
|
mod.widgets.HwTitle.draw_text.text_style = theme.font_bold{font_size: 13.5}
|
|
mod.widgets.HwText.draw_text.color = #x2a2b28
|
|
mod.widgets.HwNavButton.draw_text.color = #xd9dccf
|
|
mod.widgets.HwNavButton.draw_text.color_hover = #xffa060
|
|
mod.widgets.HwNavButton.draw_bg.plate = vec4(0.0, 0.0, 0.0, 0.18)
|
|
mod.widgets.HwNavButton.draw_bg.plate_hover = vec4(1.0, 0.45, 0.15, 0.12)
|
|
mod.widgets.HwNavButton.draw_bg.rim = vec4(0.75, 0.82, 0.75, 0.12)
|
|
mod.widgets.HwDropDown.draw_bg.well = vec4(0.07, 0.05, 0.035, 1.0)
|
|
mod.widgets.HwDropDown.draw_bg.rim = vec4(1.0, 0.45, 0.15, 0.25)
|
|
mod.widgets.HwDropDown.draw_bg.arrow = vec4(1.0, 0.48, 0.16, 1.0)
|
|
mod.widgets.HwDropDown.draw_text.color = #xff9a55
|
|
mod.widgets.HwDropDown.draw_text.color_hover = #xffc090
|
|
mod.widgets.HwTextInput.draw_bg.well = vec4(0.07, 0.05, 0.035, 1.0)
|
|
mod.widgets.HwTextInput.draw_bg.rim = vec4(1.0, 0.45, 0.15, 0.25)
|
|
mod.widgets.HwTextInput.draw_text.color = #xffa060
|
|
mod.widgets.HwSegmented.draw_bg.rim = vec4(1.0, 0.45, 0.15, 0.18)
|
|
mod.widgets.HwSplitter.draw_bg.groove = vec4(0.0, 0.0, 0.0, 0.5)
|
|
mod.widgets.HwSplitter.draw_bg.glint = vec4(0.8, 0.88, 0.8, 0.15)
|
|
mod.widgets.HwArtBlank.draw_bg.vinyl = vec4(0.05, 0.045, 0.04, 1.0)
|
|
|
|
// ---- the picture in this style's colours (THEME COLOURS key; on by default) ----
|
|
mod.widgets.hw_palette.map0 = #x0a0908
|
|
mod.widgets.hw_palette.map1 = #x4a4640
|
|
mod.widgets.hw_palette.map2 = #xff6a1a
|
|
mod.widgets.hw_palette.map3 = #xffe0c0
|
|
mod.widgets.hw_palette.map_strength = 0.6
|
|
mod.widgets.hw_palette.map_default = 1.0
|
|
// The screen filter with the THEME COLOURS key: CRT: a bulging tube, scanlines, an RGB mask, bloom.
|
|
mod.widgets.hw_palette.screen_filter = 1.0
|
|
mod.widgets.hw_palette.screen_filter_strength = 0.9
|
|
mod.widgets.hw_palette.screen_cell = 3.0
|
|
mod.widgets.hw_palette.screen_curve = 0.08
|
|
true
|
|
|
|
// ---- EQ (HwEqGraph: the graphic equalizer's era look, STYLE_GUIDE "Graphic EQ") ----
|
|
mod.widgets.HwEqGraph.draw_fader.fader = vec4(1.0, 0.50, 6.0, 3.0)
|
|
mod.widgets.HwEqGraph.draw_fader.segments = vec4(5.0, 2.0, 0.0, 0.0)
|
|
mod.widgets.HwEqGraph.draw_fader.led_off = vec4(0.12, 0.06, 0.03, 1.0)
|
|
mod.widgets.HwEqGraph.draw_curve.curve = vec4(1.0, 1.8, 7.0, 0.08)
|
|
mod.widgets.HwEqGraph.draw_grid.grid = vec4(3.0, 0.10, 0.30, 0.0)
|
|
mod.widgets.HwEqGraph.draw_spectrum.spectrum = vec4(0.16, 0.0, 0.25, 0.0)
|
|
mod.widgets.HwEqGraph.light = 1.0
|
|
true
|