// Event Controller Property Inspector let websocket = null; let uuid = null; let settings = {}; let eventList = []; let isUnityConnected = false; // DOM 요소들 let eventSelect = null; let statusDot = null; let connectionStatus = null; let currentEvent = null; let refreshButton = null; let executeButton = null; let autoExecute = null; let logArea = null; function logToScreen(msg, color = "#fff") { let logDiv = document.getElementById('logArea'); if (!logDiv) return; const line = document.createElement('div'); line.style.color = color; line.textContent = `[${new Date().toLocaleTimeString()}] ${msg}`; logDiv.appendChild(line); logDiv.scrollTop = logDiv.scrollHeight; } console.log = function(...args) { logToScreen(args.map(a => (typeof a === 'object' ? JSON.stringify(a) : a)).join(' '), '#0f0'); }; console.error = function(...args) { logToScreen(args.map(a => (typeof a === 'object' ? JSON.stringify(a) : a)).join(' '), '#f55'); }; // DOM 초기화 window.addEventListener('DOMContentLoaded', function() { eventSelect = document.getElementById('event-select'); statusDot = document.getElementById('statusDot'); connectionStatus = document.getElementById('connection-status'); currentEvent = document.getElementById('current-event'); refreshButton = document.getElementById('refresh-button'); executeButton = document.getElementById('execute-button'); autoExecute = document.getElementById('autoExecute'); logArea = document.getElementById('logArea'); if (refreshButton) refreshButton.addEventListener('click', onRefreshClicked); if (executeButton) executeButton.addEventListener('click', onExecuteClicked); if (eventSelect) eventSelect.addEventListener('change', onEventSelectionChanged); if (autoExecute) autoExecute.addEventListener('change', onAutoExecuteChanged); console.log('✅ Event Property Inspector 준비 완료'); }); // StreamDeck 연결 window.connectElgatoStreamDeckSocket = function(inPort, inUUID, inEvent, inInfo, inActionInfo) { uuid = inUUID; console.log('🔌 StreamDeck 연결 시작:', inPort, inUUID); try { if (inActionInfo) { const actionInfo = JSON.parse(inActionInfo); settings = actionInfo.payload?.settings || {}; console.log('⚙️ 초기 설정:', settings); } } catch (e) { console.error('ActionInfo 파싱 오류:', e); } if (!websocket) { websocket = new WebSocket('ws://localhost:' + inPort); websocket.onopen = function() { console.log('✅ StreamDeck 연결됨'); websocket.send(JSON.stringify({ event: inEvent, uuid: inUUID })); // Unity 상태 요청 setTimeout(() => { sendToPlugin('get_unity_status'); }, 500); }; websocket.onmessage = function(evt) { try { const jsonObj = JSON.parse(evt.data); handleMessage(jsonObj); } catch (e) { console.error('메시지 파싱 오류:', e); } }; websocket.onclose = function() { console.log('❌ StreamDeck 연결 끊어짐'); websocket = null; }; websocket.onerror = function(e) { console.error('WebSocket 오류:', e); }; } }; function sendToPlugin(command, data = {}) { if (!websocket) return; const message = { action: 'com.mirabox.streamingle.event', event: 'sendToPlugin', context: uuid, payload: { command, ...data } }; websocket.send(JSON.stringify(message)); console.log('📤 Plugin으로 메시지 전송:', command, data); } function handleMessage(jsonObj) { console.log('📨 메시지 수신:', jsonObj.event); if (jsonObj.event === 'sendToPropertyInspector' && jsonObj.payload && jsonObj.payload.event) { const innerEvent = jsonObj.payload.event; console.log('📨 Property Inspector 이벤트:', innerEvent); switch (innerEvent) { case 'unity_connected': updateUnityConnection(true); break; case 'unity_disconnected': updateUnityConnection(false); break; case 'event_list': updateEventList(jsonObj.payload.events, jsonObj.payload.currentIndex); break; case 'event_changed': updateEventState(jsonObj.payload.currentIndex); break; case 'camera_list': console.log('📹 카메라 목록 수신 (이벤트 Property Inspector에서는 무시)'); break; case 'item_list': console.log('🎯 아이템 목록 수신 (이벤트 Property Inspector에서는 무시)'); break; } } if (jsonObj.event === 'didReceiveSettings' && jsonObj.payload && jsonObj.context) { settings = jsonObj.payload.settings || {}; console.log('⚙️ 설정 수신:', settings); if (settings.eventIndex !== undefined && eventSelect) { eventSelect.value = settings.eventIndex; console.log('🎯 이벤트 인덱스 설정됨:', settings.eventIndex); } if (settings.autoExecute !== undefined && autoExecute) { autoExecute.checked = settings.autoExecute; } updateCurrentEvent(); } } function updateUnityConnection(connected) { isUnityConnected = connected; if (statusDot) { statusDot.className = 'dot ' + (connected ? 'green' : 'red'); } if (connectionStatus) { connectionStatus.textContent = connected ? 'Unity 연결됨' : 'Unity 연결 안됨'; connectionStatus.className = connected ? 'connected' : 'disconnected'; } if (eventSelect) { eventSelect.disabled = !connected; } if (refreshButton) { refreshButton.disabled = !connected; } if (executeButton) { executeButton.disabled = !connected; } console.log('🔗 Unity 연결 상태 변경:', connected); } function updateEventList(events, currentIndex) { eventList = events || []; console.log('🎯 이벤트 목록 업데이트:', eventList.length, '개'); if (!eventSelect) return; eventSelect.innerHTML = ''; if (eventList.length === 0) { const option = document.createElement('option'); option.value = ''; option.textContent = '이벤트 그룹이 없습니다'; eventSelect.appendChild(option); } else { eventList.forEach((event, index) => { const option = document.createElement('option'); option.value = index; option.textContent = event.name || event.groupName || `이벤트 그룹 ${index + 1}`; eventSelect.appendChild(option); }); } // 현재 선택된 이벤트 설정 if (settings.eventIndex !== undefined) { eventSelect.value = settings.eventIndex; } else if (currentIndex !== undefined) { eventSelect.value = currentIndex; } updateCurrentEvent(); } function updateCurrentEvent() { if (!currentEvent) return; const selectedIndex = eventSelect ? parseInt(eventSelect.value) : -1; if (selectedIndex >= 0 && selectedIndex < eventList.length) { const selectedEvent = eventList[selectedIndex]; currentEvent.textContent = `현재 이벤트 그룹: ${selectedEvent.name || selectedEvent.groupName || `이벤트 그룹 ${selectedIndex + 1}`}`; } else { currentEvent.textContent = '현재 이벤트 그룹: -'; } } function updateEventState(currentIndex) { console.log('🎯 이벤트 상태 업데이트:', currentIndex); if (eventSelect && currentIndex !== undefined) { eventSelect.value = currentIndex; updateCurrentEvent(); } } function onEventSelectionChanged() { if (!eventSelect) return; const selectedIndex = parseInt(eventSelect.value); console.log('🎯 이벤트 선택 변경:', selectedIndex); if (selectedIndex >= 0) { settings.eventIndex = selectedIndex; // StreamDeck에 설정 저장 (카메라 컨트롤러와 동일한 방식) if (websocket && uuid) { websocket.send(JSON.stringify({ action: 'com.mirabox.streamingle.event', event: 'setSettings', context: uuid, payload: { eventIndex: selectedIndex, actionType: 'event' // actionType 명시적으로 설정 } })); console.log('💾 설정 저장됨:', { eventIndex: selectedIndex, actionType: 'event' }); } // Unity에 이벤트 설정 요청 (자동 실행 여부와 관계없이) if (isUnityConnected) { console.log('📤 Unity에 이벤트 설정 전송:', selectedIndex); sendToPlugin('set_event', { event_index: selectedIndex }); } else { console.log('⚠️ Unity가 연결되지 않아 이벤트 설정을 전송할 수 없습니다'); } updateCurrentEvent(); } } function onAutoExecuteChanged() { if (!autoExecute) return; settings.autoExecute = autoExecute.checked; console.log('⚙️ 자동 실행 설정 변경:', settings.autoExecute); // StreamDeck에 설정 저장 (카메라 컨트롤러와 동일한 방식) if (websocket && uuid) { websocket.send(JSON.stringify({ action: 'com.mirabox.streamingle.event', event: 'setSettings', context: uuid, payload: { autoExecute: settings.autoExecute } })); console.log('💾 자동 실행 설정 저장됨:', { autoExecute: settings.autoExecute }); } } function onRefreshClicked() { console.log('🔄 이벤트 목록 새로고침 요청'); sendToPlugin('get_event_list'); } function onExecuteClicked() { if (!eventSelect) return; const selectedIndex = parseInt(eventSelect.value); if (selectedIndex >= 0) { console.log('▶️ 이벤트 실행 요청:', selectedIndex); sendToPlugin('execute_event', { event_index: selectedIndex }); } else { console.log('⚠️ 이벤트가 선택되지 않았습니다'); } }