314 lines
13 KiB
HTML
314 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Streamingle Plugin Main</title>
|
|
</head>
|
|
<body>
|
|
<div style="color: #666; text-align: center; padding: 20px;">
|
|
플러그인 메인 - 버튼 클릭 처리<br>
|
|
Property Inspector에서 설정 관리
|
|
</div>
|
|
|
|
<script>
|
|
console.log('📄 플러그인 메인 로드됨');
|
|
|
|
// Global variables
|
|
let websocket = null;
|
|
let buttonContexts = new Map(); // 각 버튼의 컨텍스트별 설정 저장
|
|
let unitySocket = null;
|
|
let isUnityConnected = false;
|
|
let cameraList = []; // 카메라 목록 저장
|
|
|
|
// StreamDeck SDK 연결
|
|
function connectElgatoStreamDeckSocket(inPort, inUUID, inEvent, inInfo, inActionInfo) {
|
|
console.log('🔌 StreamDeck 연결 (메인)');
|
|
|
|
// Parse action info to get settings
|
|
try {
|
|
const actionInfo = JSON.parse(inActionInfo);
|
|
const context = actionInfo.context;
|
|
const settings = actionInfo.payload.settings || {};
|
|
|
|
// 각 컨텍스트별로 설정 저장
|
|
buttonContexts.set(context, settings);
|
|
console.log('⚙️ 초기 컨텍스트별 설정 저장');
|
|
console.log('📍 컨텍스트:', context);
|
|
console.log('📋 설정:', settings);
|
|
console.log('📹 카메라 인덱스:', settings.cameraIndex, '(타입:', typeof settings.cameraIndex, ')');
|
|
|
|
// 즉시 제목 업데이트 시도 (카메라 데이터가 있으면)
|
|
if (cameraList.length > 0) {
|
|
updateButtonTitle(context);
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ ActionInfo 파싱 오류:', error);
|
|
}
|
|
|
|
// 첫 번째 연결인 경우에만 WebSocket 초기화
|
|
if (!websocket) {
|
|
websocket = new WebSocket('ws://localhost:' + inPort);
|
|
|
|
websocket.onopen = function() {
|
|
console.log('✅ StreamDeck 연결됨 (메인)');
|
|
websocket.send(JSON.stringify({
|
|
event: inEvent,
|
|
uuid: inUUID
|
|
}));
|
|
|
|
// Unity 연결 시도
|
|
setTimeout(() => {
|
|
connectToUnity();
|
|
}, 1000);
|
|
};
|
|
|
|
websocket.onmessage = function(evt) {
|
|
try {
|
|
const jsonObj = JSON.parse(evt.data);
|
|
console.log('📨 메인에서 메시지 수신:', jsonObj);
|
|
|
|
switch(jsonObj.event) {
|
|
case 'didReceiveSettings':
|
|
if (jsonObj.payload && jsonObj.context) {
|
|
const newSettings = jsonObj.payload.settings || {};
|
|
buttonContexts.set(jsonObj.context, newSettings);
|
|
console.log('⚙️ 설정 업데이트됨');
|
|
console.log('📍 컨텍스트:', jsonObj.context);
|
|
console.log('📋 새 설정:', newSettings);
|
|
console.log('📹 카메라 인덱스:', newSettings.cameraIndex, '(타입:', typeof newSettings.cameraIndex, ')');
|
|
|
|
// 버튼 제목 즉시 업데이트
|
|
updateButtonTitle(jsonObj.context);
|
|
|
|
// 조금 후에 한 번 더 시도 (StreamDock 응답 지연 대응)
|
|
setTimeout(() => {
|
|
updateButtonTitle(jsonObj.context);
|
|
console.log('🔄 플러그인 메인에서 제목 재시도 업데이트');
|
|
}, 150);
|
|
}
|
|
break;
|
|
|
|
case 'willAppear':
|
|
console.log('👀 버튼 나타남:', jsonObj.context);
|
|
// 초기 설정이 있으면 적용
|
|
if (jsonObj.payload && jsonObj.payload.settings) {
|
|
buttonContexts.set(jsonObj.context, jsonObj.payload.settings);
|
|
updateButtonTitle(jsonObj.context);
|
|
}
|
|
break;
|
|
|
|
case 'keyDown':
|
|
console.log('🔘 버튼 눌림');
|
|
break;
|
|
|
|
case 'keyUp':
|
|
console.log('🔘 버튼 클릭됨! 카메라 전환 처리');
|
|
handleButtonClick(jsonObj.context);
|
|
break;
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ 메시지 파싱 오류:', error);
|
|
}
|
|
};
|
|
|
|
websocket.onclose = function() {
|
|
console.log('❌ StreamDock 연결 끊어짐 (메인)');
|
|
websocket = null;
|
|
};
|
|
}
|
|
}
|
|
|
|
// Unity 연결
|
|
function connectToUnity() {
|
|
console.log('🔌 Unity 연결 시도 (메인)...');
|
|
|
|
if (unitySocket) {
|
|
unitySocket.close();
|
|
}
|
|
|
|
try {
|
|
unitySocket = new WebSocket('ws://localhost:10701');
|
|
|
|
unitySocket.onopen = function() {
|
|
isUnityConnected = true;
|
|
console.log('✅ Unity 연결 성공 (메인)!');
|
|
|
|
// 카메라 목록 요청
|
|
setTimeout(() => {
|
|
const message = JSON.stringify({ type: 'get_camera_list' });
|
|
unitySocket.send(message);
|
|
console.log('📋 카메라 목록 요청 (메인):', message);
|
|
}, 100);
|
|
};
|
|
|
|
unitySocket.onmessage = function(event) {
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
console.log('📨 Unity 메시지 수신 (메인):', data.type);
|
|
handleUnityMessage(data);
|
|
} catch (error) {
|
|
console.error('❌ Unity 메시지 파싱 오류:', error);
|
|
}
|
|
};
|
|
|
|
unitySocket.onclose = function() {
|
|
isUnityConnected = false;
|
|
console.log('❌ Unity 연결 끊어짐 (메인)');
|
|
};
|
|
|
|
unitySocket.onerror = function(error) {
|
|
console.error('❌ Unity 연결 오류 (메인):', error);
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('❌ Unity 연결 설정 오류:', error);
|
|
}
|
|
}
|
|
|
|
// 버튼 클릭 처리
|
|
function handleButtonClick(context) {
|
|
console.log('🎯 버튼 클릭 처리 시작');
|
|
console.log('📍 컨텍스트:', context);
|
|
console.log('📋 전체 버튼 컨텍스트:', Array.from(buttonContexts.keys()));
|
|
console.log('⚙️ 현재 설정:', getCurrentSettings(context));
|
|
console.log('🔌 Unity 연결 상태:', isUnityConnected);
|
|
|
|
if (!isUnityConnected || !unitySocket) {
|
|
console.error('❌ Unity 연결되지 않음');
|
|
return;
|
|
}
|
|
|
|
// 설정에서 카메라 인덱스 가져오기
|
|
const settings = getCurrentSettings(context);
|
|
let cameraIndex = settings.cameraIndex;
|
|
|
|
// 카메라 인덱스가 설정되지 않았으면 0 사용
|
|
if (typeof cameraIndex !== 'number') {
|
|
cameraIndex = 0;
|
|
console.log('⚠️ 카메라 인덱스가 설정되지 않음, 기본값 0 사용');
|
|
}
|
|
|
|
console.log('📹 전환할 카메라 인덱스:', cameraIndex, '(타입:', typeof cameraIndex, ')');
|
|
|
|
// Unity 예상 구조에 맞게 data 객체로 래핑
|
|
const message = JSON.stringify({
|
|
type: 'switch_camera',
|
|
data: {
|
|
camera_index: cameraIndex
|
|
}
|
|
});
|
|
|
|
unitySocket.send(message);
|
|
console.log('📤 Unity에 카메라 전환 요청 전송:', message);
|
|
}
|
|
|
|
// Unity 메시지 처리
|
|
function handleUnityMessage(data) {
|
|
switch (data.type) {
|
|
case 'connection_established':
|
|
console.log('🎉 Unity 연결 확인됨 (메인)');
|
|
|
|
// 연결 시 카메라 데이터 저장
|
|
if (data.data && data.data.camera_data && data.data.camera_data.presets) {
|
|
cameraList = data.data.camera_data.presets;
|
|
console.log('📹 카메라 목록 저장됨 (메인):', cameraList.length, '개');
|
|
updateAllButtonTitles();
|
|
}
|
|
break;
|
|
|
|
case 'camera_list_response':
|
|
console.log('📹 카메라 목록 수신 (메인)');
|
|
|
|
if (data.data && data.data.camera_data && data.data.camera_data.presets) {
|
|
cameraList = data.data.camera_data.presets;
|
|
console.log('📹 카메라 목록 업데이트됨 (메인):', cameraList.length, '개');
|
|
updateAllButtonTitles();
|
|
}
|
|
break;
|
|
|
|
case 'camera_changed':
|
|
console.log('🎯 카메라 변경 알림 (메인)');
|
|
// 카메라 변경 시에는 제목 업데이트 안함 (각 버튼은 독립적)
|
|
break;
|
|
|
|
default:
|
|
console.log('❓ 알 수 없는 Unity 메시지 타입 (메인):', data.type);
|
|
}
|
|
}
|
|
|
|
// 모든 버튼의 제목 업데이트
|
|
function updateAllButtonTitles() {
|
|
for (const context of buttonContexts.keys()) {
|
|
updateButtonTitle(context);
|
|
}
|
|
}
|
|
|
|
// StreamDock 버튼 제목 업데이트
|
|
function updateButtonTitle(context) {
|
|
if (!websocket || !context) {
|
|
console.log('🚫 WebSocket 또는 context 없음 - 제목 업데이트 건너뜀');
|
|
return;
|
|
}
|
|
|
|
const cameraIndex = getCurrentSettings(context).cameraIndex || 0;
|
|
let title = `카메라 ${cameraIndex + 1}`;
|
|
|
|
// 카메라 목록에서 이름 찾기
|
|
if (cameraList && cameraList.length > cameraIndex) {
|
|
const camera = cameraList[cameraIndex];
|
|
if (camera && camera.name) {
|
|
// 카메라 이름에서 불필요한 부분 제거하고 짧게 만들기
|
|
let shortName = camera.name
|
|
.replace('Cam0', '')
|
|
.replace('Cam', '')
|
|
.replace('_', ' ')
|
|
.substring(0, 10); // 최대 10글자
|
|
|
|
title = shortName || `카메라 ${cameraIndex + 1}`;
|
|
}
|
|
}
|
|
|
|
// StreamDock에 제목 업데이트 요청
|
|
const message = {
|
|
event: 'setTitle',
|
|
context: context,
|
|
payload: {
|
|
title: title,
|
|
target: 0, // hardware and software
|
|
titleParameters: {
|
|
fontSize: 24, // 기본 12에서 24로 증가 (2배)
|
|
showTitle: true,
|
|
titleAlignment: "middle"
|
|
}
|
|
}
|
|
};
|
|
|
|
websocket.send(JSON.stringify(message));
|
|
console.log('🏷️ 버튼 제목 업데이트:', title);
|
|
}
|
|
|
|
// 설정 변경 시 제목 업데이트
|
|
function updateSettingsAndTitle(context, newSettings) {
|
|
updateCurrentSettings(context, newSettings);
|
|
updateButtonTitle(context);
|
|
}
|
|
|
|
// 설정 관리 헬퍼 함수들
|
|
function getCurrentSettings(context) {
|
|
if (!context) return {};
|
|
return buttonContexts.get(context) || {};
|
|
}
|
|
|
|
function setCurrentSettings(context, newSettings) {
|
|
if (!context) return;
|
|
buttonContexts.set(context, newSettings);
|
|
}
|
|
|
|
function updateCurrentSettings(context, partialSettings) {
|
|
if (!context) return;
|
|
const currentSettings = getCurrentSettings(context);
|
|
setCurrentSettings(context, { ...currentSettings, ...partialSettings });
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |