288 lines
9.4 KiB
C#
288 lines
9.4 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.IO;
|
|
|
|
public class MaterialAndTextureMover : EditorWindow
|
|
{
|
|
public List<GameObject> targetObjects = new List<GameObject>();
|
|
public string targetFolder = "Assets/";
|
|
private List<Material> foundMaterials = new List<Material>();
|
|
private List<bool> materialSelectionStatus = new List<bool>();
|
|
private List<Texture> foundTextures = new List<Texture>();
|
|
private List<bool> textureSelectionStatus = new List<bool>();
|
|
private bool materialsSearched = false;
|
|
|
|
private Vector2 scrollPos;
|
|
|
|
[MenuItem("Tools/Material and Texture Mover")]
|
|
public static void ShowWindow()
|
|
{
|
|
GetWindow<MaterialAndTextureMover>("Material & Texture Mover");
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.Label("Step 1: Select Target Objects and Search Materials and Textures", EditorStyles.boldLabel);
|
|
|
|
int removeIndex = -1;
|
|
for (int i = 0; i < targetObjects.Count; i++)
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
targetObjects[i] = (GameObject)EditorGUILayout.ObjectField(targetObjects[i], typeof(GameObject), true);
|
|
if (GUILayout.Button("Remove", GUILayout.Width(60)))
|
|
{
|
|
removeIndex = i;
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
|
|
if (removeIndex >= 0)
|
|
{
|
|
targetObjects.RemoveAt(removeIndex);
|
|
}
|
|
|
|
if (GUILayout.Button("Add Target Object"))
|
|
{
|
|
targetObjects.Add(null);
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
|
|
if (GUILayout.Button("Search Materials and Textures"))
|
|
{
|
|
SearchMaterialsAndTextures();
|
|
materialsSearched = true;
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
|
|
if (materialsSearched)
|
|
{
|
|
if (GUILayout.Button("Resolve Duplicated Names"))
|
|
{
|
|
ResolveDuplicatedNames();
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
}
|
|
|
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(300));
|
|
|
|
if (materialsSearched && foundMaterials.Count > 0)
|
|
{
|
|
GUILayout.Label("Remapped Materials", EditorStyles.boldLabel);
|
|
|
|
for (int i = 0; i < foundMaterials.Count; i++)
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
materialSelectionStatus[i] = EditorGUILayout.ToggleLeft(foundMaterials[i] ? foundMaterials[i].name : "None", materialSelectionStatus[i], GUILayout.Width(200));
|
|
if (foundMaterials[i] != null && GUILayout.Button("Ping", GUILayout.Width(50)))
|
|
{
|
|
EditorGUIUtility.PingObject(foundMaterials[i]);
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
|
|
if (materialsSearched && foundTextures.Count > 0)
|
|
{
|
|
GUILayout.Label("Remapped Textures", EditorStyles.boldLabel);
|
|
|
|
for (int i = 0; i < foundTextures.Count; i++)
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
textureSelectionStatus[i] = EditorGUILayout.ToggleLeft(foundTextures[i] ? foundTextures[i].name : "None", textureSelectionStatus[i], GUILayout.Width(200));
|
|
if (foundTextures[i] != null && GUILayout.Button("Ping", GUILayout.Width(50)))
|
|
{
|
|
EditorGUIUtility.PingObject(foundTextures[i]);
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
GUILayout.Space(20);
|
|
GUILayout.Label("Step 2: Select Target Folder and Move Materials and Textures", EditorStyles.boldLabel);
|
|
|
|
GUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("Folder Path:", targetFolder);
|
|
if (GUILayout.Button("Select Folder", GUILayout.Width(100)))
|
|
{
|
|
string selectedPath = EditorUtility.OpenFolderPanel("Select Target Folder", "Assets/", "");
|
|
if (!string.IsNullOrEmpty(selectedPath))
|
|
{
|
|
if (selectedPath.StartsWith(Application.dataPath))
|
|
{
|
|
targetFolder = "Assets" + selectedPath.Substring(Application.dataPath.Length);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Please select a folder within the Assets directory.");
|
|
}
|
|
}
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
|
|
GUILayout.Space(10);
|
|
|
|
if (GUILayout.Button("Move Materials and Textures"))
|
|
{
|
|
MoveMaterialsAndTextures();
|
|
}
|
|
}
|
|
|
|
private void SearchMaterialsAndTextures()
|
|
{
|
|
foundMaterials.Clear();
|
|
materialSelectionStatus.Clear();
|
|
foundTextures.Clear();
|
|
textureSelectionStatus.Clear();
|
|
|
|
foreach (var obj in targetObjects)
|
|
{
|
|
if (obj == null) continue;
|
|
|
|
Renderer[] renderers = obj.GetComponentsInChildren<Renderer>();
|
|
foreach (var renderer in renderers)
|
|
{
|
|
foreach (var mat in renderer.sharedMaterials)
|
|
{
|
|
if (mat != null && !foundMaterials.Contains(mat))
|
|
{
|
|
foundMaterials.Add(mat);
|
|
materialSelectionStatus.Add(true);
|
|
|
|
// 모든 텍스처 검색
|
|
Shader shader = mat.shader;
|
|
for (int j = 0; j < ShaderUtil.GetPropertyCount(shader); j++)
|
|
{
|
|
if (ShaderUtil.GetPropertyType(shader, j) == ShaderUtil.ShaderPropertyType.TexEnv)
|
|
{
|
|
string propertyName = ShaderUtil.GetPropertyName(shader, j);
|
|
Texture texture = mat.GetTexture(propertyName);
|
|
if (texture != null && !foundTextures.Contains(texture))
|
|
{
|
|
foundTextures.Add(texture);
|
|
textureSelectionStatus.Add(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 사용자 정의 속성 직접 검색
|
|
foreach (string propertyName in mat.GetTexturePropertyNames())
|
|
{
|
|
Texture texture = mat.GetTexture(propertyName);
|
|
if (texture != null && !foundTextures.Contains(texture))
|
|
{
|
|
foundTextures.Add(texture);
|
|
textureSelectionStatus.Add(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Debug.Log("Materials and Textures found and listed.");
|
|
}
|
|
|
|
|
|
private void ResolveDuplicatedNames()
|
|
{
|
|
HashSet<string> usedNames = new HashSet<string>();
|
|
|
|
for (int i = 0; i < foundMaterials.Count; i++)
|
|
{
|
|
Material mat = foundMaterials[i];
|
|
string originalName = mat.name;
|
|
int counter = 1;
|
|
|
|
while (usedNames.Contains(mat.name))
|
|
{
|
|
mat.name = $"{originalName}_{counter}";
|
|
counter++;
|
|
}
|
|
|
|
usedNames.Add(mat.name);
|
|
}
|
|
|
|
for (int i = 0; i < foundTextures.Count; i++)
|
|
{
|
|
Texture tex = foundTextures[i];
|
|
string originalName = tex.name;
|
|
int counter = 1;
|
|
|
|
while (usedNames.Contains(tex.name))
|
|
{
|
|
tex.name = $"{originalName}_{counter}";
|
|
counter++;
|
|
}
|
|
|
|
usedNames.Add(tex.name);
|
|
}
|
|
|
|
Debug.Log("Duplicated names resolved.");
|
|
}
|
|
|
|
private void MoveMaterialsAndTextures()
|
|
{
|
|
if (!AssetDatabase.IsValidFolder(targetFolder))
|
|
{
|
|
Debug.LogError("Target folder does not exist or is invalid.");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < foundMaterials.Count; i++)
|
|
{
|
|
if (!materialSelectionStatus[i]) continue;
|
|
|
|
Material mat = foundMaterials[i];
|
|
string path = AssetDatabase.GetAssetPath(mat);
|
|
string targetPath = Path.Combine(targetFolder, Path.GetFileName(path));
|
|
|
|
if (AssetDatabase.LoadAssetAtPath<Material>(targetPath) != null)
|
|
{
|
|
Debug.LogWarning($"Material '{mat.name}' already exists in the target folder. Skipping.");
|
|
continue;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
string uniquePath = AssetDatabase.GenerateUniqueAssetPath(targetPath);
|
|
AssetDatabase.MoveAsset(path, uniquePath);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < foundTextures.Count; i++)
|
|
{
|
|
if (!textureSelectionStatus[i]) continue;
|
|
|
|
Texture tex = foundTextures[i];
|
|
string path = AssetDatabase.GetAssetPath(tex);
|
|
string targetPath = Path.Combine(targetFolder, Path.GetFileName(path));
|
|
|
|
if (AssetDatabase.LoadAssetAtPath<Texture>(targetPath) != null)
|
|
{
|
|
Debug.LogWarning($"Texture '{tex.name}' already exists in the target folder. Skipping.");
|
|
continue;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
string uniquePath = AssetDatabase.GenerateUniqueAssetPath(targetPath);
|
|
AssetDatabase.MoveAsset(path, uniquePath);
|
|
}
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log("Selected materials and textures moved successfully.");
|
|
}
|
|
}
|