2025-06-08 00:55:10 +09:00

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.");
}
}