// Spiral Bloom preset for LEDLab const BasePreset = require('./base-preset'); const { createFrame, frameToPayload, hexToRgb, samplePalette, toIndex } = require('./frame-utils'); class SpiralBloomPreset extends BasePreset { constructor(width = 16, height = 16) { super(width, height); this.rotation = 0; this.hueShift = 0; this.paletteStops = [ { stop: 0.0, color: hexToRgb('051923') }, { stop: 0.2, color: hexToRgb('0c4057') }, { stop: 0.45, color: hexToRgb('1d7a70') }, { stop: 0.7, color: hexToRgb('39b15f') }, { stop: 0.88, color: hexToRgb('9dd54c') }, { stop: 1.0, color: hexToRgb('f7f5bc') }, ]; this.defaultParameters = { rotationSpeed: 0.7, hueSpeed: 0.2, spiralArms: 5, brightness: 1.0, }; } renderFrame() { this.rotation += 0.016 * (this.getParameter('rotationSpeed') || 0.7); this.hueShift += 0.016 * (this.getParameter('hueSpeed') || 0.2); const frame = createFrame(this.width, this.height); const brightness = this.getParameter('brightness') || 1.0; const spiralArms = this.getParameter('spiralArms') || 5; const cx = (this.width - 1) / 2; const cy = (this.height - 1) / 2; const radiusNorm = Math.hypot(cx, cy) || 1; for (let row = 0; row < this.height; ++row) { for (let col = 0; col < this.width; ++col) { const dx = col - cx; const dy = row - cy; const radius = Math.hypot(dx, dy) / radiusNorm; const angle = Math.atan2(dy, dx); const arm = 0.5 + 0.5 * Math.sin(spiralArms * (angle + this.rotation) + this.hueShift * Math.PI * 2); const value = Math.min(1, radius * 0.8 + arm * 0.4); let color = samplePalette(this.paletteStops, value); // Apply brightness if (brightness < 1.0) { const rgb = hexToRgb(color); color = 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)] = color; } } return frame; } getMetadata() { return { name: 'Spiral Bloom', description: 'Rotating spiral patterns blooming outward', parameters: { rotationSpeed: { type: 'range', min: 0.3, max: 1.5, step: 0.1, default: 0.7 }, hueSpeed: { type: 'range', min: 0.1, max: 0.5, step: 0.05, default: 0.2 }, spiralArms: { type: 'range', min: 3, max: 8, step: 1, default: 5 }, brightness: { type: 'range', min: 0.3, max: 1.0, step: 0.1, default: 1.0 }, }, width: this.width, height: this.height, }; } } module.exports = SpiralBloomPreset;