do less work when not drawing

This commit is contained in:
Felix Roos 2023-01-15 23:11:49 +01:00
parent 800989419b
commit 5aa983b45b
5 changed files with 283 additions and 282 deletions

View File

@ -46,7 +46,7 @@ const _bjork = function (n, x) {
return Math.min(ons, offs) <= 1 ? [n, x] : _bjork(...(ons > offs ? left(n, x) : right(n, x))); return Math.min(ons, offs) <= 1 ? [n, x] : _bjork(...(ons > offs ? left(n, x) : right(n, x)));
}; };
const bjork = function (ons, steps) { export const bjork = function (ons, steps) {
const offs = steps - ons; const offs = steps - ons;
const x = Array(ons).fill([1]); const x = Array(ons).fill([1]);
const y = Array(offs).fill([0]); const y = Array(offs).fill([0]);

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,15 @@
import l, { useCallback as y, useRef as N, useEffect as k, useMemo as J, useState as M, useLayoutEffect as te } from "react"; import d, { useCallback as E, useRef as A, useEffect as k, useMemo as Q, useState as _, useLayoutEffect as te } from "react";
import le from "@uiw/react-codemirror"; import ue from "@uiw/react-codemirror";
import { Decoration as A, EditorView as re } from "@codemirror/view"; import { Decoration as M, EditorView as re } from "@codemirror/view";
import { StateEffect as ne, StateField as oe } from "@codemirror/state"; import { StateEffect as ne, StateField as oe } from "@codemirror/state";
import { javascript as ue } from "@codemirror/lang-javascript"; import { javascript as de } from "@codemirror/lang-javascript";
import { tags as i } from "@lezer/highlight"; import { tags as u } from "@lezer/highlight";
import { createTheme as de } from "@uiw/codemirror-themes"; import { createTheme as fe } from "@uiw/codemirror-themes";
import { webaudioOutput as fe, getAudioContext as me } from "@strudel.cycles/webaudio"; import { webaudioOutput as me, getAudioContext as he } from "@strudel.cycles/webaudio";
import { useInView as he } from "react-hook-inview"; import { useInView as ge } from "react-hook-inview";
import { repl as ge, logger as pe } from "@strudel.cycles/core"; import { repl as pe, logger as ve } from "@strudel.cycles/core";
import { transpiler as ve } from "@strudel.cycles/transpiler"; import { transpiler as be } from "@strudel.cycles/transpiler";
const be = de({ const Ee = fe({
theme: "dark", theme: "dark",
settings: { settings: {
background: "#222", background: "#222",
@ -22,421 +22,421 @@ const be = de({
gutterForeground: "#8a919966" gutterForeground: "#8a919966"
}, },
styles: [ styles: [
{ tag: i.keyword, color: "#c792ea" }, { tag: u.keyword, color: "#c792ea" },
{ tag: i.operator, color: "#89ddff" }, { tag: u.operator, color: "#89ddff" },
{ tag: i.special(i.variableName), color: "#eeffff" }, { tag: u.special(u.variableName), color: "#eeffff" },
{ tag: i.typeName, color: "#c3e88d" }, { tag: u.typeName, color: "#c3e88d" },
{ tag: i.atom, color: "#f78c6c" }, { tag: u.atom, color: "#f78c6c" },
{ tag: i.number, color: "#c3e88d" }, { tag: u.number, color: "#c3e88d" },
{ tag: i.definition(i.variableName), color: "#82aaff" }, { tag: u.definition(u.variableName), color: "#82aaff" },
{ tag: i.string, color: "#c3e88d" }, { tag: u.string, color: "#c3e88d" },
{ tag: i.special(i.string), color: "#c3e88d" }, { tag: u.special(u.string), color: "#c3e88d" },
{ tag: i.comment, color: "#7d8799" }, { tag: u.comment, color: "#7d8799" },
{ tag: i.variableName, color: "#c792ea" }, { tag: u.variableName, color: "#c792ea" },
{ tag: i.tagName, color: "#c3e88d" }, { tag: u.tagName, color: "#c3e88d" },
{ tag: i.bracket, color: "#525154" }, { tag: u.bracket, color: "#525154" },
{ tag: i.meta, color: "#ffcb6b" }, { tag: u.meta, color: "#ffcb6b" },
{ tag: i.attributeName, color: "#c792ea" }, { tag: u.attributeName, color: "#c792ea" },
{ tag: i.propertyName, color: "#c792ea" }, { tag: u.propertyName, color: "#c792ea" },
{ tag: i.className, color: "#decb6b" }, { tag: u.className, color: "#decb6b" },
{ tag: i.invalid, color: "#ffffff" } { tag: u.invalid, color: "#ffffff" }
] ]
}); });
const Q = ne.define(), Ee = oe.define({ const X = ne.define(), ye = oe.define({
create() { create() {
return A.none; return M.none;
}, },
update(e, r) { update(e, t) {
try { try {
for (let t of r.effects) for (let r of t.effects)
if (t.is(Q)) if (r.is(X))
if (t.value) { if (r.value) {
const n = A.mark({ attributes: { style: "background-color: #FFCA2880" } }); const n = M.mark({ attributes: { style: "background-color: #FFCA2880" } });
e = A.set([n.range(0, r.newDoc.length)]); e = M.set([n.range(0, t.newDoc.length)]);
} else } else
e = A.set([]); e = M.set([]);
return e; return e;
} catch (t) { } catch (r) {
return console.warn("flash error", t), e; return console.warn("flash error", r), e;
} }
}, },
provide: (e) => re.decorations.from(e) provide: (e) => re.decorations.from(e)
}), ye = (e) => { }), we = (e) => {
e.dispatch({ effects: Q.of(!0) }), setTimeout(() => { e.dispatch({ effects: X.of(!0) }), setTimeout(() => {
e.dispatch({ effects: Q.of(!1) }); e.dispatch({ effects: X.of(!1) });
}, 200); }, 200);
}, I = ne.define(), we = oe.define({ }, B = ne.define(), ke = oe.define({
create() { create() {
return A.none; return M.none;
}, },
update(e, r) { update(e, t) {
try { try {
for (let t of r.effects) for (let r of t.effects)
if (t.is(I)) { if (r.is(B)) {
const n = t.value.map( const n = r.value.map(
(s) => (s.context.locations || []).map(({ start: m, end: u }) => { (l) => (l.context.locations || []).map(({ start: m, end: f }) => {
const o = s.context.color || "#FFCA28"; const c = l.context.color || "#FFCA28";
let c = r.newDoc.line(m.line).from + m.column, g = r.newDoc.line(u.line).from + u.column; let s = t.newDoc.line(m.line).from + m.column, g = t.newDoc.line(f.line).from + f.column;
const b = r.newDoc.length; const b = t.newDoc.length;
return c > b || g > b ? void 0 : A.mark({ attributes: { style: `outline: 1.5px solid ${o};` } }).range(c, g); return s > b || g > b ? void 0 : M.mark({ attributes: { style: `outline: 1.5px solid ${c};` } }).range(s, g);
}) })
).flat().filter(Boolean) || []; ).flat().filter(Boolean) || [];
e = A.set(n, !0); e = M.set(n, !0);
} }
return e; return e;
} catch { } catch {
return A.set([]); return M.set([]);
} }
}, },
provide: (e) => re.decorations.from(e) provide: (e) => re.decorations.from(e)
}), ke = [ue(), be, we, Ee]; }), Fe = [de(), Ee, ke, ye];
function Fe({ value: e, onChange: r, onViewChanged: t, onSelectionChange: n, options: s, editorDidMount: m }) { function _e({ value: e, onChange: t, onViewChanged: r, onSelectionChange: n, options: l, editorDidMount: m }) {
const u = y( const f = E(
(g) => {
r?.(g);
},
[r]
), o = y(
(g) => { (g) => {
t?.(g); t?.(g);
}, },
[t] [t]
), c = y( ), c = E(
(g) => {
r?.(g);
},
[r]
), s = E(
(g) => { (g) => {
g.selectionSet && n && n?.(g.state.selection); g.selectionSet && n && n?.(g.state.selection);
}, },
[n] [n]
); );
return /* @__PURE__ */ l.createElement(l.Fragment, null, /* @__PURE__ */ l.createElement(le, { return /* @__PURE__ */ d.createElement(d.Fragment, null, /* @__PURE__ */ d.createElement(ue, {
value: e, value: e,
onChange: u, onChange: f,
onCreateEditor: o, onCreateEditor: c,
onUpdate: c, onUpdate: s,
extensions: ke extensions: Fe
})); }));
} }
function T(...e) { function T(...e) {
return e.filter(Boolean).join(" "); return e.filter(Boolean).join(" ");
} }
function _e({ view: e, pattern: r, active: t, getTime: n }) { function Me({ view: e, pattern: t, active: r, getTime: n }) {
const s = N([]), m = N(0); const l = A([]), m = A(0);
k(() => { k(() => {
if (e) if (e)
if (r && t) { if (t && r) {
m.current = 0; m.current = 0;
let u = requestAnimationFrame(function o() { let f = requestAnimationFrame(function c() {
try { try {
const c = n(), b = [Math.max(m.current ?? c, c - 1 / 10, -0.01), c + 1 / 60]; const s = n(), b = [Math.max(m.current ?? s, s - 1 / 10, -0.01), s + 1 / 60];
m.current = b[1], s.current = s.current.filter((h) => h.whole.end > c); m.current = b[1], l.current = l.current.filter((h) => h.whole.end > s);
const a = r.queryArc(...b).filter((h) => h.hasOnset()); const i = t.queryArc(...b).filter((h) => h.hasOnset());
s.current = s.current.concat(a), e.dispatch({ effects: I.of(s.current) }); l.current = l.current.concat(i), e.dispatch({ effects: B.of(l.current) });
} catch { } catch {
e.dispatch({ effects: I.of([]) }); e.dispatch({ effects: B.of([]) });
} }
u = requestAnimationFrame(o); f = requestAnimationFrame(c);
}); });
return () => { return () => {
cancelAnimationFrame(u); cancelAnimationFrame(f);
}; };
} else } else
s.current = [], e.dispatch({ effects: I.of([]) }); l.current = [], e.dispatch({ effects: B.of([]) });
}, [r, t, e]); }, [t, r, e]);
} }
function Me(e, r = !1) { function Ae(e, t = !1) {
const t = N(), n = N(), s = (o) => { const r = A(), n = A(), l = (c) => {
if (n.current !== void 0) { if (n.current !== void 0) {
const c = o - n.current; const s = c - n.current;
e(o, c); e(c, s);
} }
n.current = o, t.current = requestAnimationFrame(s); n.current = c, r.current = requestAnimationFrame(l);
}, m = () => { }, m = () => {
t.current = requestAnimationFrame(s); r.current = requestAnimationFrame(l);
}, u = () => { }, f = () => {
t.current && cancelAnimationFrame(t.current), delete t.current; r.current && cancelAnimationFrame(r.current), delete r.current;
}; };
return k(() => { return k(() => {
t.current && (u(), m()); r.current && (f(), m());
}, [e]), k(() => (r && m(), u), []), { }, [e]), k(() => (t && m(), f), []), {
start: m, start: m,
stop: u stop: f
}; };
} }
function Ae({ pattern: e, started: r, getTime: t, onDraw: n, drawTime: s = [-2, 2] }) { function Ne({ pattern: e, started: t, getTime: r, onDraw: n, drawTime: l = [-2, 2] }) {
let [m, u] = s; let [m, f] = l;
m = Math.abs(m); m = Math.abs(m);
let o = N([]), c = N(null); let c = A([]), s = A(null);
k(() => { k(() => {
if (e) { if (e && t) {
const a = t(), h = e.queryArc(Math.max(a, 0), a + u + 0.1); const i = r(), h = e.queryArc(Math.max(i, 0), i + f + 0.1);
o.current = o.current.filter((v) => v.whole.begin < a), o.current = o.current.concat(h); c.current = c.current.filter((p) => p.whole.begin < i), c.current = c.current.concat(h);
} }
}, [e]); }, [e, t]);
const { start: g, stop: b } = Me( const { start: g, stop: b } = Ae(
y(() => { E(() => {
const a = t() + u; const i = r() + f;
if (c.current === null) { if (s.current === null) {
c.current = a; s.current = i;
return; return;
} }
const h = e.queryArc(Math.max(c.current, a - 1 / 10), a); const h = e.queryArc(Math.max(s.current, i - 1 / 10), i);
c.current = a, o.current = (o.current || []).filter((v) => v.whole.end >= a - m - u).concat(h.filter((v) => v.hasOnset())), n(e, a - u, o.current, s); s.current = i, c.current = (c.current || []).filter((p) => p.whole.end >= i - m - f).concat(h.filter((p) => p.hasOnset())), n(e, i - f, c.current, l);
}, [e]) }, [e])
); );
return k(() => { return k(() => {
r ? g() : (o.current = [], b()); t ? g() : (c.current = [], b());
}, [r]), { }, [t]), {
clear: () => { clear: () => {
o.current = []; c.current = [];
} }
}; };
} }
function Ne(e) { function Ce(e) {
return k(() => (window.addEventListener("message", e), () => window.removeEventListener("message", e)), [e]), y((r) => window.postMessage(r, "*"), []); return k(() => (window.addEventListener("message", e), () => window.removeEventListener("message", e)), [e]), E((t) => window.postMessage(t, "*"), []);
} }
function De({ function De({
defaultOutput: e, defaultOutput: e,
interval: r, interval: t,
getTime: t, getTime: r,
evalOnMount: n = !1, evalOnMount: n = !1,
initialCode: s = "", initialCode: l = "",
autolink: m = !1, autolink: m = !1,
beforeEval: u, beforeEval: f,
afterEval: o, afterEval: c,
editPattern: c, editPattern: s,
onEvalError: g, onEvalError: g,
onToggle: b, onToggle: b,
canvasId: a, canvasId: i,
drawContext: h, drawContext: h,
drawTime: v = [-2, 2] drawTime: p = [-2, 2]
}) { }) {
const R = J(() => Ce(), []); const D = Q(() => Re(), []);
a = a || `canvas-${R}`; i = i || `canvas-${D}`;
const [L, x] = M(), [H, P] = M(), [E, S] = M(s), [V, q] = M(), [z, K] = M(), [D, O] = M(!1), j = E !== V, { scheduler: F, evaluate: C, start: d, stop: p, pause: X } = J( const [P, R] = _(), [z, H] = _(), [y, S] = _(l), [V, q] = _(), [x, I] = _(), [N, O] = _(!1), K = y !== V, L = E((a) => !!(a?.context?.onPaint && h), [h]), { scheduler: C, evaluate: o, start: v, stop: j, pause: U } = Q(
() => ge({ () => pe({
interval: r, interval: t,
defaultOutput: e, defaultOutput: e,
onSchedulerError: x, onSchedulerError: R,
onEvalError: (f) => { onEvalError: (a) => {
P(f), g?.(f); H(a), g?.(a);
}, },
getTime: t, getTime: r,
drawContext: h, drawContext: h,
transpiler: ve, transpiler: be,
editPattern: c, editPattern: s,
beforeEval: ({ code: f }) => { beforeEval: ({ code: a }) => {
S(f), u?.(); S(a), f?.();
}, },
afterEval: ({ pattern: f, code: w }) => { afterEval: ({ pattern: a, code: w }) => {
q(w), K(f), P(), x(), m && (window.location.hash = "#" + encodeURIComponent(btoa(w))), o?.(); q(w), I(a), H(), R(), m && (window.location.hash = "#" + encodeURIComponent(btoa(w))), c?.();
}, },
onToggle: (f) => { onToggle: (a) => {
O(f), b?.(f); O(a), b?.(a);
} }
}), }),
[e, r, t] [e, t, r]
), U = Ne(({ data: { from: f, type: w } }) => { ), ce = Ce(({ data: { from: a, type: w } }) => {
w === "start" && f !== R && p(); w === "start" && a !== D && j();
}), Y = y( }), Y = E(
async (f = !0) => { async (a = !0) => {
const w = await C(E, f); const w = await o(y, a);
return U({ type: "start", from: R }), w; return ce({ type: "start", from: D }), w;
}, },
[C, E] [o, y]
), B = y( ), W = E(
(f, w, $, G) => { (a, w, G, J) => {
const { onPaint: se } = f.context || {}, ie = typeof h == "function" ? h(a) : h; const { onPaint: ie } = a.context || {}, le = typeof h == "function" ? h(i) : h;
se?.(ie, w, $, G); ie?.(le, w, G, J);
}, },
[h, a] [h, i]
), W = y( ), $ = E(
(f) => { (a) => {
if (h && B) { if (L(a)) {
const [w, $] = v, G = f.queryArc(0, $); const [w, G] = p, J = a.queryArc(0, G);
B(f, -1e-3, G, v); W(a, -1e-3, J, p);
} }
}, },
[h, v, B] [p, W, L]
), Z = N(); ), Z = A();
k(() => { k(() => {
!Z.current && n && E && (Z.current = !0, C(E, !1).then((f) => W(f))); !Z.current && n && y && (Z.current = !0, o(y, !1).then((a) => $(a)));
}, [n, E, C, W]), k(() => () => { }, [n, y, o, $]), k(() => () => {
F.stop(); C.stop();
}, [F]); }, [C]);
const ce = async () => { const ae = async () => {
D ? (F.stop(), W(z)) : await Y(); N ? (C.stop(), $(x)) : await Y();
}, ae = L || H; }, se = P || z;
return Ae({ return Ne({
pattern: z, pattern: x,
started: h && D, started: L(x) && N,
getTime: () => F.now(), getTime: () => C.now(),
drawTime: v, drawTime: p,
onDraw: B onDraw: W
}), { }), {
id: R, id: D,
canvasId: a, canvasId: i,
code: E, code: y,
setCode: S, setCode: S,
error: ae, error: se,
schedulerError: L, schedulerError: P,
scheduler: F, scheduler: C,
evalError: H, evalError: z,
evaluate: C, evaluate: o,
activateCode: Y, activateCode: Y,
activeCode: V, activeCode: V,
isDirty: j, isDirty: K,
pattern: z, pattern: x,
started: D, started: N,
start: d, start: v,
stop: p, stop: j,
pause: X, pause: U,
togglePlay: ce togglePlay: ae
}; };
} }
function Ce() { function Re() {
return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1); return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
} }
function ee({ type: e }) { function ee({ type: e }) {
return /* @__PURE__ */ l.createElement("svg", { return /* @__PURE__ */ d.createElement("svg", {
xmlns: "http://www.w3.org/2000/svg", xmlns: "http://www.w3.org/2000/svg",
className: "sc-h-5 sc-w-5", className: "sc-h-5 sc-w-5",
viewBox: "0 0 20 20", viewBox: "0 0 20 20",
fill: "currentColor" fill: "currentColor"
}, { }, {
refresh: /* @__PURE__ */ l.createElement("path", { refresh: /* @__PURE__ */ d.createElement("path", {
fillRule: "evenodd", fillRule: "evenodd",
d: "M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z", d: "M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",
clipRule: "evenodd" clipRule: "evenodd"
}), }),
play: /* @__PURE__ */ l.createElement("path", { play: /* @__PURE__ */ d.createElement("path", {
fillRule: "evenodd", fillRule: "evenodd",
d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",
clipRule: "evenodd" clipRule: "evenodd"
}), }),
pause: /* @__PURE__ */ l.createElement("path", { pause: /* @__PURE__ */ d.createElement("path", {
fillRule: "evenodd", fillRule: "evenodd",
d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",
clipRule: "evenodd" clipRule: "evenodd"
}), }),
stop: /* @__PURE__ */ l.createElement("path", { stop: /* @__PURE__ */ d.createElement("path", {
fillRule: "evenodd", fillRule: "evenodd",
d: "M2 10a8 8 0 1116 0 8 8 0 01-16 0zm5-2.25A.75.75 0 017.75 7h4.5a.75.75 0 01.75.75v4.5a.75.75 0 01-.75.75h-4.5a.75.75 0 01-.75-.75v-4.5z", d: "M2 10a8 8 0 1116 0 8 8 0 01-16 0zm5-2.25A.75.75 0 017.75 7h4.5a.75.75 0 01.75.75v4.5a.75.75 0 01-.75.75h-4.5a.75.75 0 01-.75-.75v-4.5z",
clipRule: "evenodd" clipRule: "evenodd"
}) })
}[e]); }[e]);
} }
const Re = "_container_3i85k_1", xe = "_header_3i85k_5", Le = "_buttons_3i85k_9", qe = "_button_3i85k_9", ze = "_buttonDisabled_3i85k_17", He = "_error_3i85k_21", Pe = "_body_3i85k_25", _ = { const xe = "_container_3i85k_1", Le = "_header_3i85k_5", Pe = "_buttons_3i85k_9", qe = "_button_3i85k_9", ze = "_buttonDisabled_3i85k_17", He = "_error_3i85k_21", Se = "_body_3i85k_25", F = {
container: Re, container: xe,
header: xe, header: Le,
buttons: Le, buttons: Pe,
button: qe, button: qe,
buttonDisabled: ze, buttonDisabled: ze,
error: He, error: He,
body: Pe body: Se
}, Se = () => me().currentTime; }, Ve = () => he().currentTime;
function Ye({ tune: e, hideOutsideView: r = !1, enableKeyboard: t, drawTime: n, punchcard: s, canvasHeight: m = 200 }) { function Ze({ tune: e, hideOutsideView: t = !1, enableKeyboard: r, drawTime: n, punchcard: l, canvasHeight: m = 200 }) {
n = n || (s ? [0, 4] : void 0); n = n || (l ? [0, 4] : void 0);
const u = !!n, o = y( const f = !!n, c = E(
n ? (d) => document.querySelector("#" + d)?.getContext("2d") : null, n ? (o) => document.querySelector("#" + o)?.getContext("2d") : null,
[n] [n]
), { ), {
code: c, code: s,
setCode: g, setCode: g,
evaluate: b, evaluate: b,
activateCode: a, activateCode: i,
error: h, error: h,
isDirty: v, isDirty: p,
activeCode: R, activeCode: D,
pattern: L, pattern: P,
started: x, started: R,
scheduler: H, scheduler: z,
togglePlay: P, togglePlay: H,
stop: E, stop: y,
canvasId: S, canvasId: S,
id: V id: V
} = De({ } = De({
initialCode: e, initialCode: e,
defaultOutput: fe, defaultOutput: me,
editPattern: (d) => s ? d.punchcard() : d, editPattern: (o) => l ? o.punchcard() : o,
getTime: Se, getTime: Ve,
evalOnMount: u, evalOnMount: f,
drawContext: o, drawContext: c,
drawTime: n drawTime: n
}), [q, z] = M(), [K, D] = he({ }), [q, x] = _(), [I, N] = ge({
threshold: 0.01 threshold: 0.01
}), O = N(), j = J(() => ((D || !r) && (O.current = !0), D || O.current), [D, r]); }), O = A(), K = Q(() => ((N || !t) && (O.current = !0), N || O.current), [N, t]);
_e({ Me({
view: q, view: q,
pattern: L, pattern: P,
active: x && !R?.includes("strudel disable-highlighting"), active: R && !D?.includes("strudel disable-highlighting"),
getTime: () => H.now() getTime: () => z.now()
}), te(() => { }), te(() => {
if (t) { if (r) {
const d = async (p) => { const o = async (v) => {
(p.ctrlKey || p.altKey) && (p.code === "Enter" ? (p.preventDefault(), ye(q), await a()) : p.code === "Period" && (E(), p.preventDefault())); (v.ctrlKey || v.altKey) && (v.code === "Enter" ? (v.preventDefault(), we(q), await i()) : v.code === "Period" && (y(), v.preventDefault()));
}; };
return window.addEventListener("keydown", d, !0), () => window.removeEventListener("keydown", d, !0); return window.addEventListener("keydown", o, !0), () => window.removeEventListener("keydown", o, !0);
} }
}, [t, L, c, b, E, q]); }, [r, P, s, b, y, q]);
const [F, C] = M([]); const [L, C] = _([]);
return Ve( return Oe(
y((d) => { E((o) => {
const { data: p } = d.detail; const { data: v } = o.detail;
p?.hap?.context?.id === V && C((U) => U.concat([d.detail]).slice(-10)); v?.hap?.context?.id === V && C((U) => U.concat([o.detail]).slice(-10));
}, []) }, [])
), /* @__PURE__ */ l.createElement("div", { ), /* @__PURE__ */ d.createElement("div", {
className: _.container, className: F.container,
ref: K ref: I
}, /* @__PURE__ */ l.createElement("div", { }, /* @__PURE__ */ d.createElement("div", {
className: _.header className: F.header
}, /* @__PURE__ */ l.createElement("div", { }, /* @__PURE__ */ d.createElement("div", {
className: _.buttons className: F.buttons
}, /* @__PURE__ */ l.createElement("button", { }, /* @__PURE__ */ d.createElement("button", {
className: T(_.button, x ? "sc-animate-pulse" : ""), className: T(F.button, R ? "sc-animate-pulse" : ""),
onClick: () => P() onClick: () => H()
}, /* @__PURE__ */ l.createElement(ee, { }, /* @__PURE__ */ d.createElement(ee, {
type: x ? "stop" : "play" type: R ? "stop" : "play"
})), /* @__PURE__ */ l.createElement("button", { })), /* @__PURE__ */ d.createElement("button", {
className: T(v ? _.button : _.buttonDisabled), className: T(p ? F.button : F.buttonDisabled),
onClick: () => a() onClick: () => i()
}, /* @__PURE__ */ l.createElement(ee, { }, /* @__PURE__ */ d.createElement(ee, {
type: "refresh" type: "refresh"
}))), h && /* @__PURE__ */ l.createElement("div", { }))), h && /* @__PURE__ */ d.createElement("div", {
className: _.error className: F.error
}, h.message)), /* @__PURE__ */ l.createElement("div", { }, h.message)), /* @__PURE__ */ d.createElement("div", {
className: _.body className: F.body
}, j && /* @__PURE__ */ l.createElement(Fe, { }, K && /* @__PURE__ */ d.createElement(_e, {
value: c, value: s,
onChange: g, onChange: g,
onViewChanged: z onViewChanged: x
})), n && /* @__PURE__ */ l.createElement("canvas", { })), n && /* @__PURE__ */ d.createElement("canvas", {
id: S, id: S,
className: "w-full pointer-events-none", className: "w-full pointer-events-none",
height: m, height: m,
ref: (d) => { ref: (o) => {
d && d.width !== d.clientWidth && (d.width = d.clientWidth); o && o.width !== o.clientWidth && (o.width = o.clientWidth);
} }
}), !!F.length && /* @__PURE__ */ l.createElement("div", { }), !!L.length && /* @__PURE__ */ d.createElement("div", {
className: "sc-bg-gray-800 sc-rounded-md sc-p-2" className: "sc-bg-gray-800 sc-rounded-md sc-p-2"
}, F.map(({ message: d }, p) => /* @__PURE__ */ l.createElement("div", { }, L.map(({ message: o }, v) => /* @__PURE__ */ d.createElement("div", {
key: p key: v
}, d)))); }, o))));
} }
function Ve(e) { function Oe(e) {
Oe(pe.key, e); Be(ve.key, e);
} }
function Oe(e, r, t = !1) { function Be(e, t, r = !1) {
k(() => (document.addEventListener(e, r, t), () => { k(() => (document.addEventListener(e, t, r), () => {
document.removeEventListener(e, r, t); document.removeEventListener(e, t, r);
}), [r]); }), [t]);
} }
const Ze = (e) => te(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]); const Te = (e) => te(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]);
export { export {
Fe as CodeMirror, _e as CodeMirror,
Ye as MiniRepl, Ze as MiniRepl,
T as cx, T as cx,
ye as flash, we as flash,
_e as useHighlighting, Me as useHighlighting,
Ze as useKeydown, Te as useKeydown,
Ne as usePostMessage, Ce as usePostMessage,
De as useStrudel De as useStrudel
}; };

View File

@ -8,13 +8,13 @@ function usePatternFrame({ pattern, started, getTime, onDraw, drawTime = [-2, 2]
let visibleHaps = useRef([]); let visibleHaps = useRef([]);
let lastFrame = useRef(null); let lastFrame = useRef(null);
useEffect(() => { useEffect(() => {
if (pattern) { if (pattern && started) {
const t = getTime(); const t = getTime();
const futureHaps = pattern.queryArc(Math.max(t, 0), t + lookahead + 0.1); // +0.1 = workaround for weird holes in query.. const futureHaps = pattern.queryArc(Math.max(t, 0), t + lookahead + 0.1); // +0.1 = workaround for weird holes in query..
visibleHaps.current = visibleHaps.current.filter((h) => h.whole.begin < t); visibleHaps.current = visibleHaps.current.filter((h) => h.whole.begin < t);
visibleHaps.current = visibleHaps.current.concat(futureHaps); visibleHaps.current = visibleHaps.current.concat(futureHaps);
} }
}, [pattern]); }, [pattern, started]);
const { start: startFrame, stop: stopFrame } = useFrame( const { start: startFrame, stop: stopFrame } = useFrame(
useCallback(() => { useCallback(() => {
const phase = getTime() + lookahead; const phase = getTime() + lookahead;

View File

@ -30,6 +30,7 @@ function useStrudel({
const [pattern, setPattern] = useState(); const [pattern, setPattern] = useState();
const [started, setStarted] = useState(false); const [started, setStarted] = useState(false);
const isDirty = code !== activeCode; const isDirty = code !== activeCode;
const shouldPaint = useCallback((pat) => !!(pat?.context?.onPaint && drawContext), [drawContext]);
// TODO: make sure this hook reruns when scheduler.started changes // TODO: make sure this hook reruns when scheduler.started changes
const { scheduler, evaluate, start, stop, pause } = useMemo( const { scheduler, evaluate, start, stop, pause } = useMemo(
@ -93,14 +94,14 @@ function useStrudel({
const drawFirstFrame = useCallback( const drawFirstFrame = useCallback(
(pat) => { (pat) => {
if (drawContext && onDraw) { if (shouldPaint(pat)) {
const [_, lookahead] = drawTime; const [_, lookahead] = drawTime;
const haps = pat.queryArc(0, lookahead); const haps = pat.queryArc(0, lookahead);
// draw at -0.001 to avoid activating haps at 0 // draw at -0.001 to avoid activating haps at 0
onDraw(pat, -0.001, haps, drawTime); onDraw(pat, -0.001, haps, drawTime);
} }
}, },
[drawContext, drawTime, onDraw], [drawTime, onDraw, shouldPaint],
); );
const inited = useRef(); const inited = useRef();
@ -130,7 +131,7 @@ function useStrudel({
usePatternFrame({ usePatternFrame({
pattern, pattern,
started: drawContext && started, started: shouldPaint(pattern) && started,
getTime: () => scheduler.now(), getTime: () => scheduler.now(),
drawTime, drawTime,
onDraw, onDraw,