- 모든 컨트롤러 에디터를 IMGUI → UI Toolkit(UXML/USS)으로 전환 (Camera, Item, Event, Avatar, System, StreamDeck, OptiTrack, Facial) - StreamingleCommon.uss 공통 테마 + 개별 에디터 USS 스타일시트 - SystemController 서브매니저 분리 (OptiTrack, Facial, Recording, Screenshot 등) - 런타임 컨트롤 패널 (ESC 토글, 좌측 오버레이, 150% 스케일) - 웹 대시보드 서버 (StreamingleDashboardServer) + 리타게팅 통합 - 설정 도구(StreamingleControllerSetupTool) UXML 재작성 + 원클릭 설정 - SimplePoseTransfer UXML 에디터 추가 - 전체 UXML 한글화 + NanumGothic 폰트 적용 - Streamingle.Debug → Streamingle.Debugging 네임스페이스 변경 (Debug.Log 충돌 해결) - 불필요 코드 제거 (rawkey.cs, RetargetingHTTPServer, OptitrackSkeletonAnimator 등) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
136 lines
3.8 KiB
C#
136 lines
3.8 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using KindRetargeting;
|
|
using KindRetargeting.Remote;
|
|
|
|
/// <summary>
|
|
/// 리타게팅 WebSocket 서버 관리
|
|
/// (HTTP UI는 Streamingle Dashboard에 통합됨)
|
|
/// </summary>
|
|
[Serializable]
|
|
public class RetargetingRemoteManager
|
|
{
|
|
[Tooltip("리타게팅 웹 리모컨 컨트롤러 (없으면 자동 생성)")]
|
|
public RetargetingRemoteController retargetingRemote;
|
|
|
|
[Tooltip("리타게팅 WebSocket 포트")]
|
|
public int retargetingWsPort = 64212;
|
|
|
|
[Tooltip("시작 시 리타게팅 자동 시작")]
|
|
public bool autoStartRetargetingRemote = true;
|
|
|
|
private Action<string> log;
|
|
private Action<string> logError;
|
|
|
|
public void Initialize(Action<string> log, Action<string> logError)
|
|
{
|
|
this.log = log;
|
|
this.logError = logError;
|
|
|
|
InitializeRetargetingRemote();
|
|
}
|
|
|
|
private void InitializeRetargetingRemote()
|
|
{
|
|
if (retargetingRemote == null)
|
|
{
|
|
retargetingRemote = UnityEngine.Object.FindObjectOfType<RetargetingRemoteController>();
|
|
}
|
|
|
|
if (retargetingRemote == null && autoStartRetargetingRemote)
|
|
{
|
|
GameObject remoteObj = new GameObject("RetargetingRemoteController");
|
|
retargetingRemote = remoteObj.AddComponent<RetargetingRemoteController>();
|
|
retargetingRemote.AutoStart = false;
|
|
log?.Invoke("리타게팅 컨트롤러 자동 생성됨");
|
|
}
|
|
|
|
if (retargetingRemote != null)
|
|
{
|
|
retargetingRemote.WsPort = retargetingWsPort;
|
|
}
|
|
|
|
if (retargetingRemote != null)
|
|
{
|
|
AutoRegisterRetargetingCharacters();
|
|
|
|
if (autoStartRetargetingRemote && !retargetingRemote.IsRunning)
|
|
{
|
|
retargetingRemote.StartServer();
|
|
log?.Invoke($"리타게팅 WebSocket 시작됨 - WS: {retargetingWsPort}");
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AutoRegisterRetargetingCharacters()
|
|
{
|
|
if (retargetingRemote == null)
|
|
{
|
|
logError?.Invoke("리타게팅 컨트롤러가 없습니다!");
|
|
return;
|
|
}
|
|
|
|
var characters = UnityEngine.Object.FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
|
|
foreach (var character in characters)
|
|
{
|
|
retargetingRemote.RegisterCharacter(character);
|
|
}
|
|
|
|
log?.Invoke($"리타게팅 캐릭터 {characters.Length}개 등록됨");
|
|
}
|
|
|
|
public void StartRetargetingRemote()
|
|
{
|
|
if (retargetingRemote == null)
|
|
{
|
|
InitializeRetargetingRemote();
|
|
}
|
|
|
|
if (retargetingRemote != null && !retargetingRemote.IsRunning)
|
|
{
|
|
retargetingRemote.StartServer();
|
|
log?.Invoke($"리타게팅 WebSocket 시작됨 - WS: {retargetingWsPort}");
|
|
}
|
|
}
|
|
|
|
public void StopRetargetingRemote()
|
|
{
|
|
if (retargetingRemote != null && retargetingRemote.IsRunning)
|
|
{
|
|
retargetingRemote.StopServer();
|
|
log?.Invoke("리타게팅 WebSocket 중지됨");
|
|
}
|
|
}
|
|
|
|
public void ToggleRetargetingRemote()
|
|
{
|
|
if (retargetingRemote == null || !retargetingRemote.IsRunning)
|
|
{
|
|
StartRetargetingRemote();
|
|
}
|
|
else
|
|
{
|
|
StopRetargetingRemote();
|
|
}
|
|
}
|
|
|
|
public void IsRetargetingRemoteRunning(out bool running)
|
|
{
|
|
running = retargetingRemote != null && retargetingRemote.IsRunning;
|
|
}
|
|
|
|
public bool IsRetargetingRemoteRunning()
|
|
{
|
|
return retargetingRemote != null && retargetingRemote.IsRunning;
|
|
}
|
|
|
|
public string GetRetargetingRemoteUrl()
|
|
{
|
|
if (retargetingRemote != null && retargetingRemote.IsRunning)
|
|
{
|
|
return $"ws://localhost:{retargetingWsPort}";
|
|
}
|
|
return "";
|
|
}
|
|
}
|