Files
test/Assets/Editor/PrefabMoverTool.cs
T
2026-02-10 19:28:15 +07:00

295 lines
10 KiB
C#

using UnityEngine;
using UnityEditor;
using System.IO;
namespace BrewMonster
{
public class PrefabMoverTool : EditorWindow
{
private Object folderRoot;
private string folderRootPath = "";
private string subfolderPath = "";
private Object prefabToMove;
private Vector2 scrollPosition;
private GUIStyle headerStyle;
private GUIStyle boxStyle;
[MenuItem("Tools/Prefab Mover")]
public static void ShowWindow()
{
PrefabMoverTool window = GetWindow<PrefabMoverTool>("Prefab Mover");
window.minSize = new Vector2(400, 300);
window.Show();
}
private void OnEnable()
{
// Initialize styles
InitializeStyles();
}
private void InitializeStyles()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel)
{
fontSize = 14,
alignment = TextAnchor.MiddleLeft,
margin = new RectOffset(5, 5, 10, 10)
};
}
if (boxStyle == null)
{
boxStyle = new GUIStyle(GUI.skin.box)
{
padding = new RectOffset(10, 10, 10, 10),
margin = new RectOffset(5, 5, 5, 5)
};
}
}
private void OnGUI()
{
InitializeStyles();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
// Title
GUILayout.Label("Prefab Mover Tool", headerStyle);
EditorGUILayout.Space(5);
// Folder Root Section
EditorGUILayout.BeginVertical(boxStyle);
{
GUILayout.Label("1. Set Folder Root", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("Drag and drop a folder from the Project window to set the root folder.", MessageType.Info);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Folder Root:", GUILayout.Width(100));
Object newFolderRoot = EditorGUILayout.ObjectField(folderRoot, typeof(Object), false);
if (newFolderRoot != folderRoot)
{
folderRoot = newFolderRoot;
UpdateFolderRootPath();
}
EditorGUILayout.EndHorizontal();
if (!string.IsNullOrEmpty(folderRootPath))
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Path:", GUILayout.Width(100));
EditorGUILayout.SelectableLabel(folderRootPath, EditorStyles.textField, GUILayout.Height(18));
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(5);
// Subfolder Path Section
EditorGUILayout.BeginVertical(boxStyle);
{
GUILayout.Label("2. Set Subfolder Path", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("Enter the subfolder path (e.g., 'a/b' or 'a\\b'). This will be created inside the folder root.", MessageType.Info);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Subfolder Path:", GUILayout.Width(100));
subfolderPath = EditorGUILayout.TextField(subfolderPath);
EditorGUILayout.EndHorizontal();
if (!string.IsNullOrEmpty(folderRootPath) && !string.IsNullOrEmpty(subfolderPath))
{
string fullPath = GetFullTargetPath();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Full Path:", GUILayout.Width(100));
EditorGUILayout.SelectableLabel(fullPath, EditorStyles.textField, GUILayout.Height(18));
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(5);
// Prefab Section
EditorGUILayout.BeginVertical(boxStyle);
{
GUILayout.Label("3. Select Prefab to Move", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("Drag and drop a prefab from the Project window.", MessageType.Info);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Prefab:", GUILayout.Width(100));
prefabToMove = EditorGUILayout.ObjectField(prefabToMove, typeof(GameObject), false);
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(10);
// Move Button
EditorGUI.BeginDisabledGroup(!CanMovePrefab());
{
if (GUILayout.Button("Move Prefab", GUILayout.Height(35)))
{
MovePrefab();
}
}
EditorGUI.EndDisabledGroup();
if (!CanMovePrefab())
{
if (string.IsNullOrEmpty(folderRootPath))
EditorGUILayout.HelpBox("Please set a folder root.", MessageType.Warning);
else if (string.IsNullOrEmpty(subfolderPath))
EditorGUILayout.HelpBox("Please enter a subfolder path.", MessageType.Warning);
else if (prefabToMove == null)
EditorGUILayout.HelpBox("Please select a prefab to move.", MessageType.Warning);
}
EditorGUILayout.EndScrollView();
}
private void UpdateFolderRootPath()
{
if (folderRoot == null)
{
folderRootPath = "";
return;
}
string path = AssetDatabase.GetAssetPath(folderRoot);
// Check if it's a folder
if (Directory.Exists(path))
{
folderRootPath = path;
}
else if (File.Exists(path))
{
// If user dropped a file, use its parent folder
folderRootPath = Path.GetDirectoryName(path);
EditorUtility.DisplayDialog("Info", "You selected a file. Using its parent folder instead.", "OK");
}
else
{
folderRootPath = "";
EditorUtility.DisplayDialog("Error", "Invalid folder selected.", "OK");
}
}
private string GetFullTargetPath()
{
if (string.IsNullOrEmpty(folderRootPath) || string.IsNullOrEmpty(subfolderPath))
return "";
// Normalize the subfolder path (replace backslashes with forward slashes)
string normalizedSubPath = subfolderPath.Replace('\\', '/');
// Combine paths
string fullPath = Path.Combine(folderRootPath, normalizedSubPath);
// Normalize to forward slashes (Unity convention)
return fullPath.Replace('\\', '/');
}
private bool CanMovePrefab()
{
return !string.IsNullOrEmpty(folderRootPath) &&
!string.IsNullOrEmpty(subfolderPath) &&
prefabToMove != null;
}
private void MovePrefab()
{
string prefabPath = AssetDatabase.GetAssetPath(prefabToMove);
if (string.IsNullOrEmpty(prefabPath))
{
EditorUtility.DisplayDialog("Error", "Cannot get prefab path.", "OK");
return;
}
// Get the full target path
string targetFolder = GetFullTargetPath();
// Create the folder structure if it doesn't exist
CreateFolderStructure(targetFolder);
// Get prefab filename
string prefabFileName = Path.GetFileName(prefabPath);
string targetPath = Path.Combine(targetFolder, prefabFileName).Replace('\\', '/');
// Check if file already exists at target
if (File.Exists(targetPath))
{
bool overwrite = EditorUtility.DisplayDialog(
"File Exists",
$"A file with the name '{prefabFileName}' already exists at:\n{targetPath}\n\nDo you want to overwrite it?",
"Overwrite",
"Cancel"
);
if (!overwrite)
{
return;
}
}
// Move the asset
string error = AssetDatabase.MoveAsset(prefabPath, targetPath);
if (string.IsNullOrEmpty(error))
{
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("Success", $"Prefab moved successfully to:\n{targetPath}", "OK");
// Clear the prefab field after successful move
prefabToMove = null;
// Ping the moved asset in the Project window
Object movedAsset = AssetDatabase.LoadAssetAtPath<Object>(targetPath);
EditorGUIUtility.PingObject(movedAsset);
}
else
{
EditorUtility.DisplayDialog("Error", $"Failed to move prefab:\n{error}", "OK");
}
}
private void CreateFolderStructure(string fullPath)
{
// Normalize path
fullPath = fullPath.Replace('\\', '/');
// Split the path into parts
string[] pathParts = fullPath.Split('/');
string currentPath = "";
foreach (string part in pathParts)
{
if (string.IsNullOrEmpty(part))
continue;
string parentPath = currentPath;
currentPath = string.IsNullOrEmpty(currentPath) ? part : currentPath + "/" + part;
// Check if folder exists
if (!Directory.Exists(currentPath))
{
// Create the folder using AssetDatabase
if (!string.IsNullOrEmpty(parentPath))
{
AssetDatabase.CreateFolder(parentPath, part);
Debug.Log($"Created folder: {currentPath}");
}
}
}
AssetDatabase.Refresh();
}
}
}