Implement fixtures and library

This commit is contained in:
Kai Vogelgesang 2022-12-28 02:30:36 +01:00
parent 60b2b56d8f
commit 1de834020a
Signed by: kai
GPG Key ID: 3FC8578CC818A9EB
9 changed files with 185 additions and 28 deletions

View File

@ -7,12 +7,13 @@
import defaultCode from "./defaultCode.ts?raw"; import defaultCode from "./defaultCode.ts?raw";
import defaultEnv from "./defaultEnv.d.ts?raw"; import defaultEnv from "./defaultEnv.d.ts?raw";
import { code } from "./code"; import { code } from "./code";
import tsOptions from "../eval/tsOptions";
let divEl: HTMLDivElement = null; let divEl: HTMLDivElement = null;
let editor: monaco.editor.IStandaloneCodeEditor; let editor: monaco.editor.IStandaloneCodeEditor;
let value = defaultCode; let value = defaultCode;
$: $code = TS.transpile(value, { strict: true }); $: $code = TS.transpile(value, tsOptions);
onMount(async () => { onMount(async () => {
// @ts-ignore // @ts-ignore
@ -30,7 +31,10 @@
language: "typescript", language: "typescript",
}); });
let lib = monaco.languages.typescript.typescriptDefaults.addExtraLib(defaultEnv); let lib =
monaco.languages.typescript.typescriptDefaults.addExtraLib(
defaultEnv
);
editor.onKeyUp((_e) => (value = editor.getValue())); editor.onKeyUp((_e) => (value = editor.getValue()));

View File

@ -1,6 +1,7 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import defaultCode from "./defaultCode.ts?raw"; import defaultCode from "./defaultCode.ts?raw";
import TS from "typescript"; import TS from "typescript";
import tsOptions from "../eval/tsOptions";
/** the transpiled JavaScript code */ /** the transpiled JavaScript code */
export const code = writable(TS.transpile(defaultCode, {strict: true})); export const code = writable(TS.transpile(defaultCode, tsOptions));

View File

@ -1,4 +1,101 @@
// ayaya ayaya // Connect the interface with the button below and modify the code here.
// The output should update in real time as you type :)
ctx.set(1, 255); // Fixtures library. TODO move this into a separate file
ctx.set(2, 255);
class Fixture {
address: number
ctx: Context
constructor(address: number, ctx: Context) {
this.address = address;
this.ctx = ctx;
}
}
interface GenericRGBW {
/**
* Set the brightness
*
* @param value between 0 and 1
* @param strobe enable strobe (turn off if unsupported)
*/
setBrightness(value: number, strobe?: boolean): void
setRGBW(rgb: [number, number, number], w?: number): void
}
class Par extends Fixture implements GenericRGBW {
setBrightness(value: number, strobe?: boolean) {
if (strobe || false) {
this.ctx.set(this.address, 255);
this.ctx.set(this.address + 7, value * 255);
} else {
this.ctx.set(this.address, value * 255);
this.ctx.set(this.address + 7, 0);
}
}
setRGBW(rgb: [number, number, number], w?: number) {
let [r, g, b] = rgb;
this.ctx.set(this.address + 1, r);
this.ctx.set(this.address + 2, g);
this.ctx.set(this.address + 3, b);
this.ctx.set(this.address + 4, w || 0);
}
setAUV(a: number, uv: number) {
this.ctx.set(this.address + 5, a);
this.ctx.set(this.address + 6, uv);
}
}
class MovingHead extends Fixture implements GenericRGBW {
setBrightness(value: number, strobe?: boolean) {
let out = (strobe || false)
? 135 + (239 - 135) * value
: 8 + (134 - 8) * value;
this.ctx.set(this.address + 5, out);
}
setRGBW(rgb: [number, number, number], w?: number) {
let [r, g, b] = rgb;
this.ctx.set(this.address + 6, r);
this.ctx.set(this.address + 7, g);
this.ctx.set(this.address + 8, b);
this.ctx.set(this.address + 9, w || 0);
}
/**
* Rotate the moving head. Pan and tilt are in radians.
* @param pan between -1.5pi and 1.5pi
* @param tilt between -0.5pi and 0.5pi
* @param speed between 0 (fast) and 255 (slow)
*/
setPanTilt(pan: number, tilt: number, speed?: number) {
let panRough = (pan + 3 * Math.PI / 2) / (Math.PI * 3) * 256
panRough = Math.max(0, Math.min(255, panRough))
let tiltRough = (tilt + Math.PI / 2) / (Math.PI) * 256
tiltRough = Math.max(0, Math.min(255, tiltRough))
// TODO
let panFine = 0
let tiltFine = 0
this.ctx.set(this.address + 0, panRough);
this.ctx.set(this.address + 1, panFine);
this.ctx.set(this.address + 2, tiltRough);
this.ctx.set(this.address + 3, tiltFine);
this.ctx.set(this.address + 4, speed || 0);
}
}
// ******************
// * CODE GOES HERE *
// ******************
let color = lib.hsl2rgb(360 * t, 100, 50);
let par = new Par(1, ctx);
par.setBrightness(1);
par.setRGBW(color);

View File

@ -1,9 +1,30 @@
type Context = { type Context = {
/**
* Set DMX address `address` to `value`
* @param address between 1 and 511
* @param value between 0 and 255
*/
set(address: number, value: number): void, set(address: number, value: number): void,
}; };
/** the global Context object */ /** The global Context object */
declare const ctx: Context; declare const ctx: Context;
/** the current time (in seconds, e.g. 1.25 after 1250 milliseconds) */ /** The current time (in seconds, e.g. 1.25 after 1250 milliseconds) */
declare const t: number; declare const t: number;
type Lib = {
/**
* Converts from the HSL color space to RGB
*
* Outputs [r, g, b] between 0 and 255 each
*
* @param h in degrees, i.e. 0 to 360
* @param s between 0 and 100
* @param l between 0 and 100
*/
hsl2rgb(h: number, s: number, l: number): [number, number, number]
}
/** The standard library */
declare const lib: Lib;

View File

@ -3,14 +3,16 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { code } from "../editor/code"; import { code } from "../editor/code";
import { dmxData } from "../dmx/store"; import { dmxData } from "../dmx/store";
import { lib } from "./lib";
let startTime: number; let startTime: number;
let payload = new Uint8Array(512); let payload = new Uint8Array(512);
let ctx: Context = { let ctx: Context = {
set(address: number, value: number) { set(address: number, value: number) {
payload[address - 1] = value; let rounded = Math.round(value);
} payload[address - 1] = Math.max(0, Math.min(255, rounded));
} },
};
let result: string; let result: string;
@ -18,7 +20,7 @@
payload = new Uint8Array(512); payload = new Uint8Array(512);
const t = (performance.now() - startTime) / 1000; const t = (performance.now() - startTime) / 1000;
try { try {
let ret = Function("ctx", "t", $code).call({}, ctx, t); let ret = Function("ctx", "t", "lib", $code).call({}, ctx, t, lib);
result = JSON.stringify(ret); result = JSON.stringify(ret);
} catch (err) { } catch (err) {
result = JSON.stringify(err); result = JSON.stringify(err);
@ -36,8 +38,8 @@
return () => { return () => {
clearInterval(int); clearInterval(int);
} };
}) });
</script> </script>
<!-- <pre>{result}</pre> --> <!-- <pre>{result}</pre> -->

16
webserial/src/eval/lib.ts Normal file
View File

@ -0,0 +1,16 @@
/// <reference path="../editor/defaultEnv.d.ts" />
export const lib: Lib = {
hsl2rgb(h, s, l): [number, number, number] {
// https://stackoverflow.com/a/44134328
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color)
};
return [f(0), f(8), f(4)];
},
}

View File

@ -0,0 +1,7 @@
import type { CompilerOptions } from "typescript"
const tsOptions: CompilerOptions = {
strict: true
}
export default tsOptions

View File

@ -98,7 +98,11 @@
if (loopTime < FRAME_TIME) { if (loopTime < FRAME_TIME) {
await sleep(FRAME_TIME - loopTime); await sleep(FRAME_TIME - loopTime);
} else { } else {
console.warn(`loop took too long (+${(loopTime - FRAME_TIME).toFixed(2)} ms)`); console.warn(
`loop took too long (+${(loopTime - FRAME_TIME).toFixed(
2
)} ms)`
);
} }
lastLoopTime = loopTime; lastLoopTime = loopTime;
} }

View File

@ -24,7 +24,12 @@
{/if} {/if}
{:else} {:else}
<p>Looks like your browser does not support WebSerial &#x1f622;</p> <p>Looks like your browser does not support WebSerial &#x1f622;</p>
<p>Check <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility">here</a> for a list of compatible browsers</p> <p>
Check <a
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility"
>here</a
> for a list of compatible browsers
</p>
{/if} {/if}
</div> </div>