294 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Item Controller Property Inspector
let websocket = null;
let uuid = null;
let settings = {};
let itemList = [];
let isUnityConnected = false;
// DOM 요소들
let itemSelect = null;
let statusDot = null;
let connectionStatus = null;
let currentItem = null;
let refreshButton = null;
let autoSwitch = 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() {
itemSelect = document.getElementById('item-select');
statusDot = document.getElementById('statusDot');
connectionStatus = document.getElementById('connection-status');
currentItem = document.getElementById('current-item');
refreshButton = document.getElementById('refresh-button');
autoSwitch = document.getElementById('autoSwitch');
logArea = document.getElementById('logArea');
if (refreshButton) refreshButton.addEventListener('click', onRefreshClicked);
if (itemSelect) itemSelect.addEventListener('change', onItemSelectionChanged);
if (autoSwitch) autoSwitch.addEventListener('change', onAutoSwitchChanged);
console.log(' Item 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.item',
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 'item_list':
updateItemList(jsonObj.payload.items, jsonObj.payload.currentIndex);
break;
case 'item_changed':
updateItemState(jsonObj.payload.currentIndex);
break;
case 'camera_list':
console.log('📹 카메라 목록 수신 (아이템 Property Inspector에서는 무시)');
console.log('⚠️ 아이템 컨트롤러에서 카메라 데이터를 받았습니다. 이는 잘못된 데이터 전송입니다.');
break;
}
}
if (jsonObj.event === 'didReceiveSettings' && jsonObj.payload && jsonObj.context) {
settings = jsonObj.payload.settings || {};
console.log('⚙️ 설정 수신:', settings);
if (settings.itemIndex !== undefined && itemSelect) {
itemSelect.value = settings.itemIndex;
}
if (settings.autoSwitch !== undefined && autoSwitch) {
autoSwitch.checked = settings.autoSwitch;
}
}
}
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 (itemSelect) {
itemSelect.disabled = !connected;
}
if (refreshButton) {
refreshButton.disabled = !connected;
}
console.log('🔗 Unity 연결 상태 변경:', connected);
}
function updateItemList(items, currentIndex) {
itemList = items || [];
console.log('🎯 아이템 목록 업데이트:', itemList.length, '개');
if (!itemSelect) return;
itemSelect.innerHTML = '';
if (itemList.length === 0) {
const option = document.createElement('option');
option.value = '';
option.textContent = '아이템 그룹이 없습니다';
itemSelect.appendChild(option);
} else {
itemList.forEach((item, index) => {
const option = document.createElement('option');
option.value = index;
option.textContent = item.name || item.groupName || `아이템 그룹 ${index + 1}`;
itemSelect.appendChild(option);
});
}
// 현재 선택된 아이템 설정
if (settings.itemIndex !== undefined) {
itemSelect.value = settings.itemIndex;
} else if (currentIndex !== undefined) {
itemSelect.value = currentIndex;
}
updateCurrentItem();
}
function updateCurrentItem() {
if (!currentItem || !itemSelect) return;
const selectedIndex = parseInt(itemSelect.value);
if (isNaN(selectedIndex) || selectedIndex < 0 || selectedIndex >= itemList.length) {
currentItem.textContent = '현재 아이템 그룹: -';
return;
}
const selectedItem = itemList[selectedIndex];
if (selectedItem) {
const status = selectedItem.isActive ? '활성' : '비활성';
currentItem.textContent = `현재 아이템 그룹: ${selectedItem.name || selectedItem.groupName || `그룹 ${selectedIndex + 1}`} (${status})`;
}
}
function updateItemState(currentIndex) {
if (currentIndex !== undefined && itemSelect) {
itemSelect.value = currentIndex;
}
updateCurrentItem();
}
function onItemSelectionChanged() {
const selectedIndex = parseInt(itemSelect.value);
if (isNaN(selectedIndex)) return;
// 항상 actionType: 'item'을 포함
settings.itemIndex = selectedIndex;
settings.actionType = 'item';
updateCurrentItem();
// 설정 저장 (actionType 포함)
if (websocket && uuid) {
websocket.send(JSON.stringify({
action: 'com.mirabox.streamingle.item',
event: 'setSettings',
context: uuid,
payload: settings
}));
}
// 버튼 제목 업데이트 요청 (actionType 포함)
sendToPlugin('update_title', { itemIndex: selectedIndex, actionType: 'item' });
// 즉시 버튼 제목 업데이트 요청
if (websocket && uuid) {
websocket.send(JSON.stringify({
action: 'com.mirabox.streamingle.item',
event: 'setTitle',
context: uuid,
payload: {
title: `아이템 ${selectedIndex + 1}`,
target: 0
}
}));
}
console.log('🎯 아이템 그룹 선택 변경:', selectedIndex, settings);
}
function onAutoSwitchChanged() {
if (!autoSwitch) return;
settings.autoSwitch = autoSwitch.checked;
// 설정 저장
if (websocket && uuid) {
websocket.send(JSON.stringify({
action: 'com.mirabox.streamingle.item',
event: 'setSettings',
context: uuid,
payload: settings
}));
}
console.log('⚙️ 자동 전환 설정 변경:', autoSwitch.checked);
}
function onRefreshClicked() {
if (!isUnityConnected) {
console.log('⚠️ Unity가 연결되지 않음');
return;
}
console.log('🔄 아이템 그룹 목록 새로고침 요청');
sendToPlugin('refresh_item_list');
}