272 lines
12 KiB
C#
272 lines
12 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace KindRetargeting
|
|
{
|
|
/// <summary>
|
|
/// CustomRetargetingScript의 인스펙터를 커스터마이징하여 프로퍼티들을 접었다 펼칠 수 있는 섹션으로 그룹화합니다.
|
|
/// </summary>
|
|
[CustomEditor(typeof(CustomRetargetingScript))]
|
|
public class CustomRetargetingScriptEditor : BaseRetargetingEditor
|
|
{
|
|
// Foldout 상태를 저장할 변수들
|
|
private bool showHipsSettings = false;
|
|
private bool showFingerCopySettings = false;
|
|
private bool showMotionFilterSettings = false;
|
|
private bool showRoughMotionSettings = false;
|
|
private bool showKneeSettings = true;
|
|
private bool hasCachedData = false;
|
|
private bool showFloorSettings = false;
|
|
private bool showScaleSettings = true;
|
|
|
|
// SerializedProperty 변수들
|
|
private SerializedProperty sourceAnimatorProp;
|
|
private SerializedProperty targetAnimatorProp;
|
|
private SerializedProperty hipsOffsetXProp;
|
|
private SerializedProperty hipsOffsetYProp;
|
|
private SerializedProperty hipsOffsetZProp;
|
|
private SerializedProperty debugAxisNormalizerProp;
|
|
private SerializedProperty fingerCopyModeProp;
|
|
private SerializedProperty useMotionFilterProp;
|
|
private SerializedProperty filterBufferSizeProp;
|
|
private SerializedProperty useBodyRoughMotionProp;
|
|
private SerializedProperty useFingerRoughMotionProp;
|
|
private SerializedProperty bodyRoughnessProp;
|
|
private SerializedProperty fingerRoughnessProp;
|
|
private SerializedProperty kneeInOutWeightProp;
|
|
private SerializedProperty kneeFrontBackWeightProp;
|
|
private SerializedProperty floorHeightProp;
|
|
private SerializedProperty avatarScaleProp;
|
|
|
|
protected override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
// SerializedProperty 초기화
|
|
sourceAnimatorProp = serializedObject.FindProperty("sourceAnimator");
|
|
targetAnimatorProp = serializedObject.FindProperty("targetAnimator");
|
|
hipsOffsetXProp = serializedObject.FindProperty("hipsOffsetX");
|
|
hipsOffsetYProp = serializedObject.FindProperty("hipsOffsetY");
|
|
hipsOffsetZProp = serializedObject.FindProperty("hipsOffsetZ");
|
|
debugAxisNormalizerProp = serializedObject.FindProperty("debugAxisNormalizer");
|
|
fingerCopyModeProp = serializedObject.FindProperty("fingerCopyMode");
|
|
useMotionFilterProp = serializedObject.FindProperty("useMotionFilter");
|
|
filterBufferSizeProp = serializedObject.FindProperty("filterBufferSize");
|
|
useBodyRoughMotionProp = serializedObject.FindProperty("useBodyRoughMotion");
|
|
useFingerRoughMotionProp = serializedObject.FindProperty("useFingerRoughMotion");
|
|
bodyRoughnessProp = serializedObject.FindProperty("bodyRoughness");
|
|
fingerRoughnessProp = serializedObject.FindProperty("fingerRoughness");
|
|
kneeInOutWeightProp = serializedObject.FindProperty("kneeInOutWeight");
|
|
kneeFrontBackWeightProp = serializedObject.FindProperty("kneeFrontBackWeight");
|
|
floorHeightProp = serializedObject.FindProperty("floorHeight");
|
|
avatarScaleProp = serializedObject.FindProperty("avatarScale");
|
|
}
|
|
|
|
private void CheckCacheStatus()
|
|
{
|
|
var script = (CustomRetargetingScript)target;
|
|
hasCachedData = script.HasCachedSettings();
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// sourceAnimator를 한 번만 표시
|
|
EditorGUILayout.PropertyField(sourceAnimatorProp, new GUIContent("원본 Animator"));
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// 아바타 크기 조정 섹션 추가
|
|
showScaleSettings = EditorGUILayout.Foldout(showScaleSettings, "아바타 크기 설정", true);
|
|
if (showScaleSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(avatarScaleProp, new GUIContent("아바타 크기"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 힙 위치 보정 Foldout
|
|
showHipsSettings = EditorGUILayout.Foldout(showHipsSettings, "힙 위치 보정 (로컬 좌표계)");
|
|
if (showHipsSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
// 축 정규화 정보 표시
|
|
if (debugAxisNormalizerProp != null)
|
|
{
|
|
Vector3 normalizer = debugAxisNormalizerProp.vector3Value;
|
|
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUILayout.LabelField("축 정규화 정보", EditorStyles.boldLabel);
|
|
|
|
EditorGUI.BeginDisabledGroup(true);
|
|
EditorGUILayout.Vector3Field("정규화 계수", normalizer);
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
EditorGUILayout.HelpBox(
|
|
$"X축: {(normalizer.x > 0 ? "정방향 ↔" : "역방향 ↔")}\n" +
|
|
$"Y축: {(normalizer.y > 0 ? "정방향 ↕" : "역방향 ↕")}\n" +
|
|
$"Z축: {(normalizer.z > 0 ? "정방향 ⇄" : "역방향 ⇄")}\n\n" +
|
|
"이 계수는 Start()에서 자동 계산되며, 항상 직관적인 방향으로 제어할 수 있게 합니다.",
|
|
MessageType.Info);
|
|
EditorGUILayout.EndVertical();
|
|
|
|
GUILayout.Space(5);
|
|
}
|
|
|
|
EditorGUILayout.PropertyField(hipsOffsetXProp,
|
|
new GUIContent("좌우 오프셋 (←-/+→)", "캐릭터 기준 왼쪽(-) / 오른쪽(+)"));
|
|
EditorGUILayout.PropertyField(hipsOffsetYProp,
|
|
new GUIContent("상하 오프셋 (↓-/+↑)", "캐릭터 기준 아래(-) / 위(+)"));
|
|
EditorGUILayout.PropertyField(hipsOffsetZProp,
|
|
new GUIContent("앞뒤 오프셋 (←-/+→)", "캐릭터 기준 뒤(-) / 앞(+)"));
|
|
|
|
EditorGUILayout.HelpBox(
|
|
"로컬 좌표계 기반: 캐릭터의 회전 상태와 관계없이 항상 캐릭터 기준으로 이동합니다.",
|
|
MessageType.Info);
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 무릎 위치 조정 Foldout
|
|
showKneeSettings = EditorGUILayout.Foldout(showKneeSettings, "무릎 위치 조정", true);
|
|
if (showKneeSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
// 몸릎 안/밖 정만 표시
|
|
EditorGUILayout.Slider(kneeFrontBackWeightProp, -1f, 1f,
|
|
new GUIContent("무릎 앞/뒤 가중치", "음수: 뒤로, 양수: 앞으로"));
|
|
EditorGUILayout.Slider(kneeInOutWeightProp, -1f, 1f,
|
|
new GUIContent("무릎 안/밖 가중치", "음수: 안쪽, 양수: 바깥쪽"));
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 손가락 복제 설정 Foldout
|
|
showFingerCopySettings = EditorGUILayout.Foldout(showFingerCopySettings, "손가락 복제 설정");
|
|
if (showFingerCopySettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(fingerCopyModeProp,
|
|
new GUIContent("복제 방식", "손가락 포즈를 복제하는 방식을 선택합니다."));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 모션 필터링 설정 Foldout
|
|
showMotionFilterSettings = EditorGUILayout.Foldout(showMotionFilterSettings, "모션 필터링 설정");
|
|
if (showMotionFilterSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(useMotionFilterProp,
|
|
new GUIContent("모션 필터 사용", "모션 필터링을 적용할지 여부를 설정합니다."));
|
|
if (useMotionFilterProp.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(filterBufferSizeProp,
|
|
new GUIContent("필터 버퍼 크기", "모션 필터링에 사용할 버퍼의 크기를 설정합니다. (2-10)"));
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 러프 모션 설정 Foldout
|
|
showRoughMotionSettings = EditorGUILayout.Foldout(showRoughMotionSettings, "러프 모션 설정");
|
|
if (showRoughMotionSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
// 몸 러프 모션 설정
|
|
EditorGUILayout.PropertyField(useBodyRoughMotionProp,
|
|
new GUIContent("몸 러프 모션 사용", "몸의 러프한 움직임을 적용할지 여부를 설정합니다."));
|
|
if (useBodyRoughMotionProp.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(bodyRoughnessProp,
|
|
new GUIContent("몸 러프니스", "몸 전체의 러프한 정도를 설정합니다 (0: 없음, 1: 최대)"));
|
|
}
|
|
|
|
// 손가락 러프 모션 설정
|
|
EditorGUILayout.PropertyField(useFingerRoughMotionProp,
|
|
new GUIContent("손가락 러프 모션 사용", "손가락의 러프한 움직임을 적용할지 여부를 설정합니다."));
|
|
if (useFingerRoughMotionProp.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(fingerRoughnessProp,
|
|
new GUIContent("손가락 러프니스", "손가락의 러프한 정도를 설정합니다 (0: 없음, 1: 최대)"));
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUILayout.Space(5);
|
|
|
|
// 바닥 높이 조정 Foldout
|
|
showFloorSettings = EditorGUILayout.Foldout(showFloorSettings, "바닥 높이 조정", true);
|
|
if (showFloorSettings)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(floorHeightProp, new GUIContent("바닥 높이 (-1 ~ 1)"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
// 캐시 상태를 텍스트로 표시
|
|
EditorGUILayout.LabelField(hasCachedData ?
|
|
"캘리브레이션 데이터가 저장되어 있습니다." :
|
|
"저장된 캘리브레이션 데이터가 없습니다.",
|
|
EditorStyles.boldLabel);
|
|
|
|
// 버튼들을 수평으로 배치
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
// I-포즈 캘리브레이션 버튼
|
|
if (GUILayout.Button("I-포즈 캘리브레이션"))
|
|
{
|
|
var script = (CustomRetargetingScript)target;
|
|
script.I_PoseCalibration();
|
|
CheckCacheStatus();
|
|
Repaint();
|
|
}
|
|
|
|
// 캐시 삭제 버튼 (캐시가 있을 때만 표시)
|
|
if (hasCachedData)
|
|
{
|
|
if (GUILayout.Button("캐시 데이터 삭제"))
|
|
{
|
|
var script = (CustomRetargetingScript)target;
|
|
script.ResetPoseAndCache();
|
|
CheckCacheStatus();
|
|
Repaint();
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
GUILayout.Space(10);
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
var script = (CustomRetargetingScript)target;
|
|
if (script.targetAnimator != null) // targetAnimator가 설정되어 있을 때만 저장
|
|
{
|
|
script.SaveSettings();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
}
|
|
}
|
|
} |