Add Daylight Cycle value source type
New value source that outputs brightness (0-1) based on the daylight color LUT, computing BT.601 luminance from the simulated sky color. Supports real-time wall-clock mode or configurable simulation speed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -132,6 +132,7 @@ import {
|
||||
import {
|
||||
showValueSourceModal, closeValueSourceModal, saveValueSource,
|
||||
editValueSource, cloneValueSource, deleteValueSource, onValueSourceTypeChange,
|
||||
onDaylightVSRealTimeChange,
|
||||
addSchedulePoint,
|
||||
testValueSource, closeTestValueSourceModal,
|
||||
} from './features/value-sources.js';
|
||||
@@ -409,6 +410,7 @@ Object.assign(window, {
|
||||
cloneValueSource,
|
||||
deleteValueSource,
|
||||
onValueSourceTypeChange,
|
||||
onDaylightVSRealTimeChange,
|
||||
addSchedulePoint,
|
||||
testValueSource,
|
||||
closeTestValueSourceModal,
|
||||
|
||||
@@ -30,6 +30,7 @@ const _colorStripTypeIcons = {
|
||||
const _valueSourceTypeIcons = {
|
||||
static: _svg(P.layoutDashboard), animated: _svg(P.refreshCw), audio: _svg(P.music),
|
||||
adaptive_time: _svg(P.clock), adaptive_scene: _svg(P.cloudSun),
|
||||
daylight: _svg(P.sun),
|
||||
};
|
||||
const _audioSourceTypeIcons = { mono: _svg(P.mic), multichannel: _svg(P.volume2) };
|
||||
const _deviceTypeIcons = {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Modal } from '../core/modal.js';
|
||||
import {
|
||||
getValueSourceIcon, getAudioSourceIcon, getPictureSourceIcon,
|
||||
ICON_CLONE, ICON_EDIT, ICON_TEST,
|
||||
ICON_LED_PREVIEW, ICON_ACTIVITY, ICON_TIMER, ICON_MOVE_VERTICAL,
|
||||
ICON_LED_PREVIEW, ICON_ACTIVITY, ICON_TIMER, ICON_MOVE_VERTICAL, ICON_CLOCK,
|
||||
ICON_MUSIC, ICON_TRENDING_UP, ICON_MAP_PIN, ICON_MONITOR, ICON_REFRESH,
|
||||
} from '../core/icons.js';
|
||||
import { wrapCard } from '../core/card-colors.js';
|
||||
@@ -64,6 +64,9 @@ class ValueSourceModal extends Modal {
|
||||
sceneSensitivity: document.getElementById('value-source-scene-sensitivity').value,
|
||||
sceneSmoothing: document.getElementById('value-source-scene-smoothing').value,
|
||||
schedule: JSON.stringify(_getScheduleFromUI()),
|
||||
daylightSpeed: document.getElementById('value-source-daylight-speed').value,
|
||||
daylightRealTime: document.getElementById('value-source-daylight-real-time').checked,
|
||||
daylightLatitude: document.getElementById('value-source-daylight-latitude').value,
|
||||
tags: JSON.stringify(_vsTagsInput ? _vsTagsInput.getValue() : []),
|
||||
};
|
||||
}
|
||||
@@ -97,7 +100,7 @@ function _autoGenerateVSName() {
|
||||
|
||||
/* ── Icon-grid type selector ──────────────────────────────────── */
|
||||
|
||||
const VS_TYPE_KEYS = ['static', 'animated', 'audio', 'adaptive_time', 'adaptive_scene'];
|
||||
const VS_TYPE_KEYS = ['static', 'animated', 'audio', 'adaptive_time', 'adaptive_scene', 'daylight'];
|
||||
|
||||
function _buildVSTypeItems() {
|
||||
return VS_TYPE_KEYS.map(key => ({
|
||||
@@ -213,6 +216,13 @@ export async function showValueSourceModal(editData) {
|
||||
_setSlider('value-source-scene-smoothing', editData.smoothing ?? 0.3);
|
||||
_setSlider('value-source-adaptive-min-value', editData.min_value ?? 0);
|
||||
_setSlider('value-source-adaptive-max-value', editData.max_value ?? 1);
|
||||
} else if (editData.source_type === 'daylight') {
|
||||
_setSlider('value-source-daylight-speed', editData.speed ?? 1.0);
|
||||
document.getElementById('value-source-daylight-real-time').checked = !!editData.use_real_time;
|
||||
_setSlider('value-source-daylight-latitude', editData.latitude ?? 50);
|
||||
_syncDaylightVSSpeedVisibility();
|
||||
_setSlider('value-source-adaptive-min-value', editData.min_value ?? 0);
|
||||
_setSlider('value-source-adaptive-max-value', editData.max_value ?? 1);
|
||||
}
|
||||
} else {
|
||||
document.getElementById('value-source-name').value = '';
|
||||
@@ -240,6 +250,11 @@ export async function showValueSourceModal(editData) {
|
||||
_setSlider('value-source-scene-smoothing', 0.3);
|
||||
_setSlider('value-source-adaptive-min-value', 0);
|
||||
_setSlider('value-source-adaptive-max-value', 1);
|
||||
// Daylight defaults
|
||||
_setSlider('value-source-daylight-speed', 1.0);
|
||||
document.getElementById('value-source-daylight-real-time').checked = false;
|
||||
_setSlider('value-source-daylight-latitude', 50);
|
||||
_syncDaylightVSSpeedVisibility();
|
||||
_autoGenerateVSName();
|
||||
}
|
||||
|
||||
@@ -271,8 +286,9 @@ export function onValueSourceTypeChange() {
|
||||
if (type === 'audio') _ensureAudioModeIconSelect();
|
||||
document.getElementById('value-source-adaptive-time-section').style.display = type === 'adaptive_time' ? '' : 'none';
|
||||
document.getElementById('value-source-adaptive-scene-section').style.display = type === 'adaptive_scene' ? '' : 'none';
|
||||
document.getElementById('value-source-daylight-section').style.display = type === 'daylight' ? '' : 'none';
|
||||
document.getElementById('value-source-adaptive-range-section').style.display =
|
||||
(type === 'adaptive_time' || type === 'adaptive_scene') ? '' : 'none';
|
||||
(type === 'adaptive_time' || type === 'adaptive_scene' || type === 'daylight') ? '' : 'none';
|
||||
|
||||
// Populate audio dropdown when switching to audio type
|
||||
if (type === 'audio') {
|
||||
@@ -290,6 +306,17 @@ export function onValueSourceTypeChange() {
|
||||
_autoGenerateVSName();
|
||||
}
|
||||
|
||||
// ── Daylight helpers ──────────────────────────────────────────
|
||||
|
||||
export function onDaylightVSRealTimeChange() {
|
||||
_syncDaylightVSSpeedVisibility();
|
||||
}
|
||||
|
||||
function _syncDaylightVSSpeedVisibility() {
|
||||
const rt = document.getElementById('value-source-daylight-real-time').checked;
|
||||
document.getElementById('value-source-daylight-speed-group').style.display = rt ? 'none' : '';
|
||||
}
|
||||
|
||||
// ── Save ──────────────────────────────────────────────────────
|
||||
|
||||
export async function saveValueSource() {
|
||||
@@ -338,6 +365,12 @@ export async function saveValueSource() {
|
||||
payload.smoothing = parseFloat(document.getElementById('value-source-scene-smoothing').value);
|
||||
payload.min_value = parseFloat(document.getElementById('value-source-adaptive-min-value').value);
|
||||
payload.max_value = parseFloat(document.getElementById('value-source-adaptive-max-value').value);
|
||||
} else if (sourceType === 'daylight') {
|
||||
payload.speed = parseFloat(document.getElementById('value-source-daylight-speed').value);
|
||||
payload.use_real_time = document.getElementById('value-source-daylight-real-time').checked;
|
||||
payload.latitude = parseFloat(document.getElementById('value-source-daylight-latitude').value);
|
||||
payload.min_value = parseFloat(document.getElementById('value-source-adaptive-min-value').value);
|
||||
payload.max_value = parseFloat(document.getElementById('value-source-adaptive-max-value').value);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -632,6 +665,13 @@ export function createValueSourceCard(src) {
|
||||
<span class="stream-card-prop">${ICON_MAP_PIN} ${pts} ${t('value_source.schedule.points')}</span>
|
||||
<span class="stream-card-prop">${ICON_MOVE_VERTICAL} ${src.min_value ?? 0}–${src.max_value ?? 1}</span>
|
||||
`;
|
||||
} else if (src.source_type === 'daylight') {
|
||||
if (src.use_real_time) {
|
||||
propsHtml = `<span class="stream-card-prop">${ICON_CLOCK} ${t('value_source.daylight.real_time')}</span>`;
|
||||
} else {
|
||||
propsHtml = `<span class="stream-card-prop">${ICON_TIMER} ${t('value_source.daylight.speed_label')} ${src.speed ?? 1.0}x</span>`;
|
||||
}
|
||||
propsHtml += `<span class="stream-card-prop">${ICON_MOVE_VERTICAL} ${src.min_value ?? 0}\u2013${src.max_value ?? 1}</span>`;
|
||||
} else if (src.source_type === 'adaptive_scene') {
|
||||
const ps = _cachedStreams.find(s => s.id === src.picture_source_id);
|
||||
const psName = ps ? ps.name : (src.picture_source_id || '-');
|
||||
|
||||
Reference in New Issue
Block a user