Refactor : 리타겟팅 컨트롤 패널 + 웹 대시보드 + 리모트 컨트롤러 동기화
- RetargetingControlWindow: 어깨 보정, 접지 설정, IK 토글, 최소 발목 높이 섹션 추가 - RetargetingRemoteController: 어깨 반전 토글, 개별 손가락 curl, 최소 발목 높이 Send/Update 추가 - dashboard_script.txt: 어깨 보정/접지 설정 섹션 신규, IK 토글, 개별 손가락 슬라이더, 최소 발목 높이 추가 - 에디터 인스펙터/컨트롤 패널/웹 대시보드 3곳 설정 항목 완전 동기화 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e17cfc003c
commit
defed38ae5
BIN
Assets/Resources/StreamingleDashboard/dashboard_script.txt
(Stored with Git LFS)
BIN
Assets/Resources/StreamingleDashboard/dashboard_script.txt
(Stored with Git LFS)
Binary file not shown.
@ -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)
|
||||
|
||||
@ -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<float>(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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user