Fix : 에디터 ui 수정

This commit is contained in:
user 2026-03-08 00:23:54 +09:00
parent 657ca3d236
commit 595aa5f71f

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
@ -131,6 +132,7 @@ namespace KindRetargeting.Remote
string property = json["property"]?.ToString(); string property = json["property"]?.ToString();
float value = json["value"]?.Value<float>() ?? 0f; float value = json["value"]?.Value<float>() ?? 0f;
UpdateValue(charId, property, value); UpdateValue(charId, property, value);
BroadcastValueChanged(charId, property, value);
} }
break; break;
@ -164,6 +166,20 @@ namespace KindRetargeting.Remote
} }
break; break;
case "autoHipsOffset":
{
string charId = json["characterId"]?.ToString();
AutoHipsOffset(charId);
}
break;
case "autoCalibrateAll":
{
string charId = json["characterId"]?.ToString();
AutoCalibrateAll(charId);
}
break;
default: default:
Debug.LogWarning($"[RetargetingRemote] 알 수 없는 액션: {action}"); Debug.LogWarning($"[RetargetingRemote] 알 수 없는 액션: {action}");
break; break;
@ -574,6 +590,7 @@ namespace KindRetargeting.Remote
handPose.rightSpreadFingers = spread; handPose.rightSpreadFingers = spread;
} }
SendCharacterData(characterId);
SendStatus(true, $"{presetName} 프리셋 적용됨"); SendStatus(true, $"{presetName} 프리셋 적용됨");
} }
@ -612,6 +629,93 @@ namespace KindRetargeting.Remote
SendStatus(true, "정면 캘리브레이션 완료"); SendStatus(true, "정면 캘리브레이션 완료");
} }
private void AutoHipsOffset(string characterId)
{
var script = FindCharacter(characterId);
if (script == null) return;
float offset = CalculateHipsOffsetFromLegDifference(script);
SetPrivateField(script, "hipsOffsetY", offset);
script.SaveSettings();
SendCharacterData(characterId);
SendStatus(true, $"다리 길이 자동 보정 완료: hipsOffsetY={offset:F4}");
}
private void AutoCalibrateAll(string characterId)
{
var script = FindCharacter(characterId);
if (script == null) return;
Animator source = script.sourceAnimator;
Animator targetAnim = script.targetAnimator;
if (source == null || targetAnim == null || !source.isHuman || !targetAnim.isHuman)
{
SendStatus(false, "소스/타겟 Animator가 없거나 Humanoid가 아닙니다.");
return;
}
// Step 1: 크기 초기화 + 힙 오프셋 계산
script.ResetScale();
SetPrivateField(script, "avatarScale", 1f);
SetPrivateField(script, "hipsOffsetY", CalculateHipsOffsetFromLegDifference(script));
// Step 2: 1프레임 후 목 높이 비율로 크기 조정
StartCoroutine(AutoCalibrateCoroutine(script, characterId));
}
private IEnumerator AutoCalibrateCoroutine(CustomRetargetingScript script, string characterId)
{
yield return null; // 1프레임 대기
Animator source = script.sourceAnimator;
Animator targetAnim = script.targetAnimator;
Transform sourceNeck = source.GetBoneTransform(HumanBodyBones.Neck);
Transform targetNeck = targetAnim.GetBoneTransform(HumanBodyBones.Neck);
if (sourceNeck == null || targetNeck == null)
{
SendStatus(false, "목 본을 찾을 수 없습니다.");
yield break;
}
float scaleRatio = Mathf.Clamp(sourceNeck.position.y / Mathf.Max(targetNeck.position.y, 0.01f), 0.1f, 3f);
script.SetAvatarScale(scaleRatio);
SetPrivateField(script, "avatarScale", scaleRatio);
yield return null; // 1프레임 대기
// Step 3: 힙 오프셋 재계산 + 머리 정면 캘리브레이션
SetPrivateField(script, "hipsOffsetY", CalculateHipsOffsetFromLegDifference(script));
script.CalibrateHeadToForward();
script.SaveSettings();
SendCharacterData(characterId);
SendStatus(true, $"전체 자동 보정 완료: avatarScale={scaleRatio:F3}");
}
private float CalculateHipsOffsetFromLegDifference(CustomRetargetingScript script)
{
Animator source = script.sourceAnimator;
Animator targetAnim = script.targetAnimator;
if (source == null || targetAnim == null) return 0f;
float sourceLeg = GetLegLength(source);
float targetLeg = GetLegLength(targetAnim);
if (sourceLeg < 0.01f || targetLeg < 0.01f) return 0f;
return targetLeg - sourceLeg;
}
private float GetLegLength(Animator animator)
{
Transform upper = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
Transform lower = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
Transform foot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
if (upper == null || lower == null || foot == null) return 0f;
return Vector3.Distance(upper.position, lower.position) + Vector3.Distance(lower.position, foot.position);
}
private CustomRetargetingScript FindCharacter(string characterId) private CustomRetargetingScript FindCharacter(string characterId)
{ {
foreach (var script in registeredCharacters) foreach (var script in registeredCharacters)
@ -624,6 +728,19 @@ namespace KindRetargeting.Remote
return null; return null;
} }
private void BroadcastValueChanged(string characterId, string property, float value)
{
var response = new
{
type = "valueChanged",
characterId = characterId,
property = property,
value = value
};
wsServer?.Broadcast(JsonConvert.SerializeObject(response));
}
private void SendStatus(bool success, string message) private void SendStatus(bool success, string message)
{ {
var response = new var response = new