From 34564f0f50534ee9744e0eaad31891c7a2bb977c Mon Sep 17 00:00:00 2001 From: user Date: Thu, 22 Jan 2026 22:50:04 +0900 Subject: [PATCH] =?UTF-8?q?ADD:=20MagicaCloth=20=EC=8B=9C=EB=AE=AC?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=A0=84=EC=B2=B4=20=EB=A6=AC?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SystemController에 MagicaCloth2 시뮬레이션 리셋 기능 구현: - RefreshAllMagicaCloth(): 씬의 모든 MagicaCloth 시뮬레이션 리셋 - ResetAllMagicaCloth(): 초기 상태로 완전 리셋 - ResetAllMagicaClothKeepPose(): 현재 포즈 유지하며 리셋 - #if MAGICACLOTH2 조건부 컴파일로 의존성 처리 StreamDeck 플러그인 연동: - manifest.json에 MagicaCloth Refresh 액션 추가 - plugin/index.js에 버튼 핸들러 구현 - StreamDeckServerManager에 메시지 타입 등록 - magica_cloth_reload.png 아이콘 추가 WebSocket 명령어: - refresh_magica_cloth, reset_magica_cloth: 전체 리셋 - reset_magica_cloth_keep_pose: 포즈 유지 리셋 Co-Authored-By: Claude Opus 4.5 --- .../Streamdeck/StreamDeckServerManager.cs | 3 + .../Controllers/SystemController.cs | 84 +++++++++++++++++++ .../images/magica_cloth_reload.png | 3 + .../manifest.json | 4 +- .../plugin/index.js | 66 +++++++++++++++ 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 Streamdeck/com.mirabox.streamingle.sdPlugin/images/magica_cloth_reload.png diff --git a/Assets/Scripts/Streamdeck/StreamDeckServerManager.cs b/Assets/Scripts/Streamdeck/StreamDeckServerManager.cs index a32534bf..ba1e892f 100644 --- a/Assets/Scripts/Streamdeck/StreamDeckServerManager.cs +++ b/Assets/Scripts/Streamdeck/StreamDeckServerManager.cs @@ -357,6 +357,9 @@ public class StreamDeckServerManager : MonoBehaviour case "capture_screenshot": case "capture_alpha_screenshot": case "open_screenshot_folder": + case "refresh_magica_cloth": + case "reset_magica_cloth": + case "reset_magica_cloth_keep_pose": HandleSystemCommand(message); break; diff --git a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs index b076086c..a9520fd5 100644 --- a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs +++ b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs @@ -4,6 +4,9 @@ using System.Linq; using System.IO; using System; using Entum; +#if MAGICACLOTH2 +using MagicaCloth2; +#endif /// /// StreamDeck 단일 기능 버튼들을 통합 관리하는 시스템 컨트롤러 @@ -681,6 +684,77 @@ public class SystemController : MonoBehaviour #endregion + #region MagicaCloth 시뮬레이션 기능 + +#if MAGICACLOTH2 + /// + /// 씬의 모든 MagicaCloth 시뮬레이션을 리셋합니다 + /// + /// true면 현재 포즈를 유지하면서 리셋 + public void RefreshAllMagicaCloth(bool keepPose = false) + { + var allMagicaCloths = FindObjectsByType(FindObjectsSortMode.None); + + if (allMagicaCloths == null || allMagicaCloths.Length == 0) + { + Log("씬에 MagicaCloth 컴포넌트가 없습니다."); + return; + } + + int resetCount = 0; + foreach (var cloth in allMagicaCloths) + { + if (cloth != null && cloth.IsValid()) + { + try + { + cloth.ResetCloth(keepPose); + resetCount++; + } + catch (System.Exception e) + { + LogError($"MagicaCloth 리셋 실패 ({cloth.gameObject.name}): {e.Message}"); + } + } + } + + Log($"MagicaCloth 시뮬레이션 리셋 완료 ({resetCount}/{allMagicaCloths.Length}개)"); + } + + /// + /// 씬의 모든 MagicaCloth 시뮬레이션을 완전히 초기 상태로 리셋합니다 + /// + public void ResetAllMagicaCloth() + { + RefreshAllMagicaCloth(false); + } + + /// + /// 씬의 모든 MagicaCloth 시뮬레이션을 현재 포즈를 유지하면서 리셋합니다 + /// + public void ResetAllMagicaClothKeepPose() + { + RefreshAllMagicaCloth(true); + } +#else + public void RefreshAllMagicaCloth(bool keepPose = false) + { + LogError("MagicaCloth2가 설치되어 있지 않습니다."); + } + + public void ResetAllMagicaCloth() + { + LogError("MagicaCloth2가 설치되어 있지 않습니다."); + } + + public void ResetAllMagicaClothKeepPose() + { + LogError("MagicaCloth2가 설치되어 있지 않습니다."); + } +#endif + + #endregion + /// /// 명령어 실행 - WebSocket에서 받은 명령을 처리 /// @@ -747,6 +821,16 @@ public class SystemController : MonoBehaviour OpenScreenshotFolder(); break; + // MagicaCloth 시뮬레이션 + case "refresh_magica_cloth": + case "reset_magica_cloth": + ResetAllMagicaCloth(); + break; + + case "reset_magica_cloth_keep_pose": + ResetAllMagicaClothKeepPose(); + break; + default: LogError($"알 수 없는 명령어: {command}"); break; diff --git a/Streamdeck/com.mirabox.streamingle.sdPlugin/images/magica_cloth_reload.png b/Streamdeck/com.mirabox.streamingle.sdPlugin/images/magica_cloth_reload.png new file mode 100644 index 00000000..36606ae7 --- /dev/null +++ b/Streamdeck/com.mirabox.streamingle.sdPlugin/images/magica_cloth_reload.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef7d1829ffac2ba7d67fa0bdb0fddc4bf2245aeeb618d2c8a7f6f8c74e00b65c +size 7651 diff --git a/Streamdeck/com.mirabox.streamingle.sdPlugin/manifest.json b/Streamdeck/com.mirabox.streamingle.sdPlugin/manifest.json index 7896416a..98fb2596 100644 --- a/Streamdeck/com.mirabox.streamingle.sdPlugin/manifest.json +++ b/Streamdeck/com.mirabox.streamingle.sdPlugin/manifest.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12627ac0969f34220ce859abbc9ace8b19b657b48b7c923575b3d1a30686fa66 -size 7771 +oid sha256:afebe3438733ca4e06a6aa6a95b5f95c6329a868be6ee178abddac0f8c014b7b +size 8315 diff --git a/Streamdeck/com.mirabox.streamingle.sdPlugin/plugin/index.js b/Streamdeck/com.mirabox.streamingle.sdPlugin/plugin/index.js index 878dfd6d..35f51cb0 100644 --- a/Streamdeck/com.mirabox.streamingle.sdPlugin/plugin/index.js +++ b/Streamdeck/com.mirabox.streamingle.sdPlugin/plugin/index.js @@ -147,6 +147,20 @@ function connectElgatoStreamDeckSocket(inPort, inUUID, inEvent, inInfo, inAction newSettings.actionType = 'screenshot_alpha'; console.log('📷 알파 스크린샷 버튼으로 강제 설정됨'); + // StreamDock SDK에 저장 + if (websocket) { + const setSettingsMessage = { + event: 'setSettings', + context: jsonObj.context, + payload: newSettings + }; + websocket.send(JSON.stringify(setSettingsMessage)); + console.log('💾 강제 설정 저장:', newSettings); + } + } else if (jsonObj.action === 'com.mirabox.streamingle.magica_cloth_refresh') { + newSettings.actionType = 'magica_cloth_refresh'; + console.log('👗 MagicaCloth 리프레시 버튼으로 강제 설정됨'); + // StreamDock SDK에 저장 if (websocket) { const setSettingsMessage = { @@ -240,6 +254,14 @@ function connectElgatoStreamDeckSocket(inPort, inUUID, inEvent, inInfo, inAction // 기본 제목 설정 setButtonTitle(jsonObj.context, '알파\n스크린샷'); + } else if (jsonObj.action === 'com.mirabox.streamingle.magica_cloth_refresh') { + settings.actionType = 'magica_cloth_refresh'; + console.log('👗👗👗 MAGICA CLOTH REFRESH BUTTON DETECTED 👗👗👗'); + console.log('👗 This is the MagicaCloth Refresh button!'); + console.log('👗 When clicked, it should send: refresh_magica_cloth'); + + // 기본 제목 설정 + setButtonTitle(jsonObj.context, '마지카\n리프레시'); } else { settings.actionType = 'camera'; console.log('📹 카메라 컨트롤러 등록 (기본값)'); @@ -486,6 +508,9 @@ function handleButtonClick(context, actionUUID) { } else if (actionUUID === 'com.mirabox.streamingle.screenshot_alpha') { actionType = 'screenshot_alpha'; console.log('📷 알파 스크린샷 버튼으로 인식'); + } else if (actionUUID === 'com.mirabox.streamingle.magica_cloth_refresh') { + actionType = 'magica_cloth_refresh'; + console.log('👗 MagicaCloth 리프레시 버튼으로 인식'); } else if (actionUUID === 'com.mirabox.streamingle.item') { actionType = 'item'; } else if (actionUUID === 'com.mirabox.streamingle.event') { @@ -562,6 +587,11 @@ function handleButtonClick(context, actionUUID) { console.log(' Will send: {"type":"capture_alpha_screenshot"}'); handleAlphaScreenshot(context); break; + case 'magica_cloth_refresh': + console.log('➡️ Routing to: MAGICA CLOTH REFRESH handler'); + console.log(' Will send: {"type":"refresh_magica_cloth"}'); + handleMagicaClothRefresh(context); + break; default: console.log('⚠️ WARNING: Unknown actionType:', actionType); console.log(' Defaulting to CAMERA handler'); @@ -962,6 +992,37 @@ function handleAlphaScreenshot(context) { } } +// MagicaCloth 리프레시 액션 처리 +function handleMagicaClothRefresh(context) { + console.log('👗 MagicaCloth 시뮬레이션 리프레시 실행'); + + // Unity에 MagicaCloth 리프레시 요청 + const message = JSON.stringify({ + type: 'refresh_magica_cloth' + }); + + console.log('📤 Unity에 MagicaCloth 리프레시 요청 전송:', message); + console.log('🔍 Unity 연결 상태:', isUnityConnected); + console.log('🔍 Unity 소켓 상태:', !!unitySocket); + + if (unitySocket && unitySocket.readyState === WebSocket.OPEN) { + unitySocket.send(message); + console.log('✅ 메시지 전송 완료'); + + // 피드백을 위해 제목을 잠시 변경 + setButtonTitle(context, '리셋\n중...'); + + // 1초 후 원래 제목으로 복구 + setTimeout(() => { + setButtonTitle(context, '마지카\n리프레시'); + }, 1000); + } else { + console.error('❌ Unity 소켓이 연결되지 않음'); + console.log('🔄 Unity 재연결 시도...'); + connectToUnity(); + } +} + // Property Inspector 메시지 처리 function handlePropertyInspectorMessage(payload, context, actionUUID) { const command = payload.command; @@ -1947,6 +2008,11 @@ function updateButtonTitle(context) { title = '알파\n스크린샷'; isActive = true; // 항상 활성 상태 console.log('📷 알파 스크린샷 버튼 제목:', title); + } else if (actionType === 'magica_cloth_refresh') { + // MagicaCloth 리프레시 버튼 + title = '마지카\n리프레시'; + isActive = true; // 항상 활성 상태 + console.log('👗 MagicaCloth 리프레시 버튼 제목:', title); } // StreamDock에 제목 업데이트 요청