Implement fixtures and library
This commit is contained in:
parent
60b2b56d8f
commit
1de834020a
@ -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()));
|
||||||
|
|
||||||
|
@ -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));
|
@ -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);
|
25
webserial/src/editor/defaultEnv.d.ts
vendored
25
webserial/src/editor/defaultEnv.d.ts
vendored
@ -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;
|
@ -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
16
webserial/src/eval/lib.ts
Normal 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)];
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
7
webserial/src/eval/tsOptions.ts
Normal file
7
webserial/src/eval/tsOptions.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import type { CompilerOptions } from "typescript"
|
||||||
|
|
||||||
|
const tsOptions: CompilerOptions = {
|
||||||
|
strict: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default tsOptions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,23 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#if navigator.serial}
|
{#if navigator.serial}
|
||||||
<p>Serial available 🚀</p>
|
<p>Serial available 🚀</p>
|
||||||
{#if port !== null}
|
{#if port !== null}
|
||||||
<SerialConnection {port}/>
|
<SerialConnection {port} />
|
||||||
<p><button on:click={disconnect}>disconnect</button></p>
|
<p><button on:click={disconnect}>disconnect</button></p>
|
||||||
|
{:else}
|
||||||
|
<p><button on:click={connect}>connect</button></p>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<p><button on:click={connect}>connect</button></p>
|
<p>Looks like your browser does not support WebSerial 😢</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}
|
||||||
{:else}
|
|
||||||
<p>Looks like your browser does not support WebSerial 😢</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}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
Loading…
Reference in New Issue
Block a user