- 모든 컨트롤러 에디터를 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>
184 lines
5.5 KiB
C#
184 lines
5.5 KiB
C#
using UnityEngine;
|
|
using System;
|
|
|
|
/// <summary>
|
|
/// OptiTrack 모션캡처 클라이언트 관리
|
|
/// </summary>
|
|
[Serializable]
|
|
public class OptiTrackManager
|
|
{
|
|
[Tooltip("OptiTrack 클라이언트")]
|
|
public OptitrackStreamingClient optitrackClient;
|
|
|
|
[Tooltip("OptiTrack 클라이언트가 없을 때 자동으로 프리펩에서 생성할지 여부")]
|
|
public bool autoSpawnOptitrackClient = true;
|
|
|
|
[Tooltip("OptiTrack 클라이언트 프리펩 경로 (Resources 폴더 기준이 아닌 경우 직접 할당 필요)")]
|
|
public GameObject optitrackClientPrefab;
|
|
|
|
[Tooltip("모션 녹화 시 OptiTrack Motive도 함께 녹화할지 여부")]
|
|
public bool recordOptiTrackWithMotion = true;
|
|
|
|
private Action<string> log;
|
|
private Action<string> logError;
|
|
|
|
public void Initialize(Action<string> log, Action<string> logError)
|
|
{
|
|
this.log = log;
|
|
this.logError = logError;
|
|
InitializeOptitrackClient();
|
|
}
|
|
|
|
private void InitializeOptitrackClient()
|
|
{
|
|
if (optitrackClient != null)
|
|
{
|
|
log?.Invoke("OptiTrack 클라이언트가 이미 할당되어 있습니다.");
|
|
return;
|
|
}
|
|
|
|
optitrackClient = UnityEngine.Object.FindObjectOfType<OptitrackStreamingClient>();
|
|
|
|
if (optitrackClient != null)
|
|
{
|
|
log?.Invoke("씬에서 OptiTrack 클라이언트를 찾았습니다.");
|
|
return;
|
|
}
|
|
|
|
if (autoSpawnOptitrackClient)
|
|
{
|
|
SpawnOptitrackClientFromPrefab();
|
|
}
|
|
else
|
|
{
|
|
log?.Invoke("OptiTrack 클라이언트가 없습니다. 자동 생성 옵션이 꺼져 있습니다.");
|
|
}
|
|
}
|
|
|
|
public void SpawnOptitrackClientFromPrefab()
|
|
{
|
|
var existingClient = UnityEngine.Object.FindObjectOfType<OptitrackStreamingClient>();
|
|
if (existingClient != null)
|
|
{
|
|
optitrackClient = existingClient;
|
|
log?.Invoke("씬에 이미 OptiTrack 클라이언트가 있습니다.");
|
|
return;
|
|
}
|
|
|
|
GameObject clientInstance = null;
|
|
|
|
if (optitrackClientPrefab != null)
|
|
{
|
|
clientInstance = UnityEngine.Object.Instantiate(optitrackClientPrefab);
|
|
clientInstance.name = "Client - OptiTrack";
|
|
log?.Invoke("할당된 프리펩에서 OptiTrack 클라이언트 생성됨");
|
|
}
|
|
else
|
|
{
|
|
#if UNITY_EDITOR
|
|
string prefabPath = "Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Client - OptiTrack.prefab";
|
|
var prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
if (prefab != null)
|
|
{
|
|
clientInstance = UnityEngine.Object.Instantiate(prefab);
|
|
clientInstance.name = "Client - OptiTrack";
|
|
log?.Invoke($"프리펩에서 OptiTrack 클라이언트 생성됨: {prefabPath}");
|
|
}
|
|
else
|
|
{
|
|
logError?.Invoke($"OptiTrack 클라이언트 프리펩을 찾을 수 없습니다: {prefabPath}");
|
|
return;
|
|
}
|
|
#else
|
|
logError?.Invoke("OptiTrack 클라이언트 프리펩이 할당되지 않았습니다. Inspector에서 프리펩을 할당해주세요.");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
if (clientInstance != null)
|
|
{
|
|
optitrackClient = clientInstance.GetComponent<OptitrackStreamingClient>();
|
|
if (optitrackClient == null)
|
|
{
|
|
logError?.Invoke("생성된 프리펩에 OptitrackStreamingClient 컴포넌트가 없습니다!");
|
|
UnityEngine.Object.Destroy(clientInstance);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ToggleOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
logError?.Invoke("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
optitrackClient.ToggleDrawMarkers();
|
|
log?.Invoke($"OptiTrack 마커 표시: {optitrackClient.DrawMarkers}");
|
|
}
|
|
|
|
public void ShowOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
logError?.Invoke("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
if (!optitrackClient.DrawMarkers)
|
|
{
|
|
optitrackClient.ToggleDrawMarkers();
|
|
}
|
|
log?.Invoke("OptiTrack 마커 표시 켜짐");
|
|
}
|
|
|
|
public void HideOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
logError?.Invoke("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
if (optitrackClient.DrawMarkers)
|
|
{
|
|
optitrackClient.ToggleDrawMarkers();
|
|
}
|
|
log?.Invoke("OptiTrack 마커 표시 꺼짐");
|
|
}
|
|
|
|
public void ReconnectOptitrack()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
logError?.Invoke("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
log?.Invoke("OptiTrack 재접속 시도...");
|
|
optitrackClient.Reconnect();
|
|
log?.Invoke("OptiTrack 재접속 명령 전송 완료");
|
|
}
|
|
|
|
public bool IsOptitrackConnected()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return optitrackClient.IsConnected();
|
|
}
|
|
|
|
public string GetOptitrackConnectionStatus()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
return "OptiTrack 클라이언트 없음";
|
|
}
|
|
|
|
return optitrackClient.GetConnectionStatus();
|
|
}
|
|
}
|