diff --git a/boilerbloat/src/main/backend.ts b/boilerbloat/src/main/backend.ts index 0b8fd5d..d9825f4 100644 --- a/boilerbloat/src/main/backend.ts +++ b/boilerbloat/src/main/backend.ts @@ -6,6 +6,8 @@ import { TestPattern } from '../patterns/test'; import rust, { BeatTrackerHandle, MovingHeadState, OutputHandle, TrackerConfig } from 'rust_native_module'; import { ChaserPattern } from '../patterns/chaser'; import { HSLRandomMovementPattern } from '../patterns/hslRandom'; +import { HSLRandomMovementPairsPattern } from '../patterns/hslRandom2'; +import { SnoopDoggPattern } from '../patterns/snoop'; export type AppState = { patterns: { [key: string]: PatternOutput }, @@ -63,6 +65,8 @@ class Backend { this.patterns.set("test", new TestPattern()); this.patterns.set("chaser", new ChaserPattern()); this.patterns.set("hslRandom", new HSLRandomMovementPattern()); + this.patterns.set("snoop", new SnoopDoggPattern()); + this.patterns.set("hslRandomPairs", new HSLRandomMovementPairsPattern()); this.state = { patterns: {}, diff --git a/boilerbloat/src/patterns/hslRandom2.ts b/boilerbloat/src/patterns/hslRandom2.ts new file mode 100644 index 0000000..b68b64e --- /dev/null +++ b/boilerbloat/src/patterns/hslRandom2.ts @@ -0,0 +1,105 @@ + +import { panLeft, panRight, startAddresses, tiltDown, tiltUp } from './stage' +import { Pattern, PatternOutput, RenderUpdate } from './proto'; +import { MovingHeadState } from 'rust_native_module'; +import { Tuple4 } from './types'; +import { hsl2rgb, clamp, rescale } from './util'; + +const HSL_CYCLE_LENGTH: number = 7; // seconds +const MOVEMENT_CYCLE_LENGTH: number = 0.5; // seconds? +const THRESHOLD: number = 1.5; + +const panBounds: Tuple4<[number, number]> = [ + [panLeft, panRight], + [panLeft, panRight], + [panLeft, panRight], + [panLeft, panRight], +]; + +const tiltBound: [number, number] = [tiltDown, tiltUp]; + +export class HSLRandomMovementPairsPattern implements Pattern { + + brightness: number; + targets: [[number, number], [number, number]]; + lastUpdate: number; + + constructor() { + this.brightness = 0; + this.targets = [ + [panLeft, tiltUp], + [panRight, tiltUp], + ] + this.lastUpdate = 0; + } + + render(update: RenderUpdate): PatternOutput { + + // color + + const t = update.absolute; + const h = 360 * ((t % HSL_CYCLE_LENGTH) / HSL_CYCLE_LENGTH); + const s = 1; + const v = 0.5; + + const [r, g, b] = hsl2rgb(h, s, v); + const rgbw1: Tuple4 = [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255), + 0 + ]; + + const [r2, g2, b2] = hsl2rgb((h + 90) % 360, s, v); + const rgbw2: Tuple4 = [ + Math.round(r2 * 255), + Math.round(g2 * 255), + Math.round(b2 * 255), + 0 + ]; + + // brightness + + this.brightness = update.bassVolume > THRESHOLD + ? 1 + : 0.75 * this.brightness; + + // movement + + if (t - this.lastUpdate > MOVEMENT_CYCLE_LENGTH) { + + this.lastUpdate = t; + + for (let index in [0, 1]) { + + const bound = panBounds[index]; + + const pan = rescale(Math.random(), { to: bound }); + const tilt = clamp(Math.acos(Math.random()), tiltBound); + + this.targets[index] = [pan, tilt]; + } + } + + return startAddresses.map((startAddress, index) => { + const [pan, tilt] = this.targets[index % 2]; + const rgbw = [rgbw1, rgbw2][index % 2]; + + let state: MovingHeadState = { + startAddress: startAddress, + pan: pan, + tilt: tilt, + brightness: { + type: 'dimmer', + value: 0.2 + 0.8 * this.brightness, + }, + rgbw: rgbw, + speed: 1, + reset: false + } + + return state; + + }) as PatternOutput; + } +} diff --git a/boilerbloat/src/patterns/snoop.ts b/boilerbloat/src/patterns/snoop.ts new file mode 100644 index 0000000..b1d1d88 --- /dev/null +++ b/boilerbloat/src/patterns/snoop.ts @@ -0,0 +1,55 @@ +import { MovingHeadState } from "rust_native_module"; +import { Pattern, PatternOutput, RenderUpdate } from "./proto"; +import { down, panLeft, panRight, startAddresses, tiltUp } from "./stage"; +import { Tuple4 } from "./types"; + +const SNOOPY_COLOR: Tuple4 = [ + 0, 255, 0, 0 +] + +const LEFT_RIGHT_TIME: number = 5 // seconds; + +export class SnoopDoggPattern implements Pattern { + lastUpdate: number; + left: boolean; + + + constructor() { + this.lastUpdate = 0; + this.left = true; + } + + render(update: RenderUpdate): PatternOutput { + const t = update.absolute; + if (t - this.lastUpdate > LEFT_RIGHT_TIME) { + this.left = !this.left; + this.lastUpdate = t; + } + + const tiltTarget = tiltUp + 0.25 * Math.PI * down; + + const target = this.left + ? [panLeft, tiltTarget] + : [panRight, tiltTarget]; + + const [pan, tilt] = target; + + return (startAddresses.map((startAddress) => { + const state: MovingHeadState = { + startAddress: startAddress, + pan: pan, + tilt: tilt, + brightness: { + type: "dimmer", + value: 1, + }, + rgbw: SNOOPY_COLOR, + speed: 0.1, + reset: false + } + + return state; + })) as PatternOutput + } + +} diff --git a/boilerbloat/src/patterns/stage.ts b/boilerbloat/src/patterns/stage.ts index 7e5a564..17e9800 100644 --- a/boilerbloat/src/patterns/stage.ts +++ b/boilerbloat/src/patterns/stage.ts @@ -4,7 +4,12 @@ export const startAddresses: Tuple4 = [1, 15, 29, 43] export const panLeft = 0; export const panRight = Math.PI; -export const panForward = (panLeft + panRight) / 2; +export const panForward = 0.5 * Math.PI; + +export const left = -1; +export const right = 1; +export const up = 1; +export const down = -1; export const tiltUp = 0.5 * Math.PI; export const tiltDown = 0; diff --git a/boilerbloat/src/patterns/test.ts b/boilerbloat/src/patterns/test.ts index e831061..fe056b6 100644 --- a/boilerbloat/src/patterns/test.ts +++ b/boilerbloat/src/patterns/test.ts @@ -13,7 +13,7 @@ export class TestPattern implements Pattern { ] render(update: RenderUpdate): PatternOutput { - let t = update.absolute % this.rgbw.length; + let t = (1.5 * update.absolute) % this.rgbw.length; let second = Math.floor(t); let brightness = 1 - (t % 1); diff --git a/boilerbloat/src/renderer/App.tsx b/boilerbloat/src/renderer/App.tsx index e441ed0..39c50db 100644 --- a/boilerbloat/src/renderer/App.tsx +++ b/boilerbloat/src/renderer/App.tsx @@ -45,7 +45,7 @@ const Frontend: React.FC<{ state: AppState }> = ({ state }) => { return
- +
{ diff --git a/boilerbloat/src/renderer/PatternPreview.tsx b/boilerbloat/src/renderer/PatternPreview.tsx index 8596e40..6a5a403 100644 --- a/boilerbloat/src/renderer/PatternPreview.tsx +++ b/boilerbloat/src/renderer/PatternPreview.tsx @@ -38,7 +38,7 @@ const Cone: React.FC<{ color: string, translate: [number, number] , pan : number // TODO: adjust if necessary const degreesPan = pan / (2* Math.PI) * 360 - 45; - console.log(degreesTilt); + // console.log(degreesTilt); return diff --git a/boilerbloat/src/res/snoop.png b/boilerbloat/src/res/snoop.png new file mode 100644 index 0000000..e59b785 Binary files /dev/null and b/boilerbloat/src/res/snoop.png differ