777 lines
23 KiB
C#
777 lines
23 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.IO;
|
|
using System;
|
|
using Entum;
|
|
|
|
/// <summary>
|
|
/// StreamDeck 단일 기능 버튼들을 통합 관리하는 시스템 컨트롤러
|
|
/// 각 기능은 고유 ID로 식별되며, 확장이 용이한 구조
|
|
/// </summary>
|
|
public class SystemController : MonoBehaviour
|
|
{
|
|
[Header("OptiTrack 참조")]
|
|
public OptitrackStreamingClient optitrackClient;
|
|
|
|
[Header("모션 녹화 설정")]
|
|
[Tooltip("모션 녹화 시 OptiTrack Motive도 함께 녹화할지 여부")]
|
|
public bool recordOptiTrackWithMotion = true;
|
|
|
|
[Header("EasyMotion Recorder")]
|
|
[Tooltip("true면 씬의 모든 MotionDataRecorder를 자동으로 찾습니다")]
|
|
public bool autoFindRecorders = true;
|
|
|
|
[Tooltip("수동으로 지정할 레코더 목록 (autoFindRecorders가 false일 때 사용)")]
|
|
public List<MotionDataRecorder> motionRecorders = new List<MotionDataRecorder>();
|
|
|
|
[Header("Facial Motion Capture")]
|
|
[Tooltip("true면 씬의 모든 페이셜 모션 클라이언트를 자동으로 찾습니다")]
|
|
public bool autoFindFacialMotionClients = true;
|
|
|
|
[Tooltip("수동으로 지정할 페이셜 모션 클라이언트 목록 (autoFindFacialMotionClients가 false일 때 사용)")]
|
|
public List<UnityRecieve_FACEMOTION3D_and_iFacialMocap> facialMotionClients = new List<UnityRecieve_FACEMOTION3D_and_iFacialMocap>();
|
|
|
|
[Header("Screenshot Settings")]
|
|
[Tooltip("스크린샷 해상도 (기본: 4K)")]
|
|
public int screenshotWidth = 3840;
|
|
|
|
[Tooltip("스크린샷 해상도 (기본: 4K)")]
|
|
public int screenshotHeight = 2160;
|
|
|
|
[Tooltip("스크린샷 저장 경로 (비어있으면 바탕화면)")]
|
|
public string screenshotSavePath = "";
|
|
|
|
[Tooltip("파일명 앞에 붙을 접두사")]
|
|
public string screenshotFilePrefix = "Screenshot";
|
|
|
|
[Tooltip("알파 채널 추출용 셰이더")]
|
|
public Shader alphaShader;
|
|
|
|
[Tooltip("NiloToon Prepass 버퍼 텍스처 이름")]
|
|
public string niloToonPrepassBufferName = "_NiloToonPrepassBufferTex";
|
|
|
|
[Tooltip("촬영할 카메라 (비어있으면 메인 카메라 사용)")]
|
|
public Camera screenshotCamera;
|
|
|
|
[Tooltip("알파 채널 블러 반경 (0 = 블러 없음, 1.0 = 약한 블러)")]
|
|
[Range(0f, 3f)]
|
|
public float alphaBlurRadius = 1.0f;
|
|
|
|
[Header("디버그")]
|
|
public bool enableDebugLog = true;
|
|
|
|
private bool isRecording = false;
|
|
private Material alphaMaterial;
|
|
|
|
// 싱글톤 패턴
|
|
public static SystemController Instance { get; private set; }
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
}
|
|
else
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
// OptiTrack 클라이언트 자동 찾기
|
|
if (optitrackClient == null)
|
|
{
|
|
optitrackClient = FindObjectOfType<OptitrackStreamingClient>();
|
|
}
|
|
|
|
// Motion Recorder 자동 찾기
|
|
if (autoFindRecorders)
|
|
{
|
|
RefreshMotionRecorders();
|
|
}
|
|
|
|
// Facial Motion 클라이언트 자동 찾기
|
|
if (autoFindFacialMotionClients)
|
|
{
|
|
RefreshFacialMotionClients();
|
|
}
|
|
|
|
// Screenshot 설정 초기화
|
|
if (screenshotCamera == null)
|
|
{
|
|
screenshotCamera = Camera.main;
|
|
}
|
|
|
|
if (alphaShader == null)
|
|
{
|
|
alphaShader = Shader.Find("Hidden/AlphaFromNiloToon");
|
|
if (alphaShader == null)
|
|
{
|
|
LogError("알파 셰이더를 찾을 수 없습니다: Hidden/AlphaFromNiloToon");
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(screenshotSavePath))
|
|
{
|
|
screenshotSavePath = Path.Combine(Application.dataPath, "..", "Screenshots");
|
|
}
|
|
|
|
// Screenshots 폴더가 없으면 생성
|
|
if (!Directory.Exists(screenshotSavePath))
|
|
{
|
|
Directory.CreateDirectory(screenshotSavePath);
|
|
Log($"Screenshots 폴더 생성됨: {screenshotSavePath}");
|
|
}
|
|
|
|
Log("SystemController 초기화 완료");
|
|
Log($"Motion Recorder 개수: {motionRecorders.Count}");
|
|
Log($"Facial Motion 클라이언트 개수: {facialMotionClients.Count}");
|
|
Log($"Screenshot 카메라: {(screenshotCamera != null ? "설정됨" : "없음")}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 씬에서 모든 MotionDataRecorder를 다시 찾습니다
|
|
/// </summary>
|
|
public void RefreshMotionRecorders()
|
|
{
|
|
var allRecorders = FindObjectsOfType<MotionDataRecorder>();
|
|
motionRecorders = allRecorders.ToList();
|
|
Log($"Motion Recorder {motionRecorders.Count}개 발견");
|
|
}
|
|
|
|
#region OptiTrack 마커 기능
|
|
|
|
/// <summary>
|
|
/// OptiTrack 마커 표시 토글 (켜기/끄기)
|
|
/// </summary>
|
|
public void ToggleOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
LogError("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
optitrackClient.ToggleDrawMarkers();
|
|
Log($"OptiTrack 마커 표시: {optitrackClient.DrawMarkers}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// OptiTrack 마커 표시 켜기
|
|
/// </summary>
|
|
public void ShowOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
LogError("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
if (!optitrackClient.DrawMarkers)
|
|
{
|
|
optitrackClient.ToggleDrawMarkers();
|
|
}
|
|
Log("OptiTrack 마커 표시 켜짐");
|
|
}
|
|
|
|
/// <summary>
|
|
/// OptiTrack 마커 표시 끄기
|
|
/// </summary>
|
|
public void HideOptitrackMarkers()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
LogError("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
if (optitrackClient.DrawMarkers)
|
|
{
|
|
optitrackClient.ToggleDrawMarkers();
|
|
}
|
|
Log("OptiTrack 마커 표시 꺼짐");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OptiTrack 재접속 기능
|
|
|
|
/// <summary>
|
|
/// OptiTrack 서버에 재접속 시도
|
|
/// </summary>
|
|
public void ReconnectOptitrack()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
LogError("OptitrackStreamingClient를 찾을 수 없습니다!");
|
|
return;
|
|
}
|
|
|
|
Log("OptiTrack 재접속 시도...");
|
|
optitrackClient.Reconnect();
|
|
Log("OptiTrack 재접속 명령 전송 완료");
|
|
}
|
|
|
|
/// <summary>
|
|
/// OptiTrack 연결 상태 확인
|
|
/// </summary>
|
|
public bool IsOptitrackConnected()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return optitrackClient.IsConnected();
|
|
}
|
|
|
|
/// <summary>
|
|
/// OptiTrack 연결 상태를 문자열로 반환
|
|
/// </summary>
|
|
public string GetOptitrackConnectionStatus()
|
|
{
|
|
if (optitrackClient == null)
|
|
{
|
|
return "OptiTrack 클라이언트 없음";
|
|
}
|
|
|
|
return optitrackClient.GetConnectionStatus();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Facial Motion Capture 재접속 기능
|
|
|
|
/// <summary>
|
|
/// 씬에서 모든 Facial Motion 클라이언트를 다시 찾습니다
|
|
/// </summary>
|
|
public void RefreshFacialMotionClients()
|
|
{
|
|
var allClients = FindObjectsOfType<UnityRecieve_FACEMOTION3D_and_iFacialMocap>();
|
|
facialMotionClients = allClients.ToList();
|
|
Log($"Facial Motion 클라이언트 {facialMotionClients.Count}개 발견");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 Facial Motion 클라이언트 재접속
|
|
/// </summary>
|
|
public void ReconnectFacialMotion()
|
|
{
|
|
if (autoFindFacialMotionClients)
|
|
{
|
|
RefreshFacialMotionClients();
|
|
}
|
|
|
|
if (facialMotionClients == null || facialMotionClients.Count == 0)
|
|
{
|
|
LogError("Facial Motion 클라이언트가 없습니다!");
|
|
return;
|
|
}
|
|
|
|
Log($"Facial Motion 클라이언트 재접속 시도... ({facialMotionClients.Count}개)");
|
|
|
|
int reconnectedCount = 0;
|
|
foreach (var client in facialMotionClients)
|
|
{
|
|
if (client != null)
|
|
{
|
|
try
|
|
{
|
|
client.Reconnect();
|
|
reconnectedCount++;
|
|
Log($"클라이언트 재접속 성공: {client.gameObject.name}");
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
LogError($"클라이언트 재접속 실패 ({client.gameObject.name}): {e.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (reconnectedCount > 0)
|
|
{
|
|
Log($"=== Facial Motion 재접속 완료 ({reconnectedCount}/{facialMotionClients.Count}개) ===");
|
|
}
|
|
else
|
|
{
|
|
LogError("재접속에 성공한 클라이언트가 없습니다!");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 스크린샷 기능
|
|
|
|
/// <summary>
|
|
/// 일반 스크린샷 촬영
|
|
/// </summary>
|
|
public void CaptureScreenshot()
|
|
{
|
|
if (screenshotCamera == null)
|
|
{
|
|
LogError("촬영할 카메라가 설정되지 않았습니다!");
|
|
return;
|
|
}
|
|
|
|
string fileName = GenerateFileName("png");
|
|
string fullPath = Path.Combine(screenshotSavePath, fileName);
|
|
|
|
try
|
|
{
|
|
// 렌더 텍스처 생성
|
|
RenderTexture rt = new RenderTexture(screenshotWidth, screenshotHeight, 24);
|
|
RenderTexture currentRT = screenshotCamera.targetTexture;
|
|
|
|
// 카메라로 렌더링
|
|
screenshotCamera.targetTexture = rt;
|
|
screenshotCamera.Render();
|
|
|
|
// 텍스처를 Texture2D로 변환
|
|
RenderTexture.active = rt;
|
|
Texture2D screenshot = new Texture2D(screenshotWidth, screenshotHeight, TextureFormat.RGB24, false);
|
|
screenshot.ReadPixels(new Rect(0, 0, screenshotWidth, screenshotHeight), 0, 0);
|
|
screenshot.Apply();
|
|
|
|
// PNG로 저장
|
|
byte[] bytes = screenshot.EncodeToPNG();
|
|
File.WriteAllBytes(fullPath, bytes);
|
|
|
|
// 정리 - RenderTexture는 Release() 후 Destroy() 호출 필요
|
|
screenshotCamera.targetTexture = currentRT;
|
|
RenderTexture.active = null;
|
|
rt.Release();
|
|
Destroy(rt);
|
|
Destroy(screenshot);
|
|
|
|
Log($"스크린샷 저장 완료: {fullPath}");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogError($"스크린샷 촬영 실패: {e.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 알파 채널 포함 스크린샷 촬영
|
|
/// NiloToon Prepass 버퍼의 G 채널을 알파로 사용
|
|
/// </summary>
|
|
public void CaptureAlphaScreenshot()
|
|
{
|
|
if (screenshotCamera == null)
|
|
{
|
|
LogError("촬영할 카메라가 설정되지 않았습니다!");
|
|
return;
|
|
}
|
|
|
|
if (alphaShader == null)
|
|
{
|
|
LogError("알파 셰이더가 설정되지 않았습니다!");
|
|
return;
|
|
}
|
|
|
|
string fileName = GenerateFileName("png", "_Alpha");
|
|
string fullPath = Path.Combine(screenshotSavePath, fileName);
|
|
|
|
try
|
|
{
|
|
// 렌더 텍스처 생성
|
|
RenderTexture rt = new RenderTexture(screenshotWidth, screenshotHeight, 24);
|
|
RenderTexture currentRT = screenshotCamera.targetTexture;
|
|
|
|
// 카메라로 렌더링
|
|
screenshotCamera.targetTexture = rt;
|
|
screenshotCamera.Render();
|
|
|
|
// NiloToon Prepass 버퍼 가져오기
|
|
Texture niloToonPrepassBuffer = Shader.GetGlobalTexture(niloToonPrepassBufferName);
|
|
|
|
if (niloToonPrepassBuffer == null)
|
|
{
|
|
LogError($"NiloToon Prepass 버퍼를 찾을 수 없습니다: {niloToonPrepassBufferName}");
|
|
screenshotCamera.targetTexture = currentRT;
|
|
Destroy(rt);
|
|
return;
|
|
}
|
|
|
|
// 알파 합성용 머티리얼 생성
|
|
if (alphaMaterial == null)
|
|
{
|
|
alphaMaterial = new Material(alphaShader);
|
|
}
|
|
|
|
// 알파 채널 합성
|
|
RenderTexture alphaRT = new RenderTexture(screenshotWidth, screenshotHeight, 0, RenderTextureFormat.ARGB32);
|
|
alphaMaterial.SetTexture("_MainTex", rt);
|
|
alphaMaterial.SetTexture("_AlphaTex", niloToonPrepassBuffer);
|
|
alphaMaterial.SetFloat("_BlurRadius", alphaBlurRadius);
|
|
|
|
// Blit으로 알파 합성
|
|
Graphics.Blit(rt, alphaRT, alphaMaterial);
|
|
|
|
// 텍스처를 Texture2D로 변환
|
|
RenderTexture.active = alphaRT;
|
|
Texture2D screenshot = new Texture2D(screenshotWidth, screenshotHeight, TextureFormat.RGBA32, false);
|
|
screenshot.ReadPixels(new Rect(0, 0, screenshotWidth, screenshotHeight), 0, 0);
|
|
screenshot.Apply();
|
|
|
|
// PNG로 저장
|
|
byte[] bytes = screenshot.EncodeToPNG();
|
|
File.WriteAllBytes(fullPath, bytes);
|
|
|
|
// 정리 - RenderTexture는 Release() 후 Destroy() 호출 필요
|
|
screenshotCamera.targetTexture = currentRT;
|
|
RenderTexture.active = null;
|
|
rt.Release();
|
|
Destroy(rt);
|
|
alphaRT.Release();
|
|
Destroy(alphaRT);
|
|
Destroy(screenshot);
|
|
|
|
Log($"알파 스크린샷 저장 완료: {fullPath}");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogError($"알파 스크린샷 촬영 실패: {e.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 스크린샷 저장 폴더 열기
|
|
/// </summary>
|
|
public void OpenScreenshotFolder()
|
|
{
|
|
if (Directory.Exists(screenshotSavePath))
|
|
{
|
|
System.Diagnostics.Process.Start(screenshotSavePath);
|
|
Log($"저장 폴더 열기: {screenshotSavePath}");
|
|
}
|
|
else
|
|
{
|
|
LogError($"저장 폴더가 존재하지 않습니다: {screenshotSavePath}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파일명 생성
|
|
/// </summary>
|
|
private string GenerateFileName(string extension, string suffix = "")
|
|
{
|
|
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
|
return $"{screenshotFilePrefix}{suffix}_{timestamp}.{extension}";
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 모션 녹화 기능 (EasyMotion Recorder + OptiTrack Motive)
|
|
|
|
/// <summary>
|
|
/// 모션 녹화 시작 (EasyMotion Recorder + OptiTrack Motive)
|
|
/// </summary>
|
|
public void StartMotionRecording()
|
|
{
|
|
// OptiTrack 녹화 시작 (옵션이 켜져 있을 때만)
|
|
bool optitrackStarted = false;
|
|
if (recordOptiTrackWithMotion)
|
|
{
|
|
if (optitrackClient != null)
|
|
{
|
|
try
|
|
{
|
|
optitrackStarted = optitrackClient.StartRecording();
|
|
if (optitrackStarted)
|
|
{
|
|
Log("OptiTrack Motive 녹화 시작 성공");
|
|
}
|
|
else
|
|
{
|
|
LogError("OptiTrack Motive 녹화 시작 실패");
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
LogError($"OptiTrack 녹화 시작 오류: {e.Message}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("OptiTrack 클라이언트 없음 - OptiTrack 녹화 건너뜀");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("OptiTrack 녹화 옵션 꺼짐 - OptiTrack 녹화 건너뜀");
|
|
}
|
|
|
|
// EasyMotion Recorder 녹화 시작
|
|
int startedCount = 0;
|
|
if (motionRecorders != null && motionRecorders.Count > 0)
|
|
{
|
|
foreach (var recorder in motionRecorders)
|
|
{
|
|
if (recorder != null)
|
|
{
|
|
try
|
|
{
|
|
// RecordStart 메서드 호출
|
|
var method = recorder.GetType().GetMethod("RecordStart");
|
|
if (method != null)
|
|
{
|
|
method.Invoke(recorder, null);
|
|
startedCount++;
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
LogError($"레코더 시작 실패 ({recorder.name}): {e.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (startedCount > 0)
|
|
{
|
|
Log($"EasyMotion 녹화 시작 ({startedCount}/{motionRecorders.Count}개 레코더)");
|
|
}
|
|
else
|
|
{
|
|
LogError("녹화를 시작한 EasyMotion 레코더가 없습니다!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("EasyMotion Recorder 없음 - EasyMotion 녹화 건너뜀");
|
|
}
|
|
|
|
// 하나라도 성공하면 녹화 중 상태로 설정
|
|
if (optitrackStarted || startedCount > 0)
|
|
{
|
|
isRecording = true;
|
|
Log($"=== 녹화 시작 완료 ===");
|
|
if (recordOptiTrackWithMotion)
|
|
{
|
|
Log($"OptiTrack: {(optitrackStarted ? "시작됨" : "시작 안됨")}");
|
|
}
|
|
else
|
|
{
|
|
Log($"OptiTrack: 옵션 꺼짐");
|
|
}
|
|
Log($"EasyMotion: {startedCount}개 레코더 시작됨");
|
|
}
|
|
else
|
|
{
|
|
LogError("녹화를 시작할 수 있는 시스템이 없습니다!");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모션 녹화 중지 (EasyMotion Recorder + OptiTrack Motive)
|
|
/// </summary>
|
|
public void StopMotionRecording()
|
|
{
|
|
// OptiTrack 녹화 중지 (옵션이 켜져 있을 때만)
|
|
bool optitrackStopped = false;
|
|
if (recordOptiTrackWithMotion)
|
|
{
|
|
if (optitrackClient != null)
|
|
{
|
|
try
|
|
{
|
|
optitrackStopped = optitrackClient.StopRecording();
|
|
if (optitrackStopped)
|
|
{
|
|
Log("OptiTrack Motive 녹화 중지 성공");
|
|
}
|
|
else
|
|
{
|
|
LogError("OptiTrack Motive 녹화 중지 실패");
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
LogError($"OptiTrack 녹화 중지 오류: {e.Message}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("OptiTrack 클라이언트 없음 - OptiTrack 녹화 중지 건너뜀");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("OptiTrack 녹화 옵션 꺼짐 - OptiTrack 녹화 중지 건너뜀");
|
|
}
|
|
|
|
// EasyMotion Recorder 녹화 중지
|
|
int stoppedCount = 0;
|
|
if (motionRecorders != null && motionRecorders.Count > 0)
|
|
{
|
|
foreach (var recorder in motionRecorders)
|
|
{
|
|
if (recorder != null)
|
|
{
|
|
try
|
|
{
|
|
// RecordEnd 메서드 호출
|
|
var method = recorder.GetType().GetMethod("RecordEnd");
|
|
if (method != null)
|
|
{
|
|
method.Invoke(recorder, null);
|
|
stoppedCount++;
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
LogError($"레코더 중지 실패 ({recorder.name}): {e.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (stoppedCount > 0)
|
|
{
|
|
Log($"EasyMotion 녹화 중지 ({stoppedCount}/{motionRecorders.Count}개 레코더)");
|
|
}
|
|
else
|
|
{
|
|
LogError("녹화를 중지한 EasyMotion 레코더가 없습니다!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log("EasyMotion Recorder 없음 - EasyMotion 녹화 중지 건너뜀");
|
|
}
|
|
|
|
// 하나라도 성공하면 녹화 중지 상태로 설정
|
|
if (optitrackStopped || stoppedCount > 0)
|
|
{
|
|
isRecording = false;
|
|
Log($"=== 녹화 중지 완료 ===");
|
|
Log($"OptiTrack: {(optitrackStopped ? "중지됨" : "중지 안됨")}");
|
|
Log($"EasyMotion: {stoppedCount}개 레코더 중지됨");
|
|
}
|
|
else
|
|
{
|
|
LogError("녹화를 중지할 수 있는 시스템이 없습니다!");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모션 녹화 토글 (시작/중지)
|
|
/// </summary>
|
|
public void ToggleMotionRecording()
|
|
{
|
|
if (isRecording)
|
|
{
|
|
StopMotionRecording();
|
|
}
|
|
else
|
|
{
|
|
StartMotionRecording();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 녹화 중인지 여부 반환
|
|
/// </summary>
|
|
public bool IsRecording()
|
|
{
|
|
return isRecording;
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 명령어 실행 - WebSocket에서 받은 명령을 처리
|
|
/// </summary>
|
|
public void ExecuteCommand(string command, Dictionary<string, object> parameters)
|
|
{
|
|
Log($"명령어 실행: {command}");
|
|
|
|
switch (command)
|
|
{
|
|
// OptiTrack 마커
|
|
case "toggle_optitrack_markers":
|
|
ToggleOptitrackMarkers();
|
|
break;
|
|
|
|
case "show_optitrack_markers":
|
|
ShowOptitrackMarkers();
|
|
break;
|
|
|
|
case "hide_optitrack_markers":
|
|
HideOptitrackMarkers();
|
|
break;
|
|
|
|
// OptiTrack 재접속
|
|
case "reconnect_optitrack":
|
|
ReconnectOptitrack();
|
|
break;
|
|
|
|
// Facial Motion 재접속
|
|
case "reconnect_facial_motion":
|
|
ReconnectFacialMotion();
|
|
break;
|
|
|
|
case "refresh_facial_motion_clients":
|
|
RefreshFacialMotionClients();
|
|
break;
|
|
|
|
// EasyMotion Recorder
|
|
case "start_motion_recording":
|
|
StartMotionRecording();
|
|
break;
|
|
|
|
case "stop_motion_recording":
|
|
StopMotionRecording();
|
|
break;
|
|
|
|
case "toggle_motion_recording":
|
|
ToggleMotionRecording();
|
|
break;
|
|
|
|
case "refresh_motion_recorders":
|
|
RefreshMotionRecorders();
|
|
break;
|
|
|
|
// 스크린샷
|
|
case "capture_screenshot":
|
|
CaptureScreenshot();
|
|
break;
|
|
|
|
case "capture_alpha_screenshot":
|
|
CaptureAlphaScreenshot();
|
|
break;
|
|
|
|
case "open_screenshot_folder":
|
|
OpenScreenshotFolder();
|
|
break;
|
|
|
|
default:
|
|
LogError($"알 수 없는 명령어: {command}");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (alphaMaterial != null)
|
|
{
|
|
Destroy(alphaMaterial);
|
|
}
|
|
}
|
|
|
|
private void Log(string message)
|
|
{
|
|
if (enableDebugLog)
|
|
{
|
|
Debug.Log($"[SystemController] {message}");
|
|
}
|
|
}
|
|
|
|
private void LogError(string message)
|
|
{
|
|
Debug.LogError($"[SystemController] {message}");
|
|
}
|
|
}
|