This commit is contained in:
2025-09-17 18:56:28 +08:00
commit 54c72710a5
5244 changed files with 5717609 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Debug = UnityEngine.Debug;
namespace DestroyIt
{
[CustomEditor(typeof(ObjectPool))]
public class ObjectPoolEditor : Editor
{
private Texture deleteButton;
private Texture lockOff;
private Texture lockOn;
private readonly string[] delimiter = {":|:"}; // The complex delimiter for loading/saving Object Pool to file. Should be something you won't use in your prefab names.
private void OnEnable()
{
deleteButton = Resources.Load("UI_Textures/delete-16x16") as Texture;
lockOff = Resources.Load("UI_Textures/lock-off-16x16") as Texture;
lockOn = Resources.Load("UI_Textures/lock-on-16x16") as Texture;
}
public override void OnInspectorGUI()
{
ObjectPool objectPool = target as ObjectPool;
List<PoolEntry> changeEntries = new List<PoolEntry>();
if (objectPool != null && objectPool.prefabsToPool != null)
changeEntries = objectPool.prefabsToPool.ToList();
List<PoolEntry> removeEntries = new List<PoolEntry>();
GUIStyle style = new GUIStyle();
style.padding.top = 2;
if (changeEntries.Count > 0)
{
EditorGUILayout.LabelField("Prefab | Count | Pooled Only");
List<string> previouslyUsedNames = new List<string>();
foreach(PoolEntry entry in changeEntries)
{
// Remove duplicate entries
if (entry != null && entry.Prefab != null)
{
if (previouslyUsedNames.Contains(entry.Prefab.name))
{
Debug.LogWarning("Prefab \"" + entry.Prefab.name + "\" already exists in Object Pool (item #" + (previouslyUsedNames.IndexOf(entry.Prefab.name) + 1) + ").");
removeEntries.Add(entry);
continue;
}
previouslyUsedNames.Add(entry.Prefab.name);
}
EditorGUILayout.BeginHorizontal();
entry.Prefab = EditorGUILayout.ObjectField(entry.Prefab, typeof(GameObject), false) as GameObject;
entry.Count = EditorGUILayout.IntField(entry.Count, GUILayout.Width(20));
Texture currentLock = lockOff;
if (entry.OnlyPooled)
currentLock = lockOn;
if (GUILayout.Button(currentLock, style, GUILayout.Width(16)))
entry.OnlyPooled = !entry.OnlyPooled;
if (GUILayout.Button(deleteButton, style, GUILayout.Width(16)))
removeEntries.Add(entry); // flag for removal
EditorGUILayout.EndHorizontal();
}
// Remove entries flagged for removal
foreach (PoolEntry entry in removeEntries)
changeEntries.Remove(entry);
}
// Add entries button
EditorGUILayout.Separator();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("+", EditorStyles.toolbarButton, GUILayout.Width(30)))
changeEntries.Add(new PoolEntry{ Prefab = null, Count = 1 });
EditorGUILayout.LabelField(" Add a prefab to the pool.");
EditorGUILayout.EndHorizontal();
EditorGUILayout.Separator();
// Suppress Warnings checkbox
EditorGUILayout.BeginHorizontal();
objectPool.suppressWarnings = EditorGUILayout.Toggle(objectPool.suppressWarnings, GUILayout.Width(16));
EditorGUILayout.LabelField("Suppress Warnings");
EditorGUILayout.EndHorizontal();
EditorGUILayout.Separator();
// IMPORT from file
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Import", EditorStyles.toolbarButton, GUILayout.Width(70)))
{
string path = EditorUtility.OpenFilePanel("Import Object Pool Save File", SceneManager.GetActiveScene().path.SceneFolder(), "txt");
if (path.Length != 0 && File.Exists(path))
{
string[] lines = File.ReadAllLines(path);
if (EditorUtility.DisplayDialog("Add Items to Object Pool?", "Are you sure you want to import " + lines.Length + " items into the Object Pool from " + Path.GetFileName(path) + "?", "Add Items", "Cancel"))
{
int itemsModified = 0;
int itemsAdded = 0;
for (int i = 0; i < lines.Length; i++)
{
string[] parts = lines[i].Split(delimiter, StringSplitOptions.None);
string assetPath = AssetDatabase.GUIDToAssetPath(parts[1]);
GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)) as GameObject;
if (prefab == null)
{
Debug.LogWarning("Could not find \"" + parts[0] + "\" prefab.");
continue;
}
int count = Convert.ToInt32(parts[2]);
bool onlyPooled = Convert.ToBoolean(parts[3]);
PoolEntry existingEntry = changeEntries.Find(x => x.Prefab == prefab);
// Update existing entries
if (existingEntry != null)
{
bool updatedExisting = false;
if (existingEntry.Count < count)
{
existingEntry.Count = count;
updatedExisting = true;
}
if (onlyPooled && !existingEntry.OnlyPooled)
{
existingEntry.OnlyPooled = onlyPooled;
updatedExisting = true;
}
if (updatedExisting)
itemsModified++;
}
else // Add new entries
{
changeEntries.Add(new PoolEntry { Prefab = prefab, Count = count, OnlyPooled = onlyPooled });
itemsAdded++;
}
}
Debug.Log(String.Format("{0} imported into Object Pool. Results: {1} new items added, {2} existing items updated.", Path.GetFileName(path), itemsAdded, itemsModified));
}
}
}
// CLEAR object pool
EditorGUILayout.Space();
if (GUILayout.Button("Clear", EditorStyles.toolbarButton, GUILayout.Width(70)) &&
EditorUtility.DisplayDialog("Clear Object Pool?", "Are you sure you want to remove all objects from the object pool?", "Clear", "Cancel"))
{
changeEntries = new List<PoolEntry>();
Debug.Log("Object Pool cleared.");
}
// SAVE to file
EditorGUILayout.Space();
if (GUILayout.Button("Save", EditorStyles.toolbarButton, GUILayout.Width(70)))
{
string saveFilePath = EditorUtility.SaveFilePanel("Save Object File To", SceneManager.GetActiveScene().path.SceneFolder(), SceneManager.GetActiveScene().name.Replace(" ", "") + "ObjectPool.txt", "txt");
//string saveFilePath = SceneManager.GetActiveScene().path.SceneFolder() + "/ObjectPool-SaveFile.txt"; //"Assets/DestroyIt - Core/ObjectPool-SaveFile.txt";
if (saveFilePath.Length != 0)
{
if (objectPool.prefabsToPool != null && objectPool.prefabsToPool.Count > 0)
{
string[] lines = new string[objectPool.prefabsToPool.Count];
for (int i = 0; i < objectPool.prefabsToPool.Count; i++)
{
string assetPath = AssetDatabase.GetAssetPath(objectPool.prefabsToPool[i].Prefab.GetInstanceID());
string assetId = AssetDatabase.AssetPathToGUID(assetPath);
lines[i] = String.Format("{1}{0}{2}{0}{3}{0}{4}", string.Join("", delimiter), objectPool.prefabsToPool[i].Prefab.name, assetId, objectPool.prefabsToPool[i].Count, objectPool.prefabsToPool[i].OnlyPooled);
}
File.WriteAllLines(saveFilePath, lines);
Debug.Log(lines.Length + " object Pool entries saved to: " + saveFilePath + ".");
}
else
Debug.Log("Object Pool is empty. Nothing to save.");
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Separator();
// Save changes back to object pool
objectPool.prefabsToPool = changeEntries;
if (GUI.changed && !Application.isPlaying)
{
EditorUtility.SetDirty(objectPool);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
}
}
}