feat: BindableFloat — universal value source binding for all scalar properties
Lint & Test / test (push) Successful in 1m20s
Lint & Test / test (push) Successful in 1m20s
Introduce BindableFloat abstraction that allows any numeric property to be
either a static value or dynamically driven by a ValueSource. Backward-compatible
serialization: plain float when unbound, {value, source_id} dict when bound.
Backend:
- storage/bindable.py — BindableFloat dataclass + bfloat() helper
- 25+ scalar properties converted across all entity types
- Runtime VS acquisition in ColorStripStreamManager for CSS bindings
- All stream hot loops use self.resolve() for live values
- KeyColorsColorStripStream now inherits ColorStripStream
Frontend:
- BindableScalarWidget (slider + VS picker toggle) for all editors
- TypeScript BindableFloat type + helpers
- Graph editor edges for all bindable properties
- Audio source channel IconSelect grid
Fixes: daylight longitude, candlelight wind_strength/candle_type from_dict
This commit is contained in:
@@ -67,14 +67,13 @@
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-smoothing">
|
||||
<label>
|
||||
<span data-i18n="color_strip.smoothing">Smoothing:</span>
|
||||
<span id="css-editor-smoothing-value">0.30</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.smoothing.hint">Temporal blending between frames (0=none, 1=full). Reduces flicker.</small>
|
||||
<input type="range" id="css-editor-smoothing" min="0.0" max="1.0" step="0.05" value="0.3" oninput="document.getElementById('css-editor-smoothing-value').textContent = parseFloat(this.value).toFixed(2)">
|
||||
<div id="css-editor-smoothing-container"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -176,28 +175,24 @@
|
||||
|
||||
<div id="css-editor-effect-intensity-group" class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-intensity">
|
||||
<label>
|
||||
<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 id="css-editor-effect-intensity-container"></div>
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-scale-group" class="form-group" style="display:none">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-effect-scale">
|
||||
<label>
|
||||
<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 id="css-editor-effect-scale-container"></div>
|
||||
</div>
|
||||
|
||||
<div id="css-editor-effect-mirror-group" class="form-group" style="display:none">
|
||||
@@ -267,28 +262,24 @@
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-audio-sensitivity">
|
||||
<label>
|
||||
<span data-i18n="color_strip.audio.sensitivity">Sensitivity:</span>
|
||||
<span id="css-editor-audio-sensitivity-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.audio.sensitivity.hint">Gain multiplier for audio levels. Higher values make LEDs react to quieter sounds.</small>
|
||||
<input type="range" id="css-editor-audio-sensitivity" min="0.1" max="5.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-audio-sensitivity-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-audio-sensitivity-container"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-audio-smoothing">
|
||||
<label>
|
||||
<span data-i18n="color_strip.audio.smoothing">Smoothing:</span>
|
||||
<span id="css-editor-audio-smoothing-val">0.30</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.audio.smoothing.hint">Temporal smoothing between frames. Higher values produce smoother but slower-reacting visuals.</small>
|
||||
<input type="range" id="css-editor-audio-smoothing" min="0.0" max="1.0" step="0.05" value="0.3"
|
||||
oninput="document.getElementById('css-editor-audio-smoothing-val').textContent = parseFloat(this.value).toFixed(2)">
|
||||
<div id="css-editor-audio-smoothing-container"></div>
|
||||
</div>
|
||||
|
||||
<div id="css-editor-audio-palette-group" class="form-group">
|
||||
@@ -353,15 +344,13 @@
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-api-input-timeout">
|
||||
<label>
|
||||
<span data-i18n="color_strip.api_input.timeout">Timeout (seconds):</span>
|
||||
<span id="css-editor-api-input-timeout-val">5.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.api_input.timeout.hint">How long to wait for new color data before reverting to the fallback color.</small>
|
||||
<input type="range" id="css-editor-api-input-timeout" min="0" max="60" step="0.5" value="5.0"
|
||||
oninput="document.getElementById('css-editor-api-input-timeout-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-api-input-timeout-container"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -418,15 +407,13 @@
|
||||
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-notification-duration">
|
||||
<label>
|
||||
<span data-i18n="color_strip.notification.duration">Duration (ms):</span>
|
||||
<span id="css-editor-notification-duration-val">1500</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.notification.duration.hint">How long the notification effect plays, in milliseconds.</small>
|
||||
<input type="range" id="css-editor-notification-duration" min="100" max="10000" step="100" value="1500"
|
||||
oninput="document.getElementById('css-editor-notification-duration-val').textContent = this.value">
|
||||
<div id="css-editor-notification-duration-container"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -573,12 +560,11 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-candlelight-intensity"><span data-i18n="color_strip.candlelight.intensity">Flicker Intensity:</span> <span id="css-editor-candlelight-intensity-val">1.0</span></label>
|
||||
<label><span data-i18n="color_strip.candlelight.intensity">Flicker Intensity:</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.candlelight.intensity.hint">How much the candles flicker. Low values = gentle glow, high values = windy candle.</small>
|
||||
<input type="range" id="css-editor-candlelight-intensity" min="0.1" max="2.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-candlelight-intensity-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-candlelight-intensity-container"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
@@ -590,21 +576,19 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-candlelight-speed"><span data-i18n="color_strip.candlelight.speed">Flicker Speed:</span> <span id="css-editor-candlelight-speed-val">1.0</span></label>
|
||||
<label><span data-i18n="color_strip.candlelight.speed">Flicker Speed:</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.candlelight.speed.hint">Speed of the flicker animation. Higher values produce faster, more restless flames.</small>
|
||||
<input type="range" id="css-editor-candlelight-speed" min="0.1" max="5.0" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-candlelight-speed-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-candlelight-speed-container"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-candlelight-wind"><span data-i18n="color_strip.candlelight.wind">Wind:</span> <span id="css-editor-candlelight-wind-val">0.0</span></label>
|
||||
<label><span data-i18n="color_strip.candlelight.wind">Wind:</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.candlelight.wind.hint">Wind simulation strength. Higher values create correlated gusts across all candles.</small>
|
||||
<input type="range" id="css-editor-candlelight-wind" min="0.0" max="2.0" step="0.1" value="0.0"
|
||||
oninput="document.getElementById('css-editor-candlelight-wind-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-candlelight-wind-container"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
@@ -636,21 +620,19 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-weather-speed"><span data-i18n="color_strip.weather.speed">Animation Speed:</span> <span id="css-editor-weather-speed-val">1.0</span></label>
|
||||
<label><span data-i18n="color_strip.weather.speed">Animation Speed:</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.weather.speed.hint">Speed of the ambient color drift animation</small>
|
||||
<input type="range" id="css-editor-weather-speed" min="0.1" max="5" step="0.1" value="1.0"
|
||||
oninput="document.getElementById('css-editor-weather-speed-val').textContent = parseFloat(this.value).toFixed(1)">
|
||||
<div id="css-editor-weather-speed-container"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-weather-temp-influence"><span data-i18n="color_strip.weather.temperature_influence">Temperature Influence:</span> <span id="css-editor-weather-temp-val">0.5</span></label>
|
||||
<label><span data-i18n="color_strip.weather.temperature_influence">Temperature Influence:</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.weather.temperature_influence.hint">How much the current temperature shifts the color palette warm/cool. 0 = pure condition colors, 1 = strong shift.</small>
|
||||
<input type="range" id="css-editor-weather-temp-influence" min="0" max="1" step="0.05" value="0.5"
|
||||
oninput="document.getElementById('css-editor-weather-temp-val').textContent = parseFloat(this.value).toFixed(2)">
|
||||
<div id="css-editor-weather-temp-influence-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -697,17 +679,15 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-kc-smoothing"><span data-i18n="color_strip.key_colors.smoothing">Smoothing:</span> <span id="css-editor-kc-smoothing-val">0.30</span></label>
|
||||
<label><span data-i18n="color_strip.key_colors.smoothing">Smoothing:</span></label>
|
||||
</div>
|
||||
<input type="range" id="css-editor-kc-smoothing" min="0" max="1" step="0.05" value="0.3"
|
||||
oninput="document.getElementById('css-editor-kc-smoothing-val').textContent = parseFloat(this.value).toFixed(2)">
|
||||
<div id="css-editor-kc-smoothing-container"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="label-row">
|
||||
<label for="css-editor-kc-brightness"><span data-i18n="color_strip.key_colors.brightness">Brightness:</span> <span id="css-editor-kc-brightness-val">1.00</span></label>
|
||||
<label><span data-i18n="color_strip.key_colors.brightness">Brightness:</span></label>
|
||||
</div>
|
||||
<input type="range" id="css-editor-kc-brightness" min="0" max="1" step="0.05" value="1.0"
|
||||
oninput="document.getElementById('css-editor-kc-brightness-val').textContent = parseFloat(this.value).toFixed(2)">
|
||||
<div id="css-editor-kc-brightness-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user