Add : 이름 변경 툴 추가
This commit is contained in:
parent
0abf6970d4
commit
caa8ab8dbd
315
Assets/Scripts/Editor/HumanBoneNameCopier.cs
Normal file
315
Assets/Scripts/Editor/HumanBoneNameCopier.cs
Normal file
@ -0,0 +1,315 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class HumanBoneNameCopier : EditorWindow
|
||||
{
|
||||
private GameObject sourceAvatar;
|
||||
private GameObject targetAvatar;
|
||||
private Vector2 scrollPosition;
|
||||
private bool showAdvancedOptions = false;
|
||||
private bool copyAllBones = true;
|
||||
private Dictionary<HumanBodyBones, bool> boneSelection = new Dictionary<HumanBodyBones, bool>();
|
||||
|
||||
[MenuItem("Tools/Human Bone Name Copier")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<HumanBoneNameCopier>("Human Bone Name Copier");
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
InitializeBoneSelection();
|
||||
}
|
||||
|
||||
private void InitializeBoneSelection()
|
||||
{
|
||||
boneSelection.Clear();
|
||||
foreach (HumanBodyBones bone in System.Enum.GetValues(typeof(HumanBodyBones)))
|
||||
{
|
||||
if (bone != HumanBodyBones.LastBone)
|
||||
{
|
||||
boneSelection[bone] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Label("Human Bone Name Copier", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 소스 아바타 선택
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Source Avatar:", GUILayout.Width(100));
|
||||
sourceAvatar = (GameObject)EditorGUILayout.ObjectField(sourceAvatar, typeof(GameObject), true);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// 타겟 아바타 선택
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Target Avatar:", GUILayout.Width(100));
|
||||
targetAvatar = (GameObject)EditorGUILayout.ObjectField(targetAvatar, typeof(GameObject), true);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 고급 옵션 토글
|
||||
showAdvancedOptions = EditorGUILayout.Foldout(showAdvancedOptions, "Advanced Options");
|
||||
|
||||
if (showAdvancedOptions)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
copyAllBones = EditorGUILayout.Toggle("Copy All Bones", copyAllBones);
|
||||
|
||||
if (!copyAllBones)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Label("Select Bones to Copy:", EditorStyles.boldLabel);
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(200));
|
||||
|
||||
foreach (var bone in boneSelection)
|
||||
{
|
||||
boneSelection[bone.Key] = EditorGUILayout.Toggle(bone.Key.ToString(), bone.Value);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 정보 표시
|
||||
if (sourceAvatar != null)
|
||||
{
|
||||
var sourceAnimator = sourceAvatar.GetComponent<Animator>();
|
||||
if (sourceAnimator != null && sourceAnimator.avatar != null)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"Source Avatar: {sourceAvatar.name}\n" +
|
||||
$"Human Bone Count: {GetHumanBoneCount(sourceAnimator)}",
|
||||
MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetAvatar != null)
|
||||
{
|
||||
var targetAnimator = targetAvatar.GetComponent<Animator>();
|
||||
if (targetAnimator != null && targetAnimator.avatar != null)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"Target Avatar: {targetAvatar.name}\n" +
|
||||
$"Human Bone Count: {GetHumanBoneCount(targetAnimator)}",
|
||||
MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 버튼들
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUI.enabled = sourceAvatar != null && targetAvatar != null;
|
||||
|
||||
if (GUILayout.Button("Copy Bone Names"))
|
||||
{
|
||||
CopyBoneNames();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Preview Changes"))
|
||||
{
|
||||
PreviewChanges();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 추가 기능 버튼
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUI.enabled = targetAvatar != null;
|
||||
|
||||
if (GUILayout.Button("Add 'zindnick : ' to Non-Human Bones"))
|
||||
{
|
||||
AddPrefixToNonHumanBones();
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Clear Selection"))
|
||||
{
|
||||
sourceAvatar = null;
|
||||
targetAvatar = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetHumanBoneCount(Animator animator)
|
||||
{
|
||||
if (animator == null || animator.avatar == null) return 0;
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < (int)HumanBodyBones.LastBone; i++)
|
||||
{
|
||||
if (animator.GetBoneTransform((HumanBodyBones)i) != null)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void CopyBoneNames()
|
||||
{
|
||||
if (sourceAvatar == null || targetAvatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select both source and target avatars.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceAnimator = sourceAvatar.GetComponent<Animator>();
|
||||
var targetAnimator = targetAvatar.GetComponent<Animator>();
|
||||
|
||||
if (sourceAnimator == null || sourceAnimator.avatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Source avatar must have an Animator component with a valid Avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetAnimator == null || targetAnimator.avatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Target avatar must have an Animator component with a valid Avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.RecordObject(targetAvatar, "Copy Human Bone Names");
|
||||
|
||||
int copiedCount = 0;
|
||||
|
||||
for (int i = 0; i < (int)HumanBodyBones.LastBone; i++)
|
||||
{
|
||||
HumanBodyBones bone = (HumanBodyBones)i;
|
||||
|
||||
if (!copyAllBones && boneSelection.ContainsKey(bone) && !boneSelection[bone])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Transform sourceBone = sourceAnimator.GetBoneTransform(bone);
|
||||
Transform targetBone = targetAnimator.GetBoneTransform(bone);
|
||||
|
||||
if (sourceBone != null && targetBone != null)
|
||||
{
|
||||
targetBone.name = sourceBone.name;
|
||||
copiedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(targetAvatar);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
EditorUtility.DisplayDialog("Success",
|
||||
$"Successfully copied {copiedCount} bone names from {this.sourceAvatar.name} to {this.targetAvatar.name}.",
|
||||
"OK");
|
||||
}
|
||||
|
||||
private void PreviewChanges()
|
||||
{
|
||||
if (sourceAvatar == null || targetAvatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select both source and target avatars.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceAnimator = sourceAvatar.GetComponent<Animator>();
|
||||
var targetAnimator = targetAvatar.GetComponent<Animator>();
|
||||
|
||||
if (sourceAnimator == null || sourceAnimator.avatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Source avatar must have an Animator component with a valid Avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetAnimator == null || targetAnimator.avatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Target avatar must have an Animator component with a valid Avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
string previewText = "Preview of bone name changes:\n\n";
|
||||
|
||||
for (int i = 0; i < (int)HumanBodyBones.LastBone; i++)
|
||||
{
|
||||
HumanBodyBones bone = (HumanBodyBones)i;
|
||||
|
||||
if (!copyAllBones && boneSelection.ContainsKey(bone) && !boneSelection[bone])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Transform sourceBone = sourceAnimator.GetBoneTransform(bone);
|
||||
Transform targetBone = targetAnimator.GetBoneTransform(bone);
|
||||
|
||||
if (sourceBone != null && targetBone != null)
|
||||
{
|
||||
previewText += $"{bone}: {targetBone.name} → {sourceBone.name}\n";
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.DisplayDialog("Preview", previewText, "OK");
|
||||
}
|
||||
|
||||
private void AddPrefixToNonHumanBones()
|
||||
{
|
||||
if (targetAvatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select a target avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetAnimator = targetAvatar.GetComponent<Animator>();
|
||||
|
||||
if (targetAnimator == null || targetAnimator.avatar == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Target avatar must have an Animator component with a valid Avatar.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// 휴먼본 목록 수집
|
||||
HashSet<Transform> humanBones = new HashSet<Transform>();
|
||||
for (int i = 0; i < (int)HumanBodyBones.LastBone; i++)
|
||||
{
|
||||
Transform humanBone = targetAnimator.GetBoneTransform((HumanBodyBones)i);
|
||||
if (humanBone != null)
|
||||
{
|
||||
humanBones.Add(humanBone);
|
||||
}
|
||||
}
|
||||
|
||||
Undo.RecordObject(targetAvatar, "Add Prefix to Non-Human Bones");
|
||||
|
||||
int modifiedCount = 0;
|
||||
Transform[] allTransforms = targetAvatar.GetComponentsInChildren<Transform>();
|
||||
|
||||
foreach (Transform transform in allTransforms)
|
||||
{
|
||||
// 휴먼본이 아니고, 이미 접두사가 없는 경우에만 추가
|
||||
if (!humanBones.Contains(transform) && !transform.name.StartsWith("zindnick : "))
|
||||
{
|
||||
transform.name = "zindnick : " + transform.name;
|
||||
modifiedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(targetAvatar);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
EditorUtility.DisplayDialog("Success",
|
||||
$"Successfully added 'zindnick : ' prefix to {modifiedCount} non-human bones in {targetAvatar.name}.",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Editor/HumanBoneNameCopier.cs.meta
Normal file
2
Assets/Scripts/Editor/HumanBoneNameCopier.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f15a4073776b12498e7afd36311f380
|
||||
Loading…
x
Reference in New Issue
Block a user