305 lines
13 KiB
C#
305 lines
13 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEngine.Animations.Rigging;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace EditorTools
|
|
{
|
|
public static class BoneRendererContextMenu
|
|
{
|
|
[MenuItem("CONTEXT/BoneRenderer/휴머노이드 본 자동 추가")]
|
|
private static void AddHumanoidBones(MenuCommand command)
|
|
{
|
|
BoneRenderer boneRenderer = command.context as BoneRenderer;
|
|
if (boneRenderer == null) return;
|
|
|
|
Animator animator = boneRenderer.GetComponent<Animator>();
|
|
if (animator == null || !animator.isHuman)
|
|
{
|
|
EditorUtility.DisplayDialog("오류", "휴머노이드 Animator가 필요합니다.", "확인");
|
|
return;
|
|
}
|
|
|
|
Undo.RecordObject(boneRenderer, "Add Humanoid Bones");
|
|
|
|
List<Transform> humanoidBones = GetAvailableHumanoidBones(animator);
|
|
boneRenderer.transforms = humanoidBones.ToArray();
|
|
|
|
EditorUtility.SetDirty(boneRenderer);
|
|
Debug.Log($"{humanoidBones.Count}개의 휴머노이드 본이 BoneRenderer에 추가되었습니다.");
|
|
}
|
|
|
|
[MenuItem("CONTEXT/BoneRenderer/본 목록 초기화")]
|
|
private static void ClearBones(MenuCommand command)
|
|
{
|
|
BoneRenderer boneRenderer = command.context as BoneRenderer;
|
|
if (boneRenderer == null) return;
|
|
|
|
if (!EditorUtility.DisplayDialog("확인", "본 목록을 초기화하시겠습니까?", "예", "아니오"))
|
|
return;
|
|
|
|
Undo.RecordObject(boneRenderer, "Clear Bones");
|
|
|
|
boneRenderer.transforms = new Transform[0];
|
|
|
|
EditorUtility.SetDirty(boneRenderer);
|
|
Debug.Log("BoneRenderer의 본 목록이 초기화되었습니다.");
|
|
}
|
|
|
|
private static readonly HumanBodyBones[] HumanoidBoneTypes = new HumanBodyBones[]
|
|
{
|
|
HumanBodyBones.Hips, HumanBodyBones.Spine, HumanBodyBones.Chest, HumanBodyBones.UpperChest,
|
|
HumanBodyBones.Neck, HumanBodyBones.Head,
|
|
HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand,
|
|
HumanBodyBones.LeftThumbProximal, HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,
|
|
HumanBodyBones.LeftIndexProximal, HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,
|
|
HumanBodyBones.LeftMiddleProximal, HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,
|
|
HumanBodyBones.LeftRingProximal, HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,
|
|
HumanBodyBones.LeftLittleProximal, HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal,
|
|
HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand,
|
|
HumanBodyBones.RightThumbProximal, HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,
|
|
HumanBodyBones.RightIndexProximal, HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,
|
|
HumanBodyBones.RightMiddleProximal, HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,
|
|
HumanBodyBones.RightRingProximal, HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,
|
|
HumanBodyBones.RightLittleProximal, HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal,
|
|
HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes,
|
|
HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, HumanBodyBones.RightToes
|
|
};
|
|
|
|
private static List<Transform> GetAvailableHumanoidBones(Animator animator)
|
|
{
|
|
List<Transform> humanoidBones = new List<Transform>();
|
|
|
|
foreach (HumanBodyBones boneType in HumanoidBoneTypes)
|
|
{
|
|
Transform bone = animator.GetBoneTransform(boneType);
|
|
if (bone != null)
|
|
{
|
|
humanoidBones.Add(bone);
|
|
}
|
|
}
|
|
|
|
return humanoidBones;
|
|
}
|
|
}
|
|
[CustomEditor(typeof(BoneRenderer))]
|
|
[CanEditMultipleObjects]
|
|
public class BoneRendererEditorExtension : Editor
|
|
{
|
|
static readonly GUIContent k_BoneSizeLabel = new GUIContent("Bone Size");
|
|
static readonly GUIContent k_BoneColorLabel = new GUIContent("Color");
|
|
static readonly GUIContent k_BoneShapeLabel = new GUIContent("Shape");
|
|
static readonly GUIContent k_TripodSizeLabel = new GUIContent("Tripod Size");
|
|
|
|
SerializedProperty m_DrawBones;
|
|
SerializedProperty m_BoneShape;
|
|
SerializedProperty m_BoneSize;
|
|
SerializedProperty m_BoneColor;
|
|
|
|
SerializedProperty m_DrawTripods;
|
|
SerializedProperty m_TripodSize;
|
|
|
|
SerializedProperty m_Transforms;
|
|
|
|
// 휴머노이드 본 타입 정의
|
|
private static readonly HumanBodyBones[] HumanoidBoneTypes = new HumanBodyBones[]
|
|
{
|
|
// 스파인 체인
|
|
HumanBodyBones.Hips,
|
|
HumanBodyBones.Spine,
|
|
HumanBodyBones.Chest,
|
|
HumanBodyBones.UpperChest,
|
|
HumanBodyBones.Neck,
|
|
HumanBodyBones.Head,
|
|
|
|
// 왼쪽 팔
|
|
HumanBodyBones.LeftShoulder,
|
|
HumanBodyBones.LeftUpperArm,
|
|
HumanBodyBones.LeftLowerArm,
|
|
HumanBodyBones.LeftHand,
|
|
|
|
// 왼쪽 손가락
|
|
HumanBodyBones.LeftThumbProximal,
|
|
HumanBodyBones.LeftThumbIntermediate,
|
|
HumanBodyBones.LeftThumbDistal,
|
|
HumanBodyBones.LeftIndexProximal,
|
|
HumanBodyBones.LeftIndexIntermediate,
|
|
HumanBodyBones.LeftIndexDistal,
|
|
HumanBodyBones.LeftMiddleProximal,
|
|
HumanBodyBones.LeftMiddleIntermediate,
|
|
HumanBodyBones.LeftMiddleDistal,
|
|
HumanBodyBones.LeftRingProximal,
|
|
HumanBodyBones.LeftRingIntermediate,
|
|
HumanBodyBones.LeftRingDistal,
|
|
HumanBodyBones.LeftLittleProximal,
|
|
HumanBodyBones.LeftLittleIntermediate,
|
|
HumanBodyBones.LeftLittleDistal,
|
|
|
|
// 오른쪽 팔
|
|
HumanBodyBones.RightShoulder,
|
|
HumanBodyBones.RightUpperArm,
|
|
HumanBodyBones.RightLowerArm,
|
|
HumanBodyBones.RightHand,
|
|
|
|
// 오른쪽 손가락
|
|
HumanBodyBones.RightThumbProximal,
|
|
HumanBodyBones.RightThumbIntermediate,
|
|
HumanBodyBones.RightThumbDistal,
|
|
HumanBodyBones.RightIndexProximal,
|
|
HumanBodyBones.RightIndexIntermediate,
|
|
HumanBodyBones.RightIndexDistal,
|
|
HumanBodyBones.RightMiddleProximal,
|
|
HumanBodyBones.RightMiddleIntermediate,
|
|
HumanBodyBones.RightMiddleDistal,
|
|
HumanBodyBones.RightRingProximal,
|
|
HumanBodyBones.RightRingIntermediate,
|
|
HumanBodyBones.RightRingDistal,
|
|
HumanBodyBones.RightLittleProximal,
|
|
HumanBodyBones.RightLittleIntermediate,
|
|
HumanBodyBones.RightLittleDistal,
|
|
|
|
// 왼쪽 다리
|
|
HumanBodyBones.LeftUpperLeg,
|
|
HumanBodyBones.LeftLowerLeg,
|
|
HumanBodyBones.LeftFoot,
|
|
HumanBodyBones.LeftToes,
|
|
|
|
// 오른쪽 다리
|
|
HumanBodyBones.RightUpperLeg,
|
|
HumanBodyBones.RightLowerLeg,
|
|
HumanBodyBones.RightFoot,
|
|
HumanBodyBones.RightToes
|
|
};
|
|
|
|
public void OnEnable()
|
|
{
|
|
m_DrawBones = serializedObject.FindProperty("drawBones");
|
|
m_BoneSize = serializedObject.FindProperty("boneSize");
|
|
m_BoneShape = serializedObject.FindProperty("boneShape");
|
|
m_BoneColor = serializedObject.FindProperty("boneColor");
|
|
|
|
m_DrawTripods = serializedObject.FindProperty("drawTripods");
|
|
m_TripodSize = serializedObject.FindProperty("tripodSize");
|
|
|
|
m_Transforms = serializedObject.FindProperty("m_Transforms");
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
// 기본 BoneRenderer UI
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.PropertyField(m_DrawBones, k_BoneSizeLabel);
|
|
using (new EditorGUI.DisabledScope(!m_DrawBones.boolValue))
|
|
EditorGUILayout.PropertyField(m_BoneSize, GUIContent.none);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
using (new EditorGUI.DisabledScope(!m_DrawBones.boolValue))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(m_BoneShape, k_BoneShapeLabel);
|
|
EditorGUILayout.PropertyField(m_BoneColor, k_BoneColorLabel);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.PropertyField(m_DrawTripods, k_TripodSizeLabel);
|
|
using (new EditorGUI.DisabledScope(!m_DrawTripods.boolValue))
|
|
EditorGUILayout.PropertyField(m_TripodSize, GUIContent.none);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
bool isDragPerformed = Event.current.type == EventType.DragPerform;
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUILayout.PropertyField(m_Transforms, true);
|
|
bool boneRendererDirty = EditorGUI.EndChangeCheck();
|
|
boneRendererDirty |= Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed";
|
|
boneRendererDirty |= Event.current.type == EventType.Used && isDragPerformed;
|
|
|
|
// 휴머노이드 본 자동 설정 섹션
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("휴머노이드 본 자동 설정", EditorStyles.boldLabel);
|
|
|
|
BoneRenderer boneRenderer = target as BoneRenderer;
|
|
GameObject targetObject = boneRenderer.gameObject;
|
|
|
|
// Animator 확인 및 상태 표시
|
|
Animator animator = targetObject.GetComponent<Animator>();
|
|
if (animator == null)
|
|
{
|
|
EditorGUILayout.HelpBox("Animator 컴포넌트가 필요합니다.", MessageType.Warning);
|
|
}
|
|
else if (!animator.isHuman)
|
|
{
|
|
EditorGUILayout.HelpBox("휴머노이드 아바타로 설정되지 않았습니다.", MessageType.Warning);
|
|
}
|
|
else
|
|
{
|
|
// 사용 가능한 본 수 표시
|
|
List<Transform> availableBones = GetAvailableHumanoidBones(animator);
|
|
EditorGUILayout.HelpBox($"사용 가능한 휴머노이드 본: {availableBones.Count}개", MessageType.Info);
|
|
|
|
// 버튼들
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("휴머노이드 본 추가"))
|
|
{
|
|
AddHumanoidBones(boneRenderer, animator);
|
|
}
|
|
if (GUILayout.Button("본 목록 초기화"))
|
|
{
|
|
ClearBones(boneRenderer);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
if (boneRendererDirty)
|
|
{
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
var renderer = targets[i] as BoneRenderer;
|
|
renderer.ExtractBones();
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<Transform> GetAvailableHumanoidBones(Animator animator)
|
|
{
|
|
List<Transform> humanoidBones = new List<Transform>();
|
|
|
|
foreach (HumanBodyBones boneType in HumanoidBoneTypes)
|
|
{
|
|
Transform bone = animator.GetBoneTransform(boneType);
|
|
if (bone != null)
|
|
{
|
|
humanoidBones.Add(bone);
|
|
}
|
|
}
|
|
|
|
return humanoidBones;
|
|
}
|
|
|
|
private void AddHumanoidBones(BoneRenderer boneRenderer, Animator animator)
|
|
{
|
|
Undo.RecordObject(boneRenderer, "Add Humanoid Bones");
|
|
|
|
List<Transform> humanoidBones = GetAvailableHumanoidBones(animator);
|
|
boneRenderer.transforms = humanoidBones.ToArray();
|
|
|
|
EditorUtility.SetDirty(boneRenderer);
|
|
Debug.Log($"{humanoidBones.Count}개의 휴머노이드 본이 BoneRenderer에 추가되었습니다.");
|
|
}
|
|
|
|
private void ClearBones(BoneRenderer boneRenderer)
|
|
{
|
|
Undo.RecordObject(boneRenderer, "Clear Bones");
|
|
|
|
boneRenderer.transforms = new Transform[0];
|
|
|
|
EditorUtility.SetDirty(boneRenderer);
|
|
Debug.Log("BoneRenderer의 본 목록이 초기화되었습니다.");
|
|
}
|
|
}
|
|
} |