Fix : 에디터 ui 수정
This commit is contained in:
parent
657ca3d236
commit
595aa5f71f
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user