Streamingle_URP/Assets/Scripts/Editor/BoneTools/BoneRendererContextMenu.cs

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의 본 목록이 초기화되었습니다.");
}
}
}