Add 5 procedural LED effects, gradient presets, auto-crop min aspect ratio, static source polling optimization
New features: - Procedural effect source type with fire, meteor, plasma, noise, and aurora algorithms using palette LUT system and 1D value noise generator - 12 predefined gradient presets (rainbow, sunset, ocean, forest, fire, lava, aurora, ice, warm, cool, neon, pastel) selectable from a dropdown in the gradient editor - Auto-crop filter: min aspect ratio parameter to prevent false-positive cropping in dark scenes on ultrawide displays Optimization: - Static/gradient sources without animation: stream thread sleeps 0.25s instead of frame_time; processor repolls at frame_time instead of 5ms (~40x fewer iterations) - Inverted isinstance checks in routes to test for PictureColorStripSource only Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
<option value="static" data-i18n="color_strip.type.static">Static Color</option>
|
||||
<option value="gradient" data-i18n="color_strip.type.gradient">Gradient</option>
|
||||
<option value="color_cycle" data-i18n="color_strip.type.color_cycle">Color Cycle</option>
|
||||
<option value="effect" data-i18n="color_strip.type.effect">Procedural Effect</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -166,6 +167,29 @@
|
||||
|
||||
<!-- Gradient-specific fields -->
|
||||
<div id="css-editor-gradient-section" style="display:none">
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-gradient-preset" data-i18n="color_strip.gradient.preset">Preset:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.gradient.preset.hint">Load a predefined gradient palette. Selecting a preset replaces the current stops.</small>
|
||||
<select id="css-editor-gradient-preset" onchange="applyGradientPreset(this.value)">
|
||||
<option value="" data-i18n="color_strip.gradient.preset.custom">— Custom —</option>
|
||||
<option value="rainbow" data-i18n="color_strip.gradient.preset.rainbow">Rainbow</option>
|
||||
<option value="sunset" data-i18n="color_strip.gradient.preset.sunset">Sunset</option>
|
||||
<option value="ocean" data-i18n="color_strip.gradient.preset.ocean">Ocean</option>
|
||||
<option value="forest" data-i18n="color_strip.gradient.preset.forest">Forest</option>
|
||||
<option value="fire" data-i18n="color_strip.gradient.preset.fire">Fire</option>
|
||||
<option value="lava" data-i18n="color_strip.gradient.preset.lava">Lava</option>
|
||||
<option value="aurora" data-i18n="color_strip.gradient.preset.aurora">Aurora</option>
|
||||
<option value="ice" data-i18n="color_strip.gradient.preset.ice">Ice</option>
|
||||
<option value="warm" data-i18n="color_strip.gradient.preset.warm">Warm</option>
|
||||
<option value="cool" data-i18n="color_strip.gradient.preset.cool">Cool</option>
|
||||
<option value="neon" data-i18n="color_strip.gradient.preset.neon">Neon</option>
|
||||
<option value="pastel" data-i18n="color_strip.gradient.preset.pastel">Pastel</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label data-i18n="color_strip.gradient.preview">Gradient:</label>
|
||||
@@ -188,6 +212,103 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Procedural effect fields -->
|
||||
<div id="css-editor-effect-section" style="display:none">
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-type" data-i18n="color_strip.effect.type">Effect:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.type.hint">The procedural effect algorithm to use.</small>
|
||||
<select id="css-editor-effect-type" onchange="onEffectTypeChange()">
|
||||
<option value="fire" data-i18n="color_strip.effect.fire">Fire</option>
|
||||
<option value="meteor" data-i18n="color_strip.effect.meteor">Meteor</option>
|
||||
<option value="plasma" data-i18n="color_strip.effect.plasma">Plasma</option>
|
||||
<option value="noise" data-i18n="color_strip.effect.noise">Perlin Noise</option>
|
||||
<option value="aurora" data-i18n="color_strip.effect.aurora">Aurora</option>
|
||||
</select>
|
||||
<small id="css-editor-effect-type-desc" class="field-desc"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-speed">
|
||||
<span data-i18n="color_strip.effect.speed">Speed:</span>
|
||||
<span id="css-editor-effect-speed-val">1.0</span>x
|
||||
</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.speed.hint">How fast the effect animates. 1.0 = default speed.</small>
|
||||
<input type="range" id="css-editor-effect-speed" min="0.1" max="10.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-effect-speed-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-palette-group" class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-palette" data-i18n="color_strip.effect.palette">Palette:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.palette.hint">Color palette used by the effect.</small>
|
||||
<select id="css-editor-effect-palette">
|
||||
<option value="fire" data-i18n="color_strip.palette.fire">Fire</option>
|
||||
<option value="ocean" data-i18n="color_strip.palette.ocean">Ocean</option>
|
||||
<option value="lava" data-i18n="color_strip.palette.lava">Lava</option>
|
||||
<option value="forest" data-i18n="color_strip.palette.forest">Forest</option>
|
||||
<option value="rainbow" data-i18n="color_strip.palette.rainbow">Rainbow</option>
|
||||
<option value="aurora" data-i18n="color_strip.palette.aurora">Aurora</option>
|
||||
<option value="sunset" data-i18n="color_strip.palette.sunset">Sunset</option>
|
||||
<option value="ice" data-i18n="color_strip.palette.ice">Ice</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-color-group" class="form-group" style="display:none">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-color" data-i18n="color_strip.effect.color">Color:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.color.hint">Head color for the meteor effect.</small>
|
||||
<input type="color" id="css-editor-effect-color" value="#ff5000">
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-intensity-group" class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-intensity">
|
||||
<span data-i18n="color_strip.effect.intensity">Intensity:</span>
|
||||
<span id="css-editor-effect-intensity-val">1.0</span>
|
||||
</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.intensity.hint">Effect-specific intensity.</small>
|
||||
<input type="range" id="css-editor-effect-intensity" min="0.1" max="2.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-effect-intensity-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-scale-group" class="form-group" style="display:none">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-scale">
|
||||
<span data-i18n="color_strip.effect.scale">Scale:</span>
|
||||
<span id="css-editor-effect-scale-val">1.0</span>
|
||||
</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.scale.hint">Spatial zoom level.</small>
|
||||
<input type="range" id="css-editor-effect-scale" min="0.5" max="5.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-effect-scale-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-mirror-group" class="form-group" style="display:none">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-mirror" data-i18n="color_strip.effect.mirror">Mirror:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="color_strip.effect.mirror.hint">Bounce back and forth instead of wrapping around.</small>
|
||||
<label class="settings-toggle">
|
||||
<input type="checkbox" id="css-editor-effect-mirror">
|
||||
<span class="settings-toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Animation — shown for static/gradient, hidden for picture -->
|
||||
<div id="css-editor-animation-section" style="display:none">
|
||||
<details class="form-collapse">
|
||||
|
||||
Reference in New Issue
Block a user