217 lines
7.5 KiB
JavaScript
217 lines
7.5 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function () {
|
|
// UI Elements
|
|
const sceneListEl = document.querySelector('.scene-list');
|
|
const previewPanel = document.getElementById('preview-panel');
|
|
const programPanel = document.getElementById('program-panel');
|
|
const previewContent = previewPanel.querySelector('.scene-content');
|
|
const programContent = programPanel.querySelector('.scene-content');
|
|
const cutButton = document.getElementById('cut-button');
|
|
|
|
// Modal Elements
|
|
const addSceneBtn = document.getElementById('add-scene-btn');
|
|
const modal = document.getElementById('add-scene-modal');
|
|
const modalCloseBtn = document.getElementById('modal-close-btn');
|
|
const modalCancelBtn = document.getElementById('modal-cancel-btn');
|
|
const modalSaveBtn = document.getElementById('modal-save-btn');
|
|
const sceneNameInput = document.getElementById('scene-name-input');
|
|
const sceneTypeSelect = document.getElementById('scene-type-select');
|
|
|
|
// Source settings elements
|
|
const colorSettings = document.getElementById('source-color-group');
|
|
const imageSettings = document.getElementById('source-image-group');
|
|
const sceneColorInput = document.getElementById('scene-color-input');
|
|
const sceneImageUrlInput = document.getElementById('scene-image-url-input');
|
|
|
|
// Data Store
|
|
let scenes = [];
|
|
let activePreviewSceneId = null;
|
|
let activeProgramSceneId = null;
|
|
let sceneIdCounter = 0;
|
|
|
|
// --- DATA MANAGEMENT ---
|
|
function addScene(name, type, value) {
|
|
const newScene = {
|
|
id: sceneIdCounter++,
|
|
name: name,
|
|
type: type,
|
|
value: value
|
|
};
|
|
scenes.push(newScene);
|
|
renderSceneList();
|
|
return newScene;
|
|
}
|
|
|
|
function removeScene(id) {
|
|
scenes = scenes.filter(scene => scene.id !== id);
|
|
if (activePreviewSceneId === id) {
|
|
clearPreview();
|
|
}
|
|
renderSceneList();
|
|
}
|
|
|
|
function getScene(id) {
|
|
return scenes.find(scene => scene.id === id);
|
|
}
|
|
|
|
// --- UI RENDERING ---
|
|
function renderSceneList() {
|
|
sceneListEl.innerHTML = ''; // Clear existing list
|
|
scenes.forEach(scene => {
|
|
const icon = getIconForSceneType(scene.type);
|
|
const item = document.createElement('div');
|
|
item.className = 'list-group-item list-group-item-action';
|
|
item.dataset.sceneId = scene.id;
|
|
if (scene.id === activePreviewSceneId) {
|
|
item.classList.add('active');
|
|
}
|
|
item.innerHTML = `
|
|
<span class="scene-name">${icon} ${scene.name}</span>
|
|
<button class="btn-close btn-close-white remove-scene-btn" aria-label="Remove"></button>
|
|
`;
|
|
sceneListEl.appendChild(item);
|
|
});
|
|
}
|
|
|
|
function updatePreview(sceneId) {
|
|
const scene = getScene(sceneId);
|
|
if (!scene) return;
|
|
|
|
activePreviewSceneId = scene.id;
|
|
|
|
// Clear previous styles
|
|
previewPanel.style.backgroundColor = '#000';
|
|
previewPanel.style.backgroundImage = 'none';
|
|
previewContent.textContent = scene.name;
|
|
|
|
switch (scene.type) {
|
|
case 'color':
|
|
previewPanel.style.backgroundColor = scene.value;
|
|
break;
|
|
case 'image':
|
|
previewPanel.style.backgroundImage = `url('${scene.value}')`;
|
|
break;
|
|
default:
|
|
previewPanel.style.backgroundColor = '#000';
|
|
break;
|
|
}
|
|
renderSceneList(); // Re-render to show active state
|
|
}
|
|
|
|
function clearPreview() {
|
|
activePreviewSceneId = null;
|
|
previewContent.textContent = 'Select a Scene';
|
|
previewPanel.style.backgroundColor = '#000';
|
|
previewPanel.style.backgroundImage = 'none';
|
|
renderSceneList();
|
|
}
|
|
|
|
function getIconForSceneType(type) {
|
|
switch (type) {
|
|
case 'color': return '<i class="bi bi-palette-fill"></i>';
|
|
case 'image': return '<i class="bi bi-image-fill"></i>';
|
|
case 'video': return '<i class="bi bi-film"></i>';
|
|
default: return '<i class="bi bi-question-circle-fill"></i>';
|
|
}
|
|
}
|
|
|
|
// --- EVENT LISTENERS ---
|
|
|
|
// Scene list interactions (select, remove)
|
|
sceneListEl.addEventListener('click', (e) => {
|
|
const target = e.target;
|
|
const sceneItem = target.closest('.list-group-item');
|
|
if (!sceneItem) return;
|
|
|
|
const sceneId = parseInt(sceneItem.dataset.sceneId);
|
|
|
|
if (target.classList.contains('remove-scene-btn')) {
|
|
removeScene(sceneId);
|
|
} else {
|
|
updatePreview(sceneId);
|
|
}
|
|
});
|
|
|
|
// Transition button
|
|
cutButton.addEventListener('click', () => {
|
|
if (activePreviewSceneId === null) return;
|
|
|
|
const previewScene = getScene(activePreviewSceneId);
|
|
activeProgramSceneId = previewScene.id;
|
|
|
|
programContent.textContent = previewScene.name;
|
|
programPanel.style.backgroundColor = previewPanel.style.backgroundColor;
|
|
programPanel.style.backgroundImage = previewPanel.style.backgroundImage;
|
|
|
|
clearPreview();
|
|
});
|
|
|
|
// Modal interactions
|
|
function showModal() { modal.style.display = 'flex'; sceneNameInput.focus(); }
|
|
function hideModal() { modal.style.display = 'none'; }
|
|
|
|
addSceneBtn.addEventListener('click', showModal);
|
|
modalCloseBtn.addEventListener('click', hideModal);
|
|
modalCancelBtn.addEventListener('click', hideModal);
|
|
|
|
sceneTypeSelect.addEventListener('change', (e) => {
|
|
const type = e.target.value;
|
|
colorSettings.style.display = type === 'color' ? 'block' : 'none';
|
|
imageSettings.style.display = type === 'image' ? 'block' : 'none';
|
|
});
|
|
|
|
modalSaveBtn.addEventListener('click', () => {
|
|
const name = sceneNameInput.value.trim();
|
|
if (!name) {
|
|
alert('Please enter a scene name.');
|
|
return;
|
|
}
|
|
const type = sceneTypeSelect.value;
|
|
let value;
|
|
|
|
if (type === 'color') {
|
|
value = sceneColorInput.value;
|
|
} else if (type === 'image') {
|
|
value = sceneImageUrlInput.value.trim();
|
|
if (!value) {
|
|
alert('Please enter an image URL.');
|
|
return;
|
|
}
|
|
}
|
|
|
|
const newScene = addScene(name, type, value);
|
|
updatePreview(newScene.id);
|
|
|
|
// Reset form and hide modal
|
|
sceneNameInput.value = '';
|
|
sceneColorInput.value = '#1e90ff';
|
|
sceneImageUrlInput.value = '';
|
|
sceneTypeSelect.value = 'color';
|
|
colorSettings.style.display = 'block';
|
|
imageSettings.style.display = 'none';
|
|
hideModal();
|
|
});
|
|
|
|
// --- INITIALIZATION ---
|
|
function initialize() {
|
|
// Add some default scenes
|
|
addScene('Main Camera', 'color', '#003366');
|
|
addScene('Starting Soon Screen', 'image', 'https://images.pexels.com/photos/1762851/pexels-photo-1762851.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1');
|
|
addScene('Screen Share', 'color', '#006633');
|
|
|
|
// Set initial program scene for display
|
|
const firstScene = scenes[0];
|
|
if (firstScene) {
|
|
activeProgramSceneId = firstScene.id;
|
|
programContent.textContent = firstScene.name;
|
|
programPanel.style.backgroundColor = firstScene.value;
|
|
programPanel.style.backgroundImage = 'none';
|
|
}
|
|
|
|
// Select the second scene for preview initially
|
|
if (scenes.length > 1) {
|
|
updatePreview(scenes[1].id);
|
|
}
|
|
}
|
|
|
|
initialize();
|
|
}); |