From defed38ae57b16162a2e0345018cc53144ef6c97 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 7 Mar 2026 23:48:58 +0900 Subject: [PATCH] =?UTF-8?q?Refactor=20:=20=EB=A6=AC=ED=83=80=EA=B2=9F?= =?UTF-8?q?=ED=8C=85=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=20=ED=8C=A8=EB=84=90=20?= =?UTF-8?q?+=20=EC=9B=B9=20=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20+=20?= =?UTF-8?q?=EB=A6=AC=EB=AA=A8=ED=8A=B8=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EB=8F=99=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RetargetingControlWindow: 어깨 보정, 접지 설정, IK 토글, 최소 발목 높이 섹션 추가 - RetargetingRemoteController: 어깨 반전 토글, 개별 손가락 curl, 최소 발목 높이 Send/Update 추가 - dashboard_script.txt: 어깨 보정/접지 설정 섹션 신규, IK 토글, 개별 손가락 슬라이더, 최소 발목 높이 추가 - 에디터 인스펙터/컨트롤 패널/웹 대시보드 3곳 설정 항목 완전 동기화 Co-Authored-By: Claude Opus 4.6 --- .../StreamingleDashboard/dashboard_script.txt | 4 +- .../Editor/RetargetingControlWindow.cs | 73 ++++++++++++++++++- .../Remote/RetargetingRemoteController.cs | 66 +++++++++++++++++ 3 files changed, 138 insertions(+), 5 deletions(-) diff --git a/Assets/Resources/StreamingleDashboard/dashboard_script.txt b/Assets/Resources/StreamingleDashboard/dashboard_script.txt index af1b39464..b5f65181d 100644 --- a/Assets/Resources/StreamingleDashboard/dashboard_script.txt +++ b/Assets/Resources/StreamingleDashboard/dashboard_script.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:059ac85fede20a79fe0403d71a144085818ec97e5a802a4c7e31a050a1536390 -size 73083 +oid sha256:3cc8474349ae9b211196debb5dadaf88beac2b04fd106d4ddf3a341005f8b09b +size 77699 diff --git a/Assets/Scripts/KindRetargeting/Editor/RetargetingControlWindow.cs b/Assets/Scripts/KindRetargeting/Editor/RetargetingControlWindow.cs index 7f92c758e..13d306daf 100644 --- a/Assets/Scripts/KindRetargeting/Editor/RetargetingControlWindow.cs +++ b/Assets/Scripts/KindRetargeting/Editor/RetargetingControlWindow.cs @@ -224,6 +224,12 @@ public class RetargetingControlWindow : EditorWindow footContainer.Bind(so); panel.Add(footFoldout); + // 어깨 보정 + panel.Add(BuildShoulderSection(script, so)); + + // 접지 설정 + panel.Add(BuildGroundingSection(script, so)); + // 손가락 제어 설정 panel.Add(BuildFingerControlSection(script, so)); @@ -232,9 +238,11 @@ public class RetargetingControlWindow : EditorWindow // 바닥 높이 설정 var floorFoldout = new Foldout { text = "바닥 높이 설정", value = false }; - var floorField = new PropertyField(so.FindProperty("floorHeight"), "바닥 높이 (-1 ~ 1)"); - floorFoldout.Add(floorField); - floorField.Bind(so); + var floorContainer = new VisualElement(); + floorContainer.Add(new PropertyField(so.FindProperty("floorHeight"), "바닥 높이 (-1 ~ 1)")); + floorContainer.Add(new PropertyField(so.FindProperty("minimumAnkleHeight"), "최소 발목 높이")); + floorContainer.Bind(so); + floorFoldout.Add(floorContainer); panel.Add(floorFoldout); // 아바타 크기 설정 @@ -304,6 +312,10 @@ public class RetargetingControlWindow : EditorWindow var foldout = new Foldout { text = "가중치 설정", value = false }; var container = new VisualElement(); + // IK 활성화 토글 + container.Add(new PropertyField(so.FindProperty("limbWeight.enableLeftArmIK"), "왼팔 IK 활성화")); + container.Add(new PropertyField(so.FindProperty("limbWeight.enableRightArmIK"), "오른팔 IK 활성화")); + container.Add(BuildMinMaxRange("손과 프랍과의 범위 (가중치 1 → 0)", so.FindProperty("limbWeight.minDistance"), so.FindProperty("limbWeight.maxDistance"), 0f, 1f, so)); container.Add(BuildMinMaxRange("의자와 허리 거리 범위 (가중치 1 → 0)", @@ -736,6 +748,61 @@ public class RetargetingControlWindow : EditorWindow return box; } + // ========== Shoulder Correction ========== + + private VisualElement BuildShoulderSection(CustomRetargetingScript script, SerializedObject so) + { + var foldout = new Foldout { text = "어깨 보정", value = false }; + var container = new VisualElement(); + + var strength = new Slider("블렌드 강도", 0f, 5f) { showInputField = true }; + strength.BindProperty(so.FindProperty("shoulderCorrection.blendStrength")); + container.Add(strength); + + var maxBlend = new Slider("최대 블렌드", 0f, 1f) { showInputField = true }; + maxBlend.BindProperty(so.FindProperty("shoulderCorrection.maxShoulderBlend")); + container.Add(maxBlend); + + container.Add(new PropertyField(so.FindProperty("shoulderCorrection.reverseLeftRotation"), "왼쪽 회전 반전")); + container.Add(new PropertyField(so.FindProperty("shoulderCorrection.reverseRightRotation"), "오른쪽 회전 반전")); + + container.Add(BuildMinMaxRange("높이 차이 범위", + so.FindProperty("shoulderCorrection.minHeightDifference"), + so.FindProperty("shoulderCorrection.maxHeightDifference"), + -0.5f, 2f, so)); + + container.Add(new PropertyField(so.FindProperty("shoulderCorrection.shoulderCorrectionCurve"), "보정 커브")); + + container.Bind(so); + foldout.Add(container); + return foldout; + } + + // ========== Foot Grounding ========== + + private VisualElement BuildGroundingSection(CustomRetargetingScript script, SerializedObject so) + { + var foldout = new Foldout { text = "접지 설정", value = false }; + var container = new VisualElement(); + + container.Add(new PropertyField(so.FindProperty("footGrounding.groundHeight"), "바닥 높이")); + + var weightSlider = new Slider("접지 강도", 0f, 1f) { showInputField = true }; + weightSlider.BindProperty(so.FindProperty("footGrounding.groundingWeight")); + container.Add(weightSlider); + + container.Add(new PropertyField(so.FindProperty("footGrounding.activationHeight"), "활성화 높이") { tooltip = "발목이 이 높이 이상이면 보정 비활성화" }); + container.Add(new PropertyField(so.FindProperty("footGrounding.plantThreshold"), "접지 판정 범위")); + + var smoothField = new Slider("스무딩 속도", 1f, 30f) { showInputField = true }; + smoothField.BindProperty(so.FindProperty("footGrounding.smoothSpeed")); + container.Add(smoothField); + + container.Bind(so); + foldout.Add(container); + return foldout; + } + // ========== Helpers ========== private VisualElement BuildMinMaxRange(string label, SerializedProperty minProp, SerializedProperty maxProp, float limitMin, float limitMax, SerializedObject so) diff --git a/Assets/Scripts/KindRetargeting/Remote/RetargetingRemoteController.cs b/Assets/Scripts/KindRetargeting/Remote/RetargetingRemoteController.cs index fbf07c675..cb4b1198d 100644 --- a/Assets/Scripts/KindRetargeting/Remote/RetargetingRemoteController.cs +++ b/Assets/Scripts/KindRetargeting/Remote/RetargetingRemoteController.cs @@ -269,6 +269,8 @@ namespace KindRetargeting.Remote { "shoulderMaxBlend", script.shoulderCorrection.maxShoulderBlend }, { "shoulderMaxHeightDiff", script.shoulderCorrection.maxHeightDifference }, { "shoulderMinHeightDiff", script.shoulderCorrection.minHeightDifference }, + { "shoulderReverseLeft", script.shoulderCorrection.reverseLeftRotation }, + { "shoulderReverseRight", script.shoulderCorrection.reverseRightRotation }, // FootGrounding 데이터 { "groundingWeight", script.footGrounding.groundingWeight }, @@ -281,6 +283,21 @@ namespace KindRetargeting.Remote { "handPoseEnabled", script.fingerShaped.enabled }, { "leftHandEnabled", script.fingerShaped.leftHandEnabled }, { "rightHandEnabled", script.fingerShaped.rightHandEnabled }, + { "leftThumbCurl", script.fingerShaped.leftThumbCurl }, + { "leftIndexCurl", script.fingerShaped.leftIndexCurl }, + { "leftMiddleCurl", script.fingerShaped.leftMiddleCurl }, + { "leftRingCurl", script.fingerShaped.leftRingCurl }, + { "leftPinkyCurl", script.fingerShaped.leftPinkyCurl }, + { "leftSpreadFingers", script.fingerShaped.leftSpreadFingers }, + { "rightThumbCurl", script.fingerShaped.rightThumbCurl }, + { "rightIndexCurl", script.fingerShaped.rightIndexCurl }, + { "rightMiddleCurl", script.fingerShaped.rightMiddleCurl }, + { "rightRingCurl", script.fingerShaped.rightRingCurl }, + { "rightPinkyCurl", script.fingerShaped.rightPinkyCurl }, + { "rightSpreadFingers", script.fingerShaped.rightSpreadFingers }, + + // 최소 발목 높이 + { "minimumAnkleHeight", GetPrivateField(script, "minimumAnkleHeight") }, }; var response = new @@ -409,6 +426,12 @@ namespace KindRetargeting.Remote case "shoulderMinHeightDiff": script.shoulderCorrection.minHeightDifference = value; break; + case "shoulderReverseLeft": + script.shoulderCorrection.reverseLeftRotation = value > 0.5f; + break; + case "shoulderReverseRight": + script.shoulderCorrection.reverseRightRotation = value > 0.5f; + break; // FootGrounding 속성 case "groundingWeight": @@ -442,6 +465,49 @@ namespace KindRetargeting.Remote script.fingerShaped.enabled = true; break; + // 개별 손가락 curl 값 + case "leftThumbCurl": + script.fingerShaped.leftThumbCurl = value; + break; + case "leftIndexCurl": + script.fingerShaped.leftIndexCurl = value; + break; + case "leftMiddleCurl": + script.fingerShaped.leftMiddleCurl = value; + break; + case "leftRingCurl": + script.fingerShaped.leftRingCurl = value; + break; + case "leftPinkyCurl": + script.fingerShaped.leftPinkyCurl = value; + break; + case "leftSpreadFingers": + script.fingerShaped.leftSpreadFingers = value; + break; + case "rightThumbCurl": + script.fingerShaped.rightThumbCurl = value; + break; + case "rightIndexCurl": + script.fingerShaped.rightIndexCurl = value; + break; + case "rightMiddleCurl": + script.fingerShaped.rightMiddleCurl = value; + break; + case "rightRingCurl": + script.fingerShaped.rightRingCurl = value; + break; + case "rightPinkyCurl": + script.fingerShaped.rightPinkyCurl = value; + break; + case "rightSpreadFingers": + script.fingerShaped.rightSpreadFingers = value; + break; + + // 최소 발목 높이 + case "minimumAnkleHeight": + SetPrivateField(script, "minimumAnkleHeight", value); + break; + default: Debug.LogWarning($"[RetargetingRemote] 알 수 없는 속성: {property}"); break;