350 lines
17 KiB
C#
350 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEditor.Experimental.SceneManagement;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
|
|
public static class EditorUtils {
|
|
|
|
public static void OpenAllScene(Func<float, EditorBuildSettingsScene, GameObject[], bool> editFunc){
|
|
var currentScenePath = EditorSceneManager.GetActiveScene().path;
|
|
var scenes = EditorBuildSettings.scenes.Where(s => s.enabled).ToArray();
|
|
for(int i = 0; i < scenes.Length; ++i){
|
|
var scene = scenes[i];
|
|
EditorSceneManager.OpenScene(scene.path);
|
|
var gameObjectArray = Resources.FindObjectsOfTypeAll<GameObject>().Where(go => string.IsNullOrEmpty(AssetDatabase.GetAssetPath(go)) && go.hideFlags == HideFlags.None).ToArray();
|
|
var isChanged = editFunc((float)i / scenes.Length, scene, gameObjectArray);
|
|
if(isChanged){
|
|
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
|
|
}
|
|
}
|
|
EditorSceneManager.OpenScene(currentScenePath);
|
|
}
|
|
|
|
public static GameObject[] GetAllAssets(){
|
|
var pathArray = AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/")).ToArray();
|
|
return pathArray.Select(a => AssetDatabase.LoadAssetAtPath(a, typeof(GameObject)) as GameObject).Where(a => a != null).ToArray();
|
|
}
|
|
|
|
public static void FindAllPrefabPath(string folderPath, Action<float, string> action){
|
|
var pathArray = Directory.GetFiles(folderPath, "*.prefab");
|
|
for(int i = 0; i < pathArray.Length; ++i){
|
|
action((float)i / pathArray.Length, pathArray[i].Replace(Application.dataPath, "Assets"));
|
|
}
|
|
}
|
|
public static void FindAllChildrensPrefabPath(string folderPath, Action<float, string> action){
|
|
FindAllPrefabPath(folderPath, action);
|
|
foreach(var childPath in Directory.GetDirectories(folderPath)){
|
|
FindAllChildrensPrefabPath(childPath, action);
|
|
}
|
|
}
|
|
|
|
public static void EditPrefab(string folderPath, Func<GameObject, bool> editFunc){
|
|
var prefab = PrefabUtility.LoadPrefabContents(folderPath);
|
|
var isChanged = editFunc(prefab);
|
|
if(isChanged){
|
|
PrefabUtility.SaveAsPrefabAsset(prefab, folderPath);
|
|
}
|
|
PrefabUtility.UnloadPrefabContents(prefab);
|
|
}
|
|
|
|
public static void FindAllChildrensPrefab(Transform transform, Action<Transform> action){
|
|
for(int i = transform.childCount - 1; i >= 0; --i){
|
|
Transform child = transform.GetChild(i);
|
|
if(PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject)){
|
|
action(child);
|
|
}else{
|
|
FindAllChildrensPrefab(child, action);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void SwapPrefab(Transform target, GameObject swapPrefab){
|
|
var to = (UnityEditor.PrefabUtility.InstantiatePrefab(swapPrefab) as GameObject).transform;
|
|
to.parent = target.parent;
|
|
to.localPosition = target.localPosition;
|
|
to.localRotation = target.localRotation;
|
|
to.localScale = target.localScale;
|
|
GameObject.DestroyImmediate(target.gameObject);
|
|
}
|
|
|
|
public static string MigratePrefabToPrefabVariant(GameObject basePrefab, GameObject migrationPrefab){
|
|
var basePath = AssetDatabase.GetAssetPath(basePrefab);
|
|
var path = AssetDatabase.GetAssetPath(migrationPrefab).Replace(".prefab", " Variant.prefab");
|
|
var instance = PrefabUtility.InstantiatePrefab(basePrefab) as GameObject;
|
|
PrefabUtility.SaveAsPrefabAsset(instance, path);
|
|
GameObject.DestroyImmediate(instance);
|
|
|
|
var prefab = PrefabUtility.LoadPrefabContents(path);
|
|
|
|
var result = Migrate(prefab.transform, migrationPrefab.transform);
|
|
if(!result){
|
|
FixField(prefab.transform, migrationPrefab.transform);
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(prefab, path);
|
|
}
|
|
PrefabUtility.UnloadPrefabContents(prefab);
|
|
return path;
|
|
}
|
|
|
|
private static bool Migrate(Transform targetTransform, Transform migrationTransform){
|
|
var targetChildCount = targetTransform.childCount;
|
|
for(int i = 0; i < migrationTransform.childCount; ++i){
|
|
var migrationChild = migrationTransform.GetChild(i);
|
|
Transform targetChild;
|
|
if(i < targetChildCount){
|
|
targetChild = targetTransform.GetChild(i);
|
|
if(migrationChild.name != targetChild.name){
|
|
var containsNameCount = ChildContaintsNameCount(targetTransform, migrationChild.name);
|
|
if(containsNameCount == 0){
|
|
targetChild = GameObject.Instantiate(migrationChild.gameObject, targetTransform).transform;
|
|
targetChild.name = migrationChild.name;
|
|
targetChild.SetSiblingIndex(migrationChild.GetSiblingIndex());
|
|
++targetChildCount;
|
|
}else if(containsNameCount == 1){
|
|
for(int j = 0; j < targetChildCount; ++j){
|
|
if(targetTransform.GetChild(j).name == migrationChild.name){
|
|
targetChild = targetTransform.GetChild(j);
|
|
targetChild.SetSiblingIndex(migrationChild.GetSiblingIndex());
|
|
break;
|
|
}
|
|
}
|
|
}else{
|
|
Debug.LogError("同一階層に同じ名前のオブジェクトがある為中止します。");
|
|
return true;
|
|
}
|
|
}
|
|
}else{
|
|
targetChild = GameObject.Instantiate(migrationChild.gameObject, targetTransform).transform;
|
|
targetChild.name = migrationChild.name;
|
|
++targetChildCount;
|
|
}
|
|
CopyComponents(targetChild, migrationChild);
|
|
var result = Migrate(targetChild, migrationChild);
|
|
if(result){
|
|
return true;
|
|
}
|
|
targetChild.gameObject.SetActive(migrationChild.gameObject.activeSelf);
|
|
}
|
|
for(int i = 0; i < targetChildCount; ++i){
|
|
var toChild = targetTransform.GetChild(i);
|
|
var containsNameCount = ChildContaintsNameCount(migrationTransform, toChild.name);
|
|
if(containsNameCount == 0){
|
|
toChild.gameObject.SetActive(false);
|
|
Debug.LogWarning("Change disable " + toChild.GetPath());
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static void FixField(Transform targetTransform, Transform migrationTransform){
|
|
var targetChildCount = targetTransform.childCount;
|
|
for(int i = 0; i < migrationTransform.childCount; ++i){
|
|
var migrationChild = migrationTransform.GetChild(i);
|
|
var targetChild = targetTransform.GetChild(i);
|
|
if(migrationChild.name != targetChild.name){
|
|
for(int j = 0; j < targetChildCount; ++j){
|
|
if(targetTransform.GetChild(j).name == migrationChild.name){
|
|
targetChild = targetTransform.GetChild(j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
FixField(targetChild, migrationChild);
|
|
ProcessReflection(migrationChild, targetChild, targetTransform);
|
|
migrationChild.FindComponent<ParticleSystem>(fromPS => {
|
|
if(fromPS.subEmitters.enabled){
|
|
var fromSub = fromPS.subEmitters;
|
|
FindChildrensByPath(targetTransform, migrationChild.GetPath(), t => {
|
|
t.FindComponent<ParticleSystem>(toPS => {
|
|
var toSub = toPS.subEmitters;
|
|
for(int index = 0; index < fromSub.subEmittersCount; ++index){
|
|
var fromTarget = fromSub.GetSubEmitterSystem(index);
|
|
FindChildrensByPath(targetTransform, fromTarget.transform.GetPath(), toTarget => {
|
|
toSub.SetSubEmitterSystem(index, toTarget.GetComponent<ParticleSystem>());
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
private static int ChildContaintsNameCount(Transform transform, string name){
|
|
var counter = 0;
|
|
foreach(Transform child in transform){
|
|
if(child.name == name){
|
|
++counter;
|
|
}
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
private static void CopyComponents(Transform to, Transform from){
|
|
var components = from.gameObject.GetComponents<Component>();
|
|
var targetComponents = to.gameObject.GetComponents<Component>();
|
|
var currentComponentCount = new Dictionary<System.Type, int>();
|
|
foreach(var component in components){
|
|
var componentType = component.GetType();
|
|
var componentCount = targetComponents.Count(c => c.GetType() == componentType);
|
|
ComponentUtility.CopyComponent(component);
|
|
if(componentCount == 0){
|
|
ComponentUtility.PasteComponentAsNew(to.gameObject);
|
|
}else if(componentCount == 1){
|
|
var targetComponent = targetComponents.First(c => c.GetType() == componentType);
|
|
ComponentUtility.PasteComponentValues(targetComponent);
|
|
}else{
|
|
if(!currentComponentCount.ContainsKey(componentType)){
|
|
currentComponentCount.Add(componentType, 0);
|
|
}
|
|
var count = currentComponentCount[componentType];
|
|
var targetComponentsWithType = targetComponents.Where(c => c.GetType() == componentType);
|
|
if(count < targetComponentsWithType.Count()){
|
|
var targetComponent = targetComponents.Where(c => c.GetType() == componentType).ElementAt(count);
|
|
currentComponentCount[componentType] += 1;
|
|
ComponentUtility.PasteComponentValues(targetComponent);
|
|
}else{
|
|
ComponentUtility.PasteComponentAsNew(to.gameObject);
|
|
}
|
|
}
|
|
}
|
|
foreach(var component in targetComponents){
|
|
var componentType = component.GetType();
|
|
var componentCount = components.Count(c => c.GetType() == componentType);
|
|
if(componentCount == 0){
|
|
Debug.LogWarning("Deestroy component " + to.GetPath() + " " + componentType);
|
|
GameObject.DestroyImmediate(component);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void ProcessReflection(Transform from, Transform to, Transform parent){
|
|
var fromComponents = from.GetComponents<Component>();
|
|
for(int i = 0; i < fromComponents.Length; ++i){
|
|
var fromType = fromComponents[i].GetType();
|
|
var toComponent = to.GetComponent(fromType);
|
|
if(toComponent == null){
|
|
continue;
|
|
}
|
|
MemberInfo[] members = fromType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
foreach(var m in members){
|
|
if(m.MemberType != MemberTypes.Field){
|
|
continue;
|
|
}
|
|
System.Type fieldType = ((FieldInfo)m).FieldType;
|
|
if(fieldType == typeof(Transform) || fieldType == typeof(GameObject)){
|
|
string targetPath;
|
|
FieldInfo field = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if(fieldType == typeof(Transform)){
|
|
Transform t = (Transform)field.GetValue(fromComponents[i]);
|
|
if(t == null){
|
|
continue;
|
|
}
|
|
targetPath = t.GetPath();
|
|
}else if(fieldType == typeof(GameObject)){
|
|
GameObject obj = (GameObject)field.GetValue(fromComponents[i]);
|
|
if(obj == null){
|
|
continue;
|
|
}
|
|
targetPath = obj.transform.GetPath();
|
|
}else{
|
|
continue;
|
|
}
|
|
FindChildrensByPath(parent, targetPath, targetTransform => {
|
|
FieldInfo setField = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if(setField == null){
|
|
Debug.Log("setField is null " + m.Name);
|
|
}else{
|
|
if(fieldType == typeof(Transform)){
|
|
setField.SetValue(toComponent, targetTransform);
|
|
}else if(fieldType == typeof(GameObject)){
|
|
setField.SetValue(toComponent, targetTransform.gameObject);
|
|
}
|
|
}
|
|
});
|
|
}else if(fieldType == typeof(Transform[])){
|
|
FieldInfo field = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
Transform[] t = (Transform[])field.GetValue(fromComponents[i]);
|
|
if(t == null){
|
|
continue;
|
|
}
|
|
var targetPathArray = new string[t.Length];
|
|
for(int j = 0; j < t.Length; ++j){
|
|
if(t[j] == null){
|
|
targetPathArray[j] = null;
|
|
}else{
|
|
targetPathArray[j] = t[j].GetPath();
|
|
}
|
|
}
|
|
var newTransformArray = new Transform[t.Length];
|
|
for(int j = 0; j < t.Length; ++j){
|
|
if(targetPathArray[j] == null){
|
|
continue;
|
|
}
|
|
FindChildrensByPath(parent, targetPathArray[j], targetTransform => {
|
|
newTransformArray[j] = targetTransform;
|
|
});
|
|
}
|
|
FieldInfo setField = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if(setField == null){
|
|
Debug.Log("setField is null " + m.Name);
|
|
}else{
|
|
setField.SetValue(toComponent, newTransformArray);
|
|
}
|
|
}else if(fieldType == typeof(GameObject[])){
|
|
FieldInfo field = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
GameObject[] t = (GameObject[])field.GetValue(fromComponents[i]);
|
|
if(t == null){
|
|
continue;
|
|
}
|
|
var targetPathArray = new string[t.Length];
|
|
for(int j = 0; j < t.Length; ++j){
|
|
if(t[j] == null){
|
|
targetPathArray[j] = null;
|
|
}else{
|
|
targetPathArray[j] = t[j].transform.GetPath();
|
|
}
|
|
}
|
|
var newArray = new GameObject[t.Length];
|
|
for(int j = 0; j < t.Length; ++j){
|
|
if(targetPathArray[j] == null){
|
|
continue;
|
|
}
|
|
FindChildrensByPath(parent, targetPathArray[j], targetTransform => {
|
|
newArray[j] = targetTransform.gameObject;
|
|
});
|
|
}
|
|
FieldInfo setField = fromType.GetField(m.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if(setField == null){
|
|
Debug.Log("setField is null " + m.Name);
|
|
}else{
|
|
setField.SetValue(toComponent, newArray);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool FindChildrensByPath(Transform t, string path, Action<Transform> callback){
|
|
for(int i = 0; i < t.childCount; ++i){
|
|
Transform child = t.GetChild(i);
|
|
if(child.GetPath().Replace(" Variant", "") == path){
|
|
callback(child);
|
|
return true;
|
|
}
|
|
}
|
|
for(int i = 0; i < t.childCount; ++i){
|
|
Transform child = t.GetChild(i);
|
|
if(FindChildrensByPath(child, path, callback)){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|