437 lines
12 KiB (Stored with Git LFS)
Markdown
437 lines
12 KiB (Stored with Git LFS)
Markdown
# SystemController 통합 가이드
|
|
|
|
## 개요
|
|
|
|
StreamDeck 단일 기능 버튼들을 통합 관리하는 시스템입니다. 각 기능은 하나의 버튼으로 매핑되어 간단하고 직관적으로 사용할 수 있습니다.
|
|
|
|
---
|
|
|
|
## 시스템 구조
|
|
|
|
### 1. Unity 측 (SystemController.cs)
|
|
**경로**: `Assets/Scripts/Streamdeck/SystemController.cs`
|
|
|
|
단일 기능 명령어들을 처리하는 통합 컨트롤러입니다.
|
|
|
|
**주요 메서드:**
|
|
- `ExecuteCommand(string command, Dictionary<string, object> parameters)` - 명령어 실행 진입점
|
|
|
|
**현재 구현된 기능:**
|
|
|
|
#### OptiTrack 마커 토글
|
|
```csharp
|
|
// 명령어: toggle_optitrack_markers, show_optitrack_markers, hide_optitrack_markers
|
|
public void ToggleOptitrackMarkers()
|
|
public void ShowOptitrackMarkers()
|
|
public void HideOptitrackMarkers()
|
|
```
|
|
|
|
### 2. Unity 서버 (StreamDeckServerManager.cs)
|
|
**경로**: `Assets/Scripts/Streamdeck/StreamDeckServerManager.cs`
|
|
|
|
WebSocket 서버에서 SystemController 명령을 라우팅합니다.
|
|
|
|
**통합 코드:**
|
|
```csharp
|
|
// Line 19
|
|
public SystemController systemController { get; private set; }
|
|
|
|
// Line 64-69
|
|
systemController = FindObjectOfType<SystemController>();
|
|
if (systemController == null)
|
|
{
|
|
Debug.LogWarning("[StreamDeckServerManager] SystemController를 찾을 수 없습니다.");
|
|
}
|
|
|
|
// Line 347-351 (메시지 처리)
|
|
case "toggle_optitrack_markers":
|
|
case "show_optitrack_markers":
|
|
case "hide_optitrack_markers":
|
|
HandleSystemCommand(message);
|
|
break;
|
|
|
|
// Line 979-1014 (핸들러)
|
|
private void HandleSystemCommand(Dictionary<string, object> message)
|
|
{
|
|
string messageType = message.ContainsKey("type") ? message["type"].ToString() : null;
|
|
|
|
if (systemController == null)
|
|
{
|
|
Debug.LogError("[StreamDeckServerManager] SystemController가 null입니다!");
|
|
return;
|
|
}
|
|
|
|
// 파라미터 추출
|
|
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
|
if (message.ContainsKey("data"))
|
|
{
|
|
var dataObject = message["data"];
|
|
if (dataObject is Newtonsoft.Json.Linq.JObject jObject)
|
|
{
|
|
foreach (var prop in jObject.Properties())
|
|
{
|
|
parameters[prop.Name] = prop.Value.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
// SystemController의 ExecuteCommand 호출
|
|
systemController.ExecuteCommand(messageType, parameters);
|
|
}
|
|
```
|
|
|
|
### 3. StreamDeck 플러그인 (manifest.json)
|
|
**경로**: `Streamdeck/com.mirabox.streamingle.sdPlugin/manifest.json`
|
|
|
|
새로운 액션 정의 (Line 115-137):
|
|
```json
|
|
{
|
|
"Icon": "images/optitrack_marker_icon.png",
|
|
"Name": "OptiTrack Marker Toggle",
|
|
"DisableAutomaticStates": false,
|
|
"States": [
|
|
{
|
|
"Image": "images/optitrack_marker_icon.png",
|
|
"TitleAlignment": "bottom",
|
|
"FontSize": "12"
|
|
},
|
|
{
|
|
"Image": "images/optitrack_marker_icon_off.png",
|
|
"TitleAlignment": "bottom",
|
|
"FontSize": "12"
|
|
}
|
|
],
|
|
"Settings": {},
|
|
"Controllers": ["Keypad"],
|
|
"UserTitleEnabled": true,
|
|
"SupportedInMultiActions": true,
|
|
"Tooltip": "Toggle OptiTrack markers visibility",
|
|
"UUID": "com.mirabox.streamingle.optitrack_marker_toggle"
|
|
}
|
|
```
|
|
|
|
### 4. StreamDeck 플러그인 로직 (plugin/index.js)
|
|
**경로**: `Streamdeck/com.mirabox.streamingle.sdPlugin/plugin/index.js`
|
|
|
|
**액션 타입 등록** (Line 94-100):
|
|
```javascript
|
|
else if (jsonObj.action === 'com.mirabox.streamingle.optitrack_marker_toggle') {
|
|
settings.actionType = 'optitrack_marker_toggle';
|
|
console.log('🎯 OptiTrack 마커 토글 등록:', jsonObj.context);
|
|
|
|
// 기본 제목 설정
|
|
setButtonTitle(jsonObj.context, '마커\nON');
|
|
}
|
|
```
|
|
|
|
**버튼 클릭 처리** (Line 321-323):
|
|
```javascript
|
|
case 'optitrack_marker_toggle':
|
|
handleOptitrackMarkerToggle(context);
|
|
break;
|
|
```
|
|
|
|
**마커 토글 핸들러** (Line 489-513):
|
|
```javascript
|
|
function handleOptitrackMarkerToggle(context) {
|
|
console.log('🎯 OptiTrack 마커 토글 실행');
|
|
|
|
// Unity에 마커 토글 요청
|
|
const message = JSON.stringify({
|
|
type: 'toggle_optitrack_markers'
|
|
});
|
|
|
|
console.log('📤 Unity에 OptiTrack 마커 토글 요청 전송:', message);
|
|
console.log('🔍 Unity 연결 상태:', isUnityConnected);
|
|
console.log('🔍 Unity 소켓 상태:', !!unitySocket);
|
|
|
|
if (unitySocket && unitySocket.readyState === WebSocket.OPEN) {
|
|
unitySocket.send(message);
|
|
console.log('✅ 메시지 전송 완료');
|
|
|
|
// 버튼 상태 토글 (0 <-> 1)
|
|
toggleButtonState(context);
|
|
} else {
|
|
console.error('❌ Unity 소켓이 연결되지 않음');
|
|
console.log('🔄 Unity 재연결 시도...');
|
|
connectToUnity();
|
|
}
|
|
}
|
|
```
|
|
|
|
**버튼 상태 토글** (Line 515-543):
|
|
```javascript
|
|
function toggleButtonState(context) {
|
|
const settings = getCurrentSettings(context);
|
|
const currentState = settings.currentState || 0;
|
|
const newState = currentState === 0 ? 1 : 0;
|
|
|
|
// 설정 업데이트
|
|
settings.currentState = newState;
|
|
setCurrentSettings(context, settings);
|
|
|
|
// 버튼 상태 변경
|
|
const stateMessage = {
|
|
event: 'setState',
|
|
context: context,
|
|
payload: {
|
|
state: newState,
|
|
target: 0 // hardware and software
|
|
}
|
|
};
|
|
|
|
if (websocket) {
|
|
websocket.send(JSON.stringify(stateMessage));
|
|
console.log('🎨 버튼 상태 업데이트:', newState === 0 ? 'ON' : 'OFF');
|
|
}
|
|
|
|
// 제목도 함께 변경
|
|
const title = newState === 0 ? '마커\nON' : '마커\nOFF';
|
|
setButtonTitle(context, title);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 통신 프로토콜
|
|
|
|
### WebSocket 메시지 형식
|
|
|
|
**StreamDeck → Unity**
|
|
```json
|
|
{
|
|
"type": "toggle_optitrack_markers"
|
|
}
|
|
```
|
|
|
|
**Unity 로그 (정상 동작 시)**
|
|
```
|
|
[StreamDeckServerManager] 시스템 명령어 실행: toggle_optitrack_markers
|
|
[SystemController] 명령어 실행: toggle_optitrack_markers
|
|
[SystemController] OptiTrack 마커 표시: True/False
|
|
```
|
|
|
|
---
|
|
|
|
## 새 기능 추가 방법
|
|
|
|
### 1단계: SystemController에 기능 추가
|
|
|
|
```csharp
|
|
// Assets/Scripts/Streamdeck/SystemController.cs
|
|
|
|
#region 새로운 기능 그룹
|
|
|
|
/// <summary>
|
|
/// 새로운 기능 설명
|
|
/// </summary>
|
|
public void NewFeatureMethod()
|
|
{
|
|
// 기능 구현
|
|
Log("새 기능 실행됨");
|
|
}
|
|
|
|
#endregion
|
|
```
|
|
|
|
### 2단계: ExecuteCommand에 case 추가
|
|
|
|
```csharp
|
|
switch (command)
|
|
{
|
|
// 기존 명령어들...
|
|
|
|
case "new_feature_command":
|
|
NewFeatureMethod();
|
|
break;
|
|
}
|
|
```
|
|
|
|
### 3단계: StreamDeckServerManager에 메시지 타입 추가
|
|
|
|
```csharp
|
|
// ProcessMessage의 switch문에 추가
|
|
case "new_feature_command":
|
|
HandleSystemCommand(message);
|
|
break;
|
|
```
|
|
|
|
### 4단계: manifest.json에 액션 추가
|
|
|
|
```json
|
|
{
|
|
"Icon": "images/new_feature_icon.png",
|
|
"Name": "New Feature",
|
|
"DisableAutomaticStates": false,
|
|
"States": [
|
|
{
|
|
"Image": "images/new_feature_icon.png",
|
|
"TitleAlignment": "bottom",
|
|
"FontSize": "12"
|
|
}
|
|
],
|
|
"Settings": {},
|
|
"Controllers": ["Keypad"],
|
|
"UserTitleEnabled": true,
|
|
"SupportedInMultiActions": true,
|
|
"Tooltip": "New feature description",
|
|
"UUID": "com.mirabox.streamingle.new_feature"
|
|
}
|
|
```
|
|
|
|
### 5단계: plugin/index.js에 처리 로직 추가
|
|
|
|
**액션 등록:**
|
|
```javascript
|
|
else if (jsonObj.action === 'com.mirabox.streamingle.new_feature') {
|
|
settings.actionType = 'new_feature';
|
|
console.log('🎯 새 기능 등록:', jsonObj.context);
|
|
}
|
|
```
|
|
|
|
**클릭 처리:**
|
|
```javascript
|
|
case 'new_feature':
|
|
handleNewFeature(context);
|
|
break;
|
|
```
|
|
|
|
**핸들러 함수:**
|
|
```javascript
|
|
function handleNewFeature(context) {
|
|
console.log('🎯 새 기능 실행');
|
|
|
|
const message = JSON.stringify({
|
|
type: 'new_feature_command'
|
|
});
|
|
|
|
if (unitySocket && unitySocket.readyState === WebSocket.OPEN) {
|
|
unitySocket.send(message);
|
|
console.log('✅ 메시지 전송 완료');
|
|
}
|
|
}
|
|
```
|
|
|
|
### 6단계: 배포
|
|
|
|
```bash
|
|
cd Streamdeck
|
|
deploy-plugin.bat
|
|
```
|
|
|
|
---
|
|
|
|
## 디버깅 방법
|
|
|
|
### Unity 측 디버깅
|
|
Unity Console에서 로그 확인:
|
|
```
|
|
[SystemController] 명령어 실행: <command>
|
|
```
|
|
|
|
### StreamDeck 플러그인 디버깅
|
|
|
|
**방법 1: 개발자 도구 (Electron 기반)**
|
|
- StreamDock 소프트웨어에서 **F12** 또는 **Ctrl+Shift+I** 시도
|
|
- Console 탭에서 JavaScript 로그 확인
|
|
|
|
**방법 2: 로그 파일**
|
|
- 경로: `%APPDATA%\Hotspot\StreamDock\logs\`
|
|
- 최신 로그 파일 확인
|
|
|
|
**방법 3: Unity 로그만으로 확인**
|
|
- 버튼 클릭 시 Unity Console에 예상되는 로그가 나오는지 확인
|
|
- 잘못된 메시지가 오면 플러그인 설정 문제
|
|
|
|
---
|
|
|
|
## 트러블슈팅
|
|
|
|
### 문제: 버튼을 눌러도 Unity에 메시지가 안 옴
|
|
**해결:**
|
|
1. Unity에서 SystemController GameObject가 씬에 있는지 확인
|
|
2. StreamDeckServerManager가 SystemController를 찾았는지 로그 확인
|
|
3. Unity WebSocket 서버가 포트 10701에서 실행 중인지 확인
|
|
|
|
### 문제: 잘못된 메시지 타입이 옴 (예: switch_camera)
|
|
**해결:**
|
|
1. StreamDeck에서 올바른 액션을 추가했는지 확인
|
|
2. 기존 버튼이 아닌 새 버튼에 "OptiTrack Marker Toggle" 액션을 추가
|
|
3. `deploy-plugin.bat`를 실행하여 최신 플러그인 배포
|
|
|
|
### 문제: 버튼에 제목이 안 나옴
|
|
**해결:**
|
|
1. `plugin/index.js`의 `willAppear` 이벤트에서 `setButtonTitle` 호출 확인
|
|
2. 제목에 `\n`으로 줄바꿈 가능 (예: `'마커\nON'`)
|
|
|
|
### 문제: 버튼 상태가 안 바뀜
|
|
**해결:**
|
|
1. `manifest.json`에서 `DisableAutomaticStates: false` 확인
|
|
2. `States` 배열에 2개 상태 정의 확인
|
|
3. `toggleButtonState` 함수에서 `setState` 메시지 전송 확인
|
|
|
|
---
|
|
|
|
## 파일 위치 정리
|
|
|
|
### Unity 파일
|
|
```
|
|
Assets/Scripts/Streamdeck/
|
|
├── SystemController.cs # 단일 기능 통합 컨트롤러
|
|
├── StreamDeckServerManager.cs # WebSocket 서버 & 라우팅
|
|
└── StreamDeckService.cs # WebSocket 서비스 (기존)
|
|
```
|
|
|
|
### StreamDeck 플러그인 파일
|
|
```
|
|
Streamdeck/com.mirabox.streamingle.sdPlugin/
|
|
├── manifest.json # 액션 정의
|
|
├── plugin/
|
|
│ └── index.js # 플러그인 로직
|
|
├── propertyInspector/ # 설정 UI (기존 액션용)
|
|
└── images/ # 아이콘 이미지
|
|
├── optitrack_marker_icon.png # 마커 ON 상태
|
|
└── optitrack_marker_icon_off.png # 마커 OFF 상태
|
|
```
|
|
|
|
### 배포 스크립트
|
|
```
|
|
Streamdeck/
|
|
├── deploy-plugin.bat # 간편 실행용 배치 파일
|
|
├── deploy-plugin.ps1 # 실제 배포 스크립트
|
|
└── DEPLOY_README.md # 배포 가이드
|
|
```
|
|
|
|
---
|
|
|
|
## 현재 구현된 기능 목록
|
|
|
|
### 1. OptiTrack 마커 토글
|
|
- **명령어**: `toggle_optitrack_markers`, `show_optitrack_markers`, `hide_optitrack_markers`
|
|
- **UUID**: `com.mirabox.streamingle.optitrack_marker_toggle`
|
|
- **설명**: OptiTrack 마커 표시를 켜거나 끔
|
|
- **버튼 상태**: 2개 (ON/OFF)
|
|
- **제목**: "마커\nON" ↔ "마커\nOFF"
|
|
|
|
---
|
|
|
|
## 참고 자료
|
|
|
|
### StreamDock 공식 문서
|
|
- 메인: https://creator.key123.vip/
|
|
- Getting Started: https://creator.key123.vip/en/guide/get-started.html
|
|
- Plugin SDK: https://creator.key123.vip/en/streamdock/plugin-sdk.html
|
|
|
|
### StreamDock SDK (GitHub)
|
|
- https://github.com/MiraboxSpace/StreamDock-Plugin-SDK
|
|
|
|
### 관련 문서
|
|
- `Implementation_Guide.md` - Streamingle 플러그인 구현 가이드
|
|
- `JSON_Protocol_Specification.md` - JSON 통신 프로토콜 명세
|
|
|
|
---
|
|
|
|
**작성일**: 2025-01-27
|
|
**버전**: 1.0
|
|
**작성자**: SystemController 통합 프로젝트
|