308 lines
10 KiB
JavaScript
308 lines
10 KiB
JavaScript
// 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('⚠️ 이벤트가 선택되지 않았습니다');
|
||
}
|
||
}
|