112 lines
3.6 KiB
JavaScript
112 lines
3.6 KiB
JavaScript
// Aurora Curtains preset for LEDLab
|
|
|
|
const BasePreset = require('./base-preset');
|
|
const { createFrame, toIndex, samplePalette, hexToRgb } = require('./frame-utils');
|
|
|
|
class AuroraCurtainsPreset extends BasePreset {
|
|
constructor(width = 16, height = 16) {
|
|
super(width, height);
|
|
this.bands = [];
|
|
this.defaultParameters = {
|
|
bandCount: 5,
|
|
waveSpeed: 0.35,
|
|
horizontalSway: 0.45,
|
|
brightness: 1.0,
|
|
};
|
|
}
|
|
|
|
init() {
|
|
super.init();
|
|
this.createBands();
|
|
}
|
|
|
|
createBands() {
|
|
const bandCount = this.getParameter('bandCount') || 5;
|
|
this.bands = [];
|
|
|
|
for (let index = 0; index < bandCount; ++index) {
|
|
this.bands.push({
|
|
center: Math.random() * (this.width - 1),
|
|
phase: Math.random() * Math.PI * 2,
|
|
width: 1.2 + Math.random() * 1.8,
|
|
});
|
|
}
|
|
}
|
|
|
|
renderFrame() {
|
|
const frame = createFrame(this.width, this.height);
|
|
const waveSpeed = this.getParameter('waveSpeed') || 0.35;
|
|
const horizontalSway = this.getParameter('horizontalSway') || 0.45;
|
|
const brightness = this.getParameter('brightness') || 1.0;
|
|
const timeSeconds = this.frameCount * 0.05; // Convert frame count to time
|
|
|
|
const paletteStops = [
|
|
{ stop: 0.0, color: hexToRgb('01010a') },
|
|
{ stop: 0.2, color: hexToRgb('041332') },
|
|
{ stop: 0.4, color: hexToRgb('0c3857') },
|
|
{ stop: 0.65, color: hexToRgb('1aa07a') },
|
|
{ stop: 0.85, color: hexToRgb('68d284') },
|
|
{ stop: 1.0, color: hexToRgb('f4f5c6') },
|
|
];
|
|
|
|
for (let row = 0; row < this.height; ++row) {
|
|
const verticalRatio = row / Math.max(1, this.height - 1);
|
|
|
|
for (let col = 0; col < this.width; ++col) {
|
|
let intensity = 0;
|
|
|
|
this.bands.forEach((band, index) => {
|
|
const sway = Math.sin(timeSeconds * waveSpeed + band.phase + verticalRatio * Math.PI * 2) * horizontalSway;
|
|
const center = band.center + sway * (index % 2 === 0 ? 1 : -1);
|
|
const distance = Math.abs(col - center);
|
|
const blurred = Math.exp(-(distance * distance) / (2 * band.width * band.width));
|
|
intensity += blurred * (0.8 + Math.sin(timeSeconds * 0.4 + index) * 0.2);
|
|
});
|
|
|
|
const normalized = Math.min(intensity / this.bands.length, 1);
|
|
const gradientBlend = Math.min((normalized * 0.7 + verticalRatio * 0.3), 1);
|
|
|
|
let colorHex = samplePalette(paletteStops, gradientBlend);
|
|
|
|
// Apply brightness
|
|
if (brightness < 1.0) {
|
|
const rgb = hexToRgb(colorHex);
|
|
colorHex = Math.round(rgb.r * brightness).toString(16).padStart(2, '0') +
|
|
Math.round(rgb.g * brightness).toString(16).padStart(2, '0') +
|
|
Math.round(rgb.b * brightness).toString(16).padStart(2, '0');
|
|
}
|
|
|
|
frame[toIndex(col, row, this.width)] = colorHex;
|
|
}
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
setParameter(name, value) {
|
|
super.setParameter(name, value);
|
|
|
|
// Recreate bands if band-related parameters change
|
|
if (name === 'bandCount') {
|
|
this.createBands();
|
|
}
|
|
}
|
|
|
|
getMetadata() {
|
|
return {
|
|
name: 'Aurora Curtains',
|
|
description: 'Flowing aurora-like curtains with wave motion',
|
|
parameters: {
|
|
bandCount: { type: 'range', min: 3, max: 10, step: 1, default: 5 },
|
|
waveSpeed: { type: 'range', min: 0.1, max: 2.0, step: 0.05, default: 0.35 },
|
|
horizontalSway: { type: 'range', min: 0.1, max: 1.0, step: 0.05, default: 0.45 },
|
|
brightness: { type: 'range', min: 0.1, max: 1.0, step: 0.1, default: 1.0 },
|
|
},
|
|
width: this.width,
|
|
height: this.height,
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = AuroraCurtainsPreset;
|