Compare commits

...

2 Commits

Author SHA1 Message Date
minjaesong
10e577699f taut: undefaulting things 2026-05-27 14:04:28 +09:00
minjaesong
01cc5c90ee taut: better fil8l 2026-05-27 11:33:01 +09:00
3 changed files with 109 additions and 29 deletions

View File

@@ -3356,7 +3356,7 @@ function sampleWaveformRect() {
function clearSampleWaveformArea() { function clearSampleWaveformArea() {
const r = sampleWaveformRect() const r = sampleWaveformRect()
graphics.plotRect(r.x, r.y, r.w, r.h, 255) // 255 = transparent graphics.plotRect(r.x-2, r.y-2, r.w+4, r.h+4, 255) // 255 = transparent
} }
function drawSampleWaveform() { function drawSampleWaveform() {
@@ -3364,7 +3364,7 @@ function drawSampleWaveform() {
const wx0 = r.x, wy0 = r.y, wW = r.w, wH = r.h const wx0 = r.x, wy0 = r.y, wW = r.w, wH = r.h
// Clear waveform area to transparent (255 = transparent against text bg) // Clear waveform area to transparent (255 = transparent against text bg)
graphics.plotRect(wx0, wy0, wW, wH, 255) clearSampleWaveformArea()
const s = (samplesCache && samplesCache[smpListCursor]) || null const s = (samplesCache && samplesCache[smpListCursor]) || null
if (!s || s.len === 0) return if (!s || s.len === 0) return
@@ -3665,7 +3665,9 @@ const colInstEnvNode = 198 // pink-ish — node markers stand out f
const colInstEnvAxis = 246 // dim grey for zero/center line const colInstEnvAxis = 246 // dim grey for zero/center line
const colInstEnvHair = 251 // darker grey — quarter-point hairlines (dashed) const colInstEnvHair = 251 // darker grey — quarter-point hairlines (dashed)
const colInstEnvLoop = 220 // muted yellow-orange — loop range band const colInstEnvLoop = 220 // muted yellow-orange — loop range band
const colInstEnvSust = 161 // muted red — sustain range band const colInstEnvSust = 145 // muted yellow-green — loop range band
const colInstEnvLoopSuper= 230 // muted yellow-orange — loop range band
const colInstEnvSustSuper= 155 // muted yellow-green — loop range band
let instListScroll = 0 let instListScroll = 0
let instListCursor = 0 let instListCursor = 0
@@ -3931,7 +3933,7 @@ function instEnvelopeRect() {
// the instrument viewer (mirrors clearSampleWaveformArea for the same reason). // the instrument viewer (mirrors clearSampleWaveformArea for the same reason).
function clearInstrumentsEnvelopeArea() { function clearInstrumentsEnvelopeArea() {
const r = instEnvelopeRect() const r = instEnvelopeRect()
graphics.plotRect(r.x, r.y, r.w, r.h, 255) graphics.plotRect(r.x-2, r.y-2, r.w+4, r.h+4, 255)
// Also clear the row of text that the graph overlays would otherwise visually // Also clear the row of text that the graph overlays would otherwise visually
// smudge — the body redraw paints these rows blank anyway, but switchToPanel // smudge — the body redraw paints these rows blank anyway, but switchToPanel
// bypasses the body redraw on exit. // bypasses the body redraw on exit.
@@ -3962,7 +3964,7 @@ function envPlotLine(x0, y0, x1, y1, col) {
// Value axis: 0 at bottom, env.valueMax at top. // Value axis: 0 at bottom, env.valueMax at top.
function drawEnvelopeGraph(env) { function drawEnvelopeGraph(env) {
const r = instEnvelopeRect() const r = instEnvelopeRect()
graphics.plotRect(r.x, r.y, r.w, r.h, 255) // clear clearInstrumentsEnvelopeArea() // clear
// Dashed reference hairlines at quarter points of the value range. Drawn // Dashed reference hairlines at quarter points of the value range. Drawn
// first so the solid axis line / loop bands / polyline can stack on top. // first so the solid axis line / loop bands / polyline can stack on top.
@@ -4026,13 +4028,19 @@ function drawEnvelopeGraph(env) {
const x0 = pxX(xs[env.loopStart]) const x0 = pxX(xs[env.loopStart])
const x1 = pxX(xs[env.loopEnd]) const x1 = pxX(xs[env.loopEnd])
const bw = Math.max(1, x1 - x0) const bw = Math.max(1, x1 - x0)
graphics.plotRect(x0, r.y, bw, r.h, colInstEnvLoop) graphics.plotRect(x0, r.y, bw, r.h, colInstEnvLoop, 2)
// start & end hairline
graphics.plotRect(x0, r.y, 1, r.h, colInstEnvLoopSuper)
graphics.plotRect(x1, r.y, 1, r.h, colInstEnvLoopSuper)
} }
if (env.sustEnable && env.sustStart <= lastIdx && env.sustEnd <= lastIdx) { if (env.sustEnable && env.sustStart <= lastIdx && env.sustEnd <= lastIdx) {
const x0 = pxX(xs[env.sustStart]) const x0 = pxX(xs[env.sustStart])
const x1 = pxX(xs[env.sustEnd]) const x1 = pxX(xs[env.sustEnd])
const bw = Math.max(1, x1 - x0) const bw = Math.max(1, x1 - x0)
graphics.plotRect(x0, r.y, bw, r.h, colInstEnvSust) graphics.plotRect(x0, r.y, bw, r.h, colInstEnvSust, 2)
// start & end hairline
graphics.plotRect(x0, r.y, 1, r.h, colInstEnvSustSuper)
graphics.plotRect(x1, r.y, 1, r.h, colInstEnvSustSuper)
} }
// Polyline through the envelope. // Polyline through the envelope.
@@ -4621,8 +4629,8 @@ function openConfirmQuit() {
colours: popupColours, colours: popupColours,
message: messageLines, message: messageLines,
buttons: [ buttons: [
{ label: 'Yes', action: 'yes', default: true }, { label: 'Yes', action: 'yes' },
{ label: 'No', action: 'no' }, { label: 'No', action: 'no', default: true },
], ],
onKey: (ks, _shift, ctx) => { onKey: (ks, _shift, ctx) => {
if (ks === 'y' || ks === 'Y') { ctx.close({ action: 'yes' }); return true } if (ks === 'y' || ks === 'Y') { ctx.close({ action: 'yes' }); return true }
@@ -4644,9 +4652,9 @@ function openGotoPopup() {
title: 'Go To', title: 'Go To',
drawFrame: popupDrawFrame, drawFrame: popupDrawFrame,
colours: popupColours, colours: popupColours,
fields: [{ label: promptStr, width: 3, maxLength: 3 }], fields: [{ label: promptStr, width: 4, maxLength: 3 }],
buttons: [ buttons: [
{ label: 'OK', action: 'ok', default: true }, { label: 'OK', action: 'ok' },
{ label: 'Cancel', action: 'cancel' }, { label: 'Cancel', action: 'cancel' },
], ],
}) })
@@ -4714,7 +4722,7 @@ function openRetunePopup() {
}, },
}, },
buttons: [ buttons: [
{ label: 'OK', action: 'ok', default: true }, { label: 'OK', action: 'ok' },
{ label: 'Cancel', action: 'cancel' }, { label: 'Cancel', action: 'cancel' },
], ],
onKey: (ks, _shift, ctx) => { onKey: (ks, _shift, ctx) => {
@@ -4803,7 +4811,7 @@ function openFlagsPopup() {
}, },
}, },
buttons: [ buttons: [
{ label: 'OK', action: 'ok', default: true }, { label: 'OK', action: 'ok' },
{ label: 'Cancel', action: 'cancel' }, { label: 'Cancel', action: 'cancel' },
], ],
}) })

View File

@@ -336,7 +336,7 @@ function showDialog(opts) {
const listMinW = hasList const listMinW = hasList
? (list.width != null ? list.width + 4 : longestItem + 6) ? (list.width != null ? list.width + 4 : longestItem + 6)
: 0 : 0
const w = Math.max(maxFieldW + 6, titleW + 4, longestMsg + 6, btnRowW + 4, listMinW, 24) const w = 2+Math.max(maxFieldW + 6, titleW + 4, longestMsg + 6, btnRowW + 4, listMinW, 22)
const msgRows = messageLines.length + (messageLines.length > 0 ? 1 : 0) const msgRows = messageLines.length + (messageLines.length > 0 ? 1 : 0)
const fieldsBlockH = fields.length * 4 const fieldsBlockH = fields.length * 4

View File

@@ -149,37 +149,85 @@ class GraphicsJSR223Delegate(private val vm: VM) {
} }
} }
fun plotRect(x: Int, y: Int, w: Int, h: Int, colour: Int) { fun plotRect(x: Int, y: Int, w: Int, h: Int, colour: Int) = plotRect(x, y, w, h, colour, 0)
/**
* @param eff plot effect. 0 — solid, 1 — 50% checkerboard, 2 — 25% checkerboard
*/
fun plotRect(x: Int, y: Int, w: Int, h: Int, colour: Int, eff: Int) {
val xs = min(x, x+w).toLong() val xs = min(x, x+w).toLong()
val xe = max(x, x+w).toLong() val xe = max(x, x+w).toLong()
val ys = min(y, y+h).toLong() val ys = min(y, y+h).toLong()
val ye = max(y, y+h).toLong() val ye = max(y, y+h).toLong()
getFirstGPU()?.let { getFirstGPU()?.let {
for (py in ys until ye) { val forYcond = if (eff == 2) (ys until ye step 2) else (ys until ye)
for (px in xs until xe) {
for (py in forYcond) {
when (eff) {
0 -> for (px in xs until xe) {
if (px in 0 until it.config.width && py in 0 until it.config.height) { if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(py * it.config.width + px, colour.toByte()) it.poke(py * it.config.width + px, colour.toByte())
} }
} }
1 -> {
val parity = py % 2
val forXcond = if (parity == 0L) (xs until xe step 2) else ((xs+1) until xe step 2)
for (px in forXcond) {
if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(py * it.config.width + px, colour.toByte())
}
}
}
2 -> for (px in xs until xe step 2) {
if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(py * it.config.width + px, colour.toByte())
}
}
}
} }
it.applyDelay() it.applyDelay()
} }
} }
fun plotRect2(x: Int, y: Int, w: Int, h: Int, colour: Int) { fun plotRect2(x: Int, y: Int, w: Int, h: Int, colour: Int) = plotRect2(x, y, w, h, colour, 0)
/**
* @param eff plot effect. 0 — solid, 1 — 50% checkerboard, 2 — 25% checkerboard
*/
fun plotRect2(x: Int, y: Int, w: Int, h: Int, colour: Int, eff: Int) {
val xs = min(x, x+w).toLong() val xs = min(x, x+w).toLong()
val xe = max(x, x+w).toLong() val xe = max(x, x+w).toLong()
val ys = min(y, y+h).toLong() val ys = min(y, y+h).toLong()
val ye = max(y, y+h).toLong() val ye = max(y, y+h).toLong()
getFirstGPU()?.let { getFirstGPU()?.let {
for (py in ys until ye) { val forYcond = if (eff == 2) (ys until ye step 2) else (ys until ye)
for (px in xs until xe) {
for (py in forYcond) {
when (eff) {
0 -> for (px in xs until xe) {
if (px in 0 until it.config.width && py in 0 until it.config.height) { if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(262144 + py * it.config.width + px, colour.toByte()) it.poke(262144 + py * it.config.width + px, colour.toByte())
} }
} }
1 -> {
val parity = py % 2
val forXcond = if (parity == 0L) (xs until xe step 2) else ((xs+1) until xe step 2)
for (px in forXcond) {
if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(py * it.config.width + px, colour.toByte())
}
}
}
2 -> for (px in xs until xe step 2) {
if (px in 0 until it.config.width && py in 0 until it.config.height) {
it.poke(py * it.config.width + px, colour.toByte())
}
}
}
} }
it.applyDelay() it.applyDelay()
} }
@@ -195,7 +243,12 @@ class GraphicsJSR223Delegate(private val vm: VM) {
} }
} }
fun plotRectMode1(x: Int, y: Int, w: Int, h: Int, colour: Int, plane: Int) { fun plotRectMode1(x: Int, y: Int, w: Int, h: Int, colour: Int, plane: Int) = plotRectMode1(x, y, w, h, colour, plane, 0)
/**
* @param eff plot effect. 0 — solid, 1 — 50% checkerboard, 2 — 25% checkerboard
*/
fun plotRectMode1(x: Int, y: Int, w: Int, h: Int, colour: Int, plane: Int, eff: Int) {
val xs = min(x, x+w).toLong() val xs = min(x, x+w).toLong()
val xe = max(x, x+w).toLong() val xe = max(x, x+w).toLong()
val ys = min(y, y+h).toLong() val ys = min(y, y+h).toLong()
@@ -205,12 +258,31 @@ class GraphicsJSR223Delegate(private val vm: VM) {
val halfW = it.config.width / 2 val halfW = it.config.width / 2
val halfH = it.config.height / 2 val halfH = it.config.height / 2
val planesize = it.config.width * it.config.height / 4 val planesize = it.config.width * it.config.height / 4
for (py in ys until ye) { val forYcond = if (eff == 2) (ys until ye step 2) else (ys until ye)
for (px in xs until xe) {
for (py in forYcond) {
when (eff) {
0 -> for (px in xs until xe) {
if (px in 0 until halfW && py in 0 until halfH) { if (px in 0 until halfW && py in 0 until halfH) {
it.poke(py * halfW + px + planesize * plane, colour.toByte()) it.poke(py * halfW + px + planesize * plane, colour.toByte())
} }
} }
1 -> {
val parity = py % 2
val forXcond = if (parity == 0L) (xs until xe step 2) else ((xs+1) until xe step 2)
for (px in forXcond) {
if (px in 0 until halfW && py in 0 until halfH) {
it.poke(py * halfW + px + planesize * plane, colour.toByte())
}
}
}
2 -> for (px in xs until xe step 2) {
if (px in 0 until halfW && py in 0 until halfH) {
it.poke(py * halfW + px + planesize * plane, colour.toByte())
}
}
}
} }
it.applyDelay() it.applyDelay()
} }