/** * Spatial Automation Builder - Trigger volume editor and automation UI * Integrates with VolumeEditor for 3D volume creation and editing */ (function() { 'use strict'; // ── Module state ───────────────────────────────────────────────────────────── let _triggers = []; let _currentVolume = null; // Currently drawn volume shape let _editingId = null; let _volumeEditorReady = false; // Trigger condition labels const CONDITION_LABELS = { 'enter': 'When someone enters the volume', 'leave': 'When someone leaves the volume', 'dwell': 'When someone stays in the volume for a while', 'vacant': 'When the volume becomes empty', 'count': 'When occupant count crosses threshold' }; // ── Initialization ───────────────────────────────────────────────────────────── function init() { console.log('[AutomationBuilder] Initializing'); createPanelHTML(); setupEventListeners(); loadTriggers(); // Subscribe to state changes for triggers if (window.SpaxelState) { SpaxelState.subscribe('triggers', onTriggersChanged); } // Initialize volume editor callback if (window.VolumeEditor) { VolumeEditor.onVolumeCreated(onVolumeCreated); VolumeEditor.onVolumeChanged(onVolumeChanged); VolumeEditor.onVolumeDeleted(onVolumeDeleted); _volumeEditorReady = true; } else { console.warn('[AutomationBuilder] VolumeEditor not loaded yet'); } } function createPanelHTML() { const container = document.getElementById('automations-panel'); if (!container) { console.warn('[AutomationBuilder] #automations-panel not found'); return; } container.innerHTML = `
Loading triggers...
No trigger firings yet.
No actions added
'; return; } list.innerHTML = actions.map((action, i) => `No triggers configured yet.
Click "Box" or "Cylinder" to draw a volume, then click "New Trigger".
No trigger firings yet.
'; return; } container.innerHTML = log.map(entry => `