Working generic object pooling, pool monitor editor tool and batch component adder editor tool
This commit is contained in:
227
Assets/Editor/Utilities/BatchComponentAdder.cs
Normal file
227
Assets/Editor/Utilities/BatchComponentAdder.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user