228 lines
8.4 KiB
C#
228 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Editor.Utilities
|
|
{
|
|
public class BatchComponentAdder : EditorWindow
|
|
{
|
|
private Vector2 scrollPosition;
|
|
private List<GameObject> selectedPrefabs = new List<GameObject>();
|
|
private string searchText = "";
|
|
private List<Type> availableComponentTypes = new List<Type>();
|
|
private List<Type> filteredComponentTypes = new List<Type>();
|
|
private int selectedComponentIndex = -1;
|
|
private bool showScriptsOnly = true;
|
|
private bool showBuiltInComponents = false;
|
|
|
|
[MenuItem("Tools/Batch Component Adder")]
|
|
public static void ShowWindow()
|
|
{
|
|
GetWindow<BatchComponentAdder>("Batch Component Adder");
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
// Get all component types when the window is opened
|
|
RefreshComponentTypes();
|
|
}
|
|
|
|
private void RefreshComponentTypes()
|
|
{
|
|
// Get all types that derive from Component
|
|
availableComponentTypes = AppDomain.CurrentDomain.GetAssemblies()
|
|
.SelectMany(assembly => assembly.GetTypes())
|
|
.Where(type => type.IsSubclassOf(typeof(Component)) && !type.IsAbstract)
|
|
.OrderBy(type => type.Name)
|
|
.ToList();
|
|
|
|
// Apply initial filtering
|
|
FilterComponentTypes();
|
|
}
|
|
|
|
private void FilterComponentTypes()
|
|
{
|
|
filteredComponentTypes = availableComponentTypes
|
|
.Where(type => {
|
|
if (!showBuiltInComponents && type.Namespace != null && type.Namespace.StartsWith("UnityEngine"))
|
|
return false;
|
|
|
|
if (showScriptsOnly && type.Namespace != null && type.Namespace.StartsWith("UnityEngine"))
|
|
return false;
|
|
|
|
if (!string.IsNullOrEmpty(searchText))
|
|
return type.Name.ToLower().Contains(searchText.ToLower());
|
|
|
|
return true;
|
|
})
|
|
.ToList();
|
|
|
|
// Reset selection if it's no longer valid
|
|
if (selectedComponentIndex >= filteredComponentTypes.Count)
|
|
selectedComponentIndex = -1;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
EditorGUILayout.BeginVertical();
|
|
|
|
EditorGUILayout.LabelField("Batch Component Adder", EditorStyles.boldLabel);
|
|
EditorGUILayout.HelpBox("Select multiple prefabs, choose a component type, and add it to the root of all selected prefabs.", MessageType.Info);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
// Prefab selection section
|
|
EditorGUILayout.LabelField("Selected Prefabs", EditorStyles.boldLabel);
|
|
|
|
if (GUILayout.Button("Add Selected Assets"))
|
|
{
|
|
AddSelectedAssets();
|
|
}
|
|
|
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(150));
|
|
|
|
for (int i = 0; i < selectedPrefabs.Count; i++)
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
selectedPrefabs[i] = (GameObject)EditorGUILayout.ObjectField(selectedPrefabs[i], typeof(GameObject), false);
|
|
|
|
if (GUILayout.Button("X", GUILayout.Width(20)))
|
|
{
|
|
selectedPrefabs.RemoveAt(i);
|
|
i--;
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
if (GUILayout.Button("Clear All"))
|
|
{
|
|
selectedPrefabs.Clear();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
// Component selection section
|
|
EditorGUILayout.LabelField("Component to Add", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
showScriptsOnly = EditorGUILayout.Toggle("Scripts Only", showScriptsOnly);
|
|
showBuiltInComponents = EditorGUILayout.Toggle("Show Built-in Components", showBuiltInComponents);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
string newSearchText = EditorGUILayout.TextField("Search", searchText);
|
|
if (newSearchText != searchText)
|
|
{
|
|
searchText = newSearchText;
|
|
FilterComponentTypes();
|
|
}
|
|
|
|
string[] componentNames = filteredComponentTypes.Select(t => t.Name).ToArray();
|
|
|
|
selectedComponentIndex = EditorGUILayout.Popup("Component Type", selectedComponentIndex, componentNames);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
// Validate and add the component
|
|
GUI.enabled = selectedPrefabs.Count > 0 && selectedComponentIndex >= 0 && selectedComponentIndex < filteredComponentTypes.Count;
|
|
|
|
if (GUILayout.Button("Add Component to Prefabs"))
|
|
{
|
|
AddComponentToPrefabs();
|
|
}
|
|
|
|
GUI.enabled = true;
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private void AddSelectedAssets()
|
|
{
|
|
UnityEngine.Object[] selectedObjects = Selection.objects;
|
|
|
|
foreach (var obj in selectedObjects)
|
|
{
|
|
if (obj is GameObject go)
|
|
{
|
|
string path = AssetDatabase.GetAssetPath(go);
|
|
if (!string.IsNullOrEmpty(path) && path.EndsWith(".prefab"))
|
|
{
|
|
if (!selectedPrefabs.Contains(go))
|
|
{
|
|
selectedPrefabs.Add(go);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddComponentToPrefabs()
|
|
{
|
|
if (selectedComponentIndex < 0 || selectedComponentIndex >= filteredComponentTypes.Count)
|
|
return;
|
|
|
|
Type componentType = filteredComponentTypes[selectedComponentIndex];
|
|
int successCount = 0;
|
|
List<string> failedPrefabs = new List<string>();
|
|
|
|
// For undo operations
|
|
Undo.RecordObjects(selectedPrefabs.ToArray(), "Add Component To Prefabs");
|
|
|
|
foreach (GameObject prefab in selectedPrefabs)
|
|
{
|
|
// Skip null entries
|
|
if (prefab == null) continue;
|
|
|
|
try
|
|
{
|
|
// Open the prefab for editing
|
|
string prefabPath = AssetDatabase.GetAssetPath(prefab);
|
|
GameObject prefabRoot = PrefabUtility.LoadPrefabContents(prefabPath);
|
|
|
|
// Check if the component already exists
|
|
if (prefabRoot.GetComponent(componentType) == null)
|
|
{
|
|
// Add the component
|
|
prefabRoot.AddComponent(componentType);
|
|
|
|
// Save the prefab
|
|
PrefabUtility.SaveAsPrefabAsset(prefabRoot, prefabPath);
|
|
successCount++;
|
|
}
|
|
else
|
|
{
|
|
failedPrefabs.Add($"{prefab.name} (already has component)");
|
|
}
|
|
|
|
// Unload the prefab
|
|
PrefabUtility.UnloadPrefabContents(prefabRoot);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"Error adding component to {prefab.name}: {e.Message}");
|
|
failedPrefabs.Add($"{prefab.name} (error)");
|
|
}
|
|
}
|
|
|
|
// Show results
|
|
if (successCount > 0)
|
|
{
|
|
Debug.Log($"Successfully added {componentType.Name} to {successCount} prefabs.");
|
|
}
|
|
|
|
if (failedPrefabs.Count > 0)
|
|
{
|
|
Debug.LogWarning($"Failed to add component to {failedPrefabs.Count} prefabs: {string.Join(", ", failedPrefabs)}");
|
|
}
|
|
|
|
// Refresh the asset database to show changes
|
|
AssetDatabase.Refresh();
|
|
}
|
|
}
|
|
}
|