235 lines
8.4 KiB
C#
235 lines
8.4 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.Linq;
|
|
using VRM; // VRMライブラリの名前空間を確認してください。これが正しいかどうかによっては変更が必要です。
|
|
|
|
public class VRMSpringBoneMoveTool : EditorWindow
|
|
{
|
|
GameObject sourcePrefab;
|
|
GameObject destinationPrefab;
|
|
|
|
//[MenuItem("Tools/Transfer VRM Spring Bones")]
|
|
static void ShowWindow()
|
|
{
|
|
GetWindow<VRMSpringBoneMoveTool>("VRM Spring Bone Move Tool");
|
|
}
|
|
|
|
void OnGUI()
|
|
{
|
|
GUILayout.Label("Transfer VRM Spring Bone Components", EditorStyles.boldLabel);
|
|
|
|
sourcePrefab = EditorGUILayout.ObjectField("Source Prefab", sourcePrefab, typeof(GameObject), true) as GameObject;
|
|
destinationPrefab = EditorGUILayout.ObjectField("Destination Prefab", destinationPrefab, typeof(GameObject), true) as GameObject;
|
|
|
|
if (GUILayout.Button("Transfer"))
|
|
{
|
|
if (sourcePrefab == null || destinationPrefab == null)
|
|
{
|
|
EditorUtility.DisplayDialog("Error", "Source and Destination Prefabs must be set.", "OK");
|
|
return;
|
|
}
|
|
|
|
TransferVRMSpringBone();
|
|
}
|
|
}
|
|
|
|
void TransferVRMSpringBone()
|
|
{
|
|
if (!EditorUtility.DisplayDialog("확인", "대상 프리팹의 모든 VRMSpringBone이 삭제됩니다. 계속하시겠습니까?", "예", "아니오"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Secondary 오브젝트 찾기 또는 생성
|
|
Transform destSecondary = destinationPrefab.transform.Find("Secondary");
|
|
if (destSecondary == null)
|
|
{
|
|
GameObject secondaryObj = new GameObject("Secondary");
|
|
secondaryObj.transform.SetParent(destinationPrefab.transform, false);
|
|
destSecondary = secondaryObj.transform;
|
|
Debug.Log("Secondary 오브젝트가 생성되었습니다.");
|
|
}
|
|
|
|
// 기존 VRMSpringBone 컴포넌트 제거
|
|
var existingBones = destinationPrefab.GetComponentsInChildren<VRMSpringBone>(true);
|
|
foreach (var bone in existingBones)
|
|
{
|
|
DestroyImmediate(bone);
|
|
}
|
|
|
|
int successCount = 0;
|
|
int failCount = 0;
|
|
|
|
// 소스의 VRMSpringBone 컴포넌트 복사
|
|
var springBones = sourcePrefab.GetComponentsInChildren<VRMSpringBone>(true);
|
|
foreach (var springBone in springBones)
|
|
{
|
|
try
|
|
{
|
|
// Secondary 오브젝트에 새로운 VRMSpringBone 컴포넌트 추가
|
|
VRMSpringBone newSpringBone = destSecondary.gameObject.AddComponent<VRMSpringBone>();
|
|
if (CopyVRMSpringBoneComponents(springBone, newSpringBone))
|
|
{
|
|
successCount++;
|
|
}
|
|
else
|
|
{
|
|
DestroyImmediate(newSpringBone);
|
|
failCount++;
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
Debug.LogError($"스프링본 복사 중 오류 발생: {e.Message}");
|
|
failCount++;
|
|
}
|
|
}
|
|
|
|
if (successCount > 0)
|
|
{
|
|
EditorUtility.SetDirty(destinationPrefab);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
EditorUtility.DisplayDialog("작업 완료",
|
|
$"성공: {successCount}개\n실패: {failCount}개", "확인");
|
|
}
|
|
|
|
bool CopyVRMSpringBoneComponents(VRMSpringBone original, VRMSpringBone copy)
|
|
{
|
|
try
|
|
{
|
|
// 기본 속성 복사
|
|
copy.m_comment = original.m_comment;
|
|
copy.m_stiffnessForce = original.m_stiffnessForce;
|
|
copy.m_gravityPower = original.m_gravityPower;
|
|
copy.m_gravityDir = original.m_gravityDir;
|
|
copy.m_dragForce = original.m_dragForce;
|
|
copy.m_hitRadius = original.m_hitRadius;
|
|
copy.m_updateType = original.m_updateType;
|
|
|
|
// Center 본 찾기 및 설정
|
|
if (original.m_center != null)
|
|
{
|
|
copy.m_center = FindCorrespondingTransform(original.m_center, destinationPrefab.transform);
|
|
if (copy.m_center == null)
|
|
{
|
|
Debug.LogError($"Center 본을 찾을 수 없습니다: {original.m_center.name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Root 본들 찾기 및 설정
|
|
List<Transform> newRootBones = new List<Transform>();
|
|
foreach (var rootBone in original.RootBones)
|
|
{
|
|
if (rootBone == null) continue;
|
|
|
|
var correspondingBone = FindCorrespondingTransform(rootBone, destinationPrefab.transform);
|
|
if (correspondingBone != null)
|
|
{
|
|
newRootBones.Add(correspondingBone);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError($"Root 본을 찾을 수 없습니다: {rootBone.name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (newRootBones.Count == 0)
|
|
{
|
|
Debug.LogError("Root 본이 하나도 설정되지 않았습니다.");
|
|
return false;
|
|
}
|
|
copy.RootBones = newRootBones;
|
|
|
|
// Collider Groups 찾기 및 설정
|
|
if (original.ColliderGroups != null && original.ColliderGroups.Length > 0)
|
|
{
|
|
List<VRMSpringBoneColliderGroup> newColliderGroups = new List<VRMSpringBoneColliderGroup>();
|
|
foreach (var colliderGroup in original.ColliderGroups)
|
|
{
|
|
if (colliderGroup == null) continue;
|
|
|
|
var correspondingCollider = FindCorrespondingColliderGroup(colliderGroup, destinationPrefab.transform);
|
|
if (correspondingCollider != null)
|
|
{
|
|
newColliderGroups.Add(correspondingCollider);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"Collider Group을 찾을 수 없습니다: {colliderGroup.name}");
|
|
}
|
|
}
|
|
copy.ColliderGroups = newColliderGroups.ToArray();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
Debug.LogError($"컴포넌트 복사 중 오류 발생: {e.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Transform FindCorrespondingTransform(Transform original, Transform searchRoot)
|
|
{
|
|
if (original == null) return null;
|
|
|
|
// 먼저 전체 경로로 시도
|
|
var path = GetTransformPath(original, sourcePrefab.transform);
|
|
var result = searchRoot.Find(path);
|
|
|
|
// 경로로 찾지 못한 경우 이름으로 재시도
|
|
if (result == null)
|
|
{
|
|
// 대상 프리팹에서 같은 이름을 가진 모든 Transform을 찾음
|
|
var allTransforms = searchRoot.GetComponentsInChildren<Transform>(true);
|
|
result = allTransforms.FirstOrDefault(t => t.name == original.name);
|
|
|
|
if (result != null)
|
|
{
|
|
Debug.Log($"이름으로 매칭된 본 찾음: {original.name}");
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
string GetTransformPath(Transform current, Transform root)
|
|
{
|
|
if (current == root)
|
|
{
|
|
return ""; // ルートに到達したら終了
|
|
}
|
|
var path = current.name;
|
|
while (current.parent != null && current.parent != root)
|
|
{
|
|
current = current.parent;
|
|
path = current.name + "/" + path; // 親の名前をパスに追加
|
|
}
|
|
return path;
|
|
}
|
|
|
|
VRMSpringBoneColliderGroup FindCorrespondingColliderGroup(VRMSpringBoneColliderGroup original, Transform searchRoot)
|
|
{
|
|
if (original == null)
|
|
{
|
|
return null;
|
|
}
|
|
var path = GetTransformPath(original.transform, sourcePrefab.transform);
|
|
var correspondingTransform = searchRoot.Find(path);
|
|
return correspondingTransform != null ? correspondingTransform.GetComponent<VRMSpringBoneColliderGroup>() : null;
|
|
}
|
|
|
|
void SetTransform(Transform newTransform, Transform originalTransform)
|
|
{
|
|
newTransform.localPosition = originalTransform.localPosition;
|
|
newTransform.localRotation = originalTransform.localRotation;
|
|
newTransform.localScale = originalTransform.localScale;
|
|
}
|
|
}
|