using AlicizaX; using AlicizaX.ObjectPool; using System; using System.Collections.Generic; using System.IO; using System.Text; using UnityEditor; using UnityEngine; namespace AlicizaX.Editor { [CustomEditor(typeof(ObjectPoolComponent))] internal sealed class ObjectPoolComponentInspector : GameFrameworkInspector { private readonly HashSet m_OpenedItems = new HashSet(); private ObjectPoolBase[] m_ObjectPools = new ObjectPoolBase[1]; private ObjectInfo[] m_ObjectInfos = new ObjectInfo[1]; public override void OnInspectorGUI() { base.OnInspectorGUI(); if (!EditorApplication.isPlaying) { EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); return; } ObjectPoolComponent t = (ObjectPoolComponent)target; if (IsPrefabInHierarchy(t.gameObject)) { EditorGUILayout.LabelField("Object Pool Count", t.Count.ToString()); int objectPoolCount = EnsureObjectPoolBuffer(t.Count); objectPoolCount = t.GetAllObjectPools(true, m_ObjectPools); for (int i = 0; i < objectPoolCount; i++) { DrawObjectPool(m_ObjectPools[i]); } } Repaint(); } private void DrawObjectPool(ObjectPoolBase objectPool) { bool lastState = m_OpenedItems.Contains(objectPool.FullName); bool currentState = EditorGUILayout.Foldout(lastState, objectPool.FullName); if (currentState != lastState) { if (currentState) { m_OpenedItems.Add(objectPool.FullName); } else { m_OpenedItems.Remove(objectPool.FullName); } } if (currentState) { EditorGUILayout.BeginVertical("box"); { EditorGUILayout.LabelField("Name", objectPool.Name); EditorGUILayout.LabelField("Type", objectPool.ObjectType.FullName); EditorGUILayout.LabelField("Auto Release Interval", objectPool.AutoReleaseInterval.ToString()); EditorGUILayout.LabelField("Capacity", objectPool.Capacity.ToString()); EditorGUILayout.LabelField("Used Count", objectPool.Count.ToString()); EditorGUILayout.LabelField("Expire Time", objectPool.ExpireTime.ToString()); EditorGUILayout.LabelField("Priority", objectPool.Priority.ToString()); int objectInfoCount = EnsureObjectInfoBuffer(objectPool.Count); objectInfoCount = objectPool.GetAllObjectInfos(m_ObjectInfos); if (objectInfoCount > 0) { EditorGUILayout.LabelField("Name", objectPool.AllowMultiSpawn ? "Locked\tCount\tFlag\tLast Use Time" : "Locked\tIn Use\tFlag\tLast Use Time"); for (int i = 0; i < objectInfoCount; i++) { ObjectInfo objectInfo = m_ObjectInfos[i]; #if UNITY_6000_0_OR_NEWER string lastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime); EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "" : objectInfo.Name, objectPool.AllowMultiSpawn ? Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, lastUse) : Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, lastUse)); #else string lastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime); EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "" : objectInfo.Name, objectPool.AllowMultiSpawn ? Utility.Text.Format("{0}\t{1}\t{2}\t{3}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, lastUse) : Utility.Text.Format("{0}\t{1}\t{2}\t{3}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, lastUse)); #endif } if (GUILayout.Button("Release")) { objectPool.Release(); } if (GUILayout.Button("Release All Unused")) { objectPool.ReleaseAllUnused(); } if (GUILayout.Button("Export CSV Data")) { string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Object Pool Data - {0}.csv", objectPool.Name), string.Empty); if (!string.IsNullOrEmpty(exportFileName)) { try { int index = 0; string[] data = new string[objectInfoCount + 1]; data[index++] = Utility.Text.Format("Name,Locked,{0},Custom Can Release Flag,Last Use Time", objectPool.AllowMultiSpawn ? "Count" : "In Use"); for (int i = 0; i < objectInfoCount; i++) { ObjectInfo objectInfo = m_ObjectInfos[i]; string csvLastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime); data[index++] = objectPool.AllowMultiSpawn ? Utility.Text.Format("{0},{1},{2},{3},{4}", objectInfo.Name, objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, csvLastUse) : Utility.Text.Format("{0},{1},{2},{3},{4}", objectInfo.Name, objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, csvLastUse); } File.WriteAllLines(exportFileName, data, Encoding.UTF8); Debug.Log(Utility.Text.Format("Export object pool CSV data to '{0}' success.", exportFileName)); } catch (Exception exception) { Debug.LogError(Utility.Text.Format("Export object pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); } } } } else { GUILayout.Label("Object Pool is Empty ..."); } } EditorGUILayout.EndVertical(); EditorGUILayout.Separator(); } } private int EnsureObjectPoolBuffer(int count) { if (count <= 0) return 0; if (m_ObjectPools == null || m_ObjectPools.Length < count) m_ObjectPools = new ObjectPoolBase[count]; return count; } private int EnsureObjectInfoBuffer(int count) { if (count <= 0) return 0; if (m_ObjectInfos == null || m_ObjectInfos.Length < count) m_ObjectInfos = new ObjectInfo[count]; return count; } } }