diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs index c5c9f9f12..d353860ba 100644 --- a/packages/codemirror/codemirror.mjs +++ b/packages/codemirror/codemirror.mjs @@ -5,7 +5,7 @@ import { javascript } from '@codemirror/lang-javascript'; import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'; import { Compartment, EditorState } from '@codemirror/state'; import { EditorView, highlightActiveLineGutter, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view'; -import { Drawer, repl, cleanupDraw } from '@strudel.cycles/core'; +import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core'; import { isAutoCompletionEnabled } from './Autocomplete'; import { flash, isFlashEnabled } from './flash.mjs'; import { highlightMiniLocations, isPatternHighlightingEnabled, updateMiniLocations } from './highlight.mjs'; @@ -88,13 +88,20 @@ export class StrudelMirror { this.code = initialCode; this.root = root; this.miniLocations = []; + this.painters = []; + const self = this; this.drawer = new Drawer((haps, time) => { const currentFrame = haps.filter((hap) => time >= hap.whole.begin && time <= hap.endClipped); this.highlight(currentFrame, time); - onDraw?.(haps, time, currentFrame); + onDraw?.(haps, time, currentFrame, this.painters); }, drawTime); + Pattern.prototype.onPaint = function (onPaint) { + self.painters.push(onPaint); + return this; + }; + const prebaked = prebake(); prebaked.then(async () => { if (!onDraw) { @@ -116,11 +123,13 @@ export class StrudelMirror { this.drawer.start(this.repl.scheduler); } else { this.drawer.stop(); + updateMiniLocations(this.editor, []); cleanupDraw(false); } }, beforeEval: async () => { cleanupDraw(); + this.painters = []; await prebaked; await replOptions?.beforeEval?.(); }, diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index f3d2c38a2..96126b175 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -86,6 +86,7 @@ export function pianoroll({ hideInactive = 0, colorizeInactive = 1, fontFamily, + clear = true, ctx, } = {}) { const w = ctx.canvas.width; @@ -131,7 +132,7 @@ export function pianoroll({ barThickness = fold ? valueAxis / foldValues.length : valueAxis / valueExtent; ctx.fillStyle = background; ctx.globalAlpha = 1; // reset! - if (!smear) { + if (clear && !smear) { ctx.clearRect(0, 0, w, h); ctx.fillRect(0, 0, w, h); } diff --git a/packages/core/spiral.mjs b/packages/core/spiral.mjs index e0d5cd877..3c585254a 100644 --- a/packages/core/spiral.mjs +++ b/packages/core/spiral.mjs @@ -67,9 +67,9 @@ Pattern.prototype.spiral = function (options = {}) { // logSpiral = true, } = options; - function spiral({ ctx, time, haps, drawTime }) { + function spiral({ ctx, time, haps, drawTime, clear }) { const [w, h] = [ctx.canvas.width, ctx.canvas.height]; - ctx.clearRect(0, 0, w * 2, h * 2); + clear && ctx.clearRect(0, 0, w * 2, h * 2); const [cx, cy] = [w / 2, h / 2]; const settings = { margin: size / stretch, @@ -114,5 +114,5 @@ Pattern.prototype.spiral = function (options = {}) { }); } - return this.onPaint((ctx, time, haps, drawTime) => spiral({ ctx, time, haps, drawTime })); + return this.onPaint((ctx, time, haps, drawTime, options) => spiral({ ctx, time, haps, drawTime, ...options })); }; diff --git a/website/src/repl/vanillarepl.mjs b/website/src/repl/vanillarepl.mjs index 780673045..83149da16 100644 --- a/website/src/repl/vanillarepl.mjs +++ b/website/src/repl/vanillarepl.mjs @@ -1,4 +1,4 @@ -import { logger, cleanupDraw } from '@strudel.cycles/core'; +import { logger, getDrawContext } from '@strudel.cycles/core'; import { StrudelMirror } from '@strudel/codemirror'; import { getAudioContext, webaudioOutput } from '@strudel.cycles/webaudio'; import { transpiler } from '@strudel.cycles/transpiler'; @@ -56,8 +56,8 @@ async function run() { const settings = settingsMap.get(); - /* const drawContext = getDrawContext() -const drawTime = [-2, 2]; */ + const drawContext = getDrawContext(); + const drawTime = [-2, 2]; const editor = new StrudelMirror({ defaultOutput: webaudioOutput, getTime: () => getAudioContext().currentTime, @@ -65,9 +65,14 @@ const drawTime = [-2, 2]; */ root: container, initialCode: '// LOADING', settings, - /* drawTime, - onDraw: (haps, time) => - drawPianoroll({ haps, time, ctx: drawContext, drawTime, fold: 1 }), */ + drawTime, + onDraw: (haps, time, frame, painters) => { + drawContext.clearRect(0, 0, drawContext.canvas.width * 2, drawContext.canvas.height * 2); + painters?.forEach((painter) => { + // ctx time haps drawTime paintOptions + painter(drawContext, time, haps, drawTime, { clear: false }); + }); + }, prebake: () => prebake(), afterEval: ({ code }) => { setLatestCode(code);