com.alicizax.unity.framework/Editor/GameObjectPool/GameObjectPoolEditor.cs

181 lines
7.9 KiB
C#

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AlicizaX
{
[CustomEditor(typeof(GameObjectPoolManager))]
public sealed class GameObjectPoolEditor : UnityEditor.Editor
{
private readonly Dictionary<string, bool> _foldoutState = new Dictionary<string, bool>(StringComparer.Ordinal);
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawDefaultInspector();
serializedObject.ApplyModifiedProperties();
var poolManager = (GameObjectPoolManager)target;
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("Enter Play Mode to inspect the runtime pool.", MessageType.Info);
return;
}
if (!poolManager.showDetailedInfo)
{
return;
}
EditorGUILayout.Space();
DrawRuntimeState(poolManager);
}
public override bool RequiresConstantRepaint()
{
var poolManager = target as GameObjectPoolManager;
return poolManager != null && Application.isPlaying && poolManager.showDetailedInfo;
}
private void DrawRuntimeState(GameObjectPoolManager poolManager)
{
GameObjectPoolSummarySnapshot summary = poolManager.GetDebugSummary();
DrawSummary(summary);
if (summary.WaitingForBootstrap)
{
EditorGUILayout.HelpBox("Waiting for YooAssets bootstrap before pool catalog build.", MessageType.Info);
return;
}
if (!summary.IsReady)
{
EditorGUILayout.HelpBox("Pool manager is not ready.", MessageType.Warning);
return;
}
List<GameObjectPoolSnapshot> snapshots = poolManager.GetDebugSnapshots();
if (snapshots.Count == 0)
{
EditorGUILayout.HelpBox("No pooled runtime instances exist yet.", MessageType.Info);
return;
}
for (int i = 0; i < snapshots.Count; i++)
{
DrawSnapshot(snapshots[i]);
}
}
private static void DrawSummary(in GameObjectPoolSummarySnapshot summary)
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Runtime Summary", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Ready", summary.IsReady ? "Yes" : "No");
EditorGUILayout.LabelField("Waiting Bootstrap", summary.WaitingForBootstrap ? "Yes" : "No");
EditorGUILayout.LabelField("Pools", summary.PoolCount.ToString());
EditorGUILayout.LabelField("Loaded Prefabs", summary.LoadedPrefabCount.ToString());
EditorGUILayout.LabelField("Instances", summary.TotalInstanceCount.ToString());
EditorGUILayout.LabelField("Active", summary.ActiveInstanceCount.ToString());
EditorGUILayout.LabelField("Inactive", summary.InactiveInstanceCount.ToString());
EditorGUILayout.LabelField("Pending Maintenance", summary.PendingMaintenanceCount.ToString());
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
private void DrawSnapshot(GameObjectPoolSnapshot snapshot)
{
if (snapshot == null)
{
return;
}
string entryLabel = string.IsNullOrWhiteSpace(snapshot.entryName) ? snapshot.assetPath : snapshot.entryName;
string foldoutKey = string.Concat(entryLabel, "|", snapshot.assetPath);
if (!_foldoutState.ContainsKey(foldoutKey))
{
_foldoutState[foldoutKey] = false;
}
string foldoutLabel = string.Format(
"{0} [{1}/{2}] Hit:{3}/{4}",
entryLabel,
snapshot.activeCount,
snapshot.totalCount,
snapshot.hitCount,
snapshot.acquireCount);
EditorGUILayout.BeginVertical("box");
_foldoutState[foldoutKey] = EditorGUILayout.Foldout(_foldoutState[foldoutKey], foldoutLabel, true);
if (_foldoutState[foldoutKey])
{
EditorGUILayout.LabelField("Rule", entryLabel);
EditorGUILayout.LabelField("Asset Path", snapshot.assetPath);
EditorGUILayout.LabelField("Loader", snapshot.loaderType.ToString());
EditorGUILayout.LabelField("Retain Target", snapshot.retainTarget.ToString());
EditorGUILayout.LabelField("Soft Capacity", snapshot.softCapacity.ToString());
EditorGUILayout.LabelField("Capacity", snapshot.hardCapacity.ToString());
EditorGUILayout.LabelField("Runtime Capacity", snapshot.runtimeHardCapacity.ToString());
EditorGUILayout.LabelField("Inactive", snapshot.inactiveCount.ToString());
EditorGUILayout.LabelField("Prefab Loaded", snapshot.prefabLoaded ? "Yes" : "No");
EditorGUILayout.LabelField("Prefab Cold", FormatSeconds(snapshot.prefabIdleDuration));
EditorGUILayout.LabelField("Wake Count", snapshot.prefabWakeCount.ToString());
EditorGUILayout.LabelField("Wake Gap", snapshot.prefabWakeGap < 0f ? "N/A" : FormatSeconds(snapshot.prefabWakeGap));
EditorGUILayout.LabelField("Unload Delay", snapshot.prefabUnloadDelay < 0f ? "N/A" : FormatSeconds(snapshot.prefabUnloadDelay));
EditorGUILayout.LabelField("Next Maintenance", snapshot.nextMaintenanceIn < 0f ? "None" : FormatSeconds(snapshot.nextMaintenanceIn));
EditorGUILayout.Space();
EditorGUILayout.LabelField("Acquire", snapshot.acquireCount.ToString());
EditorGUILayout.LabelField("Release", snapshot.releaseCount.ToString());
EditorGUILayout.LabelField("Hit", snapshot.hitCount.ToString());
EditorGUILayout.LabelField("Miss", snapshot.missCount.ToString());
EditorGUILayout.LabelField("Expand", snapshot.expandCount.ToString());
EditorGUILayout.LabelField("Destroy", snapshot.destroyCount.ToString());
EditorGUILayout.LabelField("Peak Active", snapshot.peakActive.ToString());
EditorGUILayout.LabelField("Peak Active Short", snapshot.peakActiveShort.ToString());
EditorGUILayout.LabelField("Peak Active Long", snapshot.peakActiveLong.ToString());
if (snapshot.instances.Count > 0)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Instances", EditorStyles.boldLabel);
for (int i = 0; i < snapshot.instances.Count; i++)
{
DrawInstance(snapshot.instances[i]);
}
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
private static void DrawInstance(GameObjectPoolInstanceSnapshot snapshot)
{
if (snapshot == null)
{
return;
}
EditorGUILayout.BeginHorizontal("box");
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField(snapshot.instanceName, EditorStyles.boldLabel);
EditorGUILayout.LabelField("State", snapshot.isActive ? "Active" : "Inactive");
EditorGUILayout.LabelField("Life", FormatSeconds(snapshot.lifeDuration));
if (!snapshot.isActive)
{
EditorGUILayout.LabelField("Idle", FormatSeconds(snapshot.idleDuration));
}
EditorGUILayout.EndVertical();
EditorGUILayout.ObjectField(snapshot.gameObject, typeof(GameObject), true, GUILayout.Width(140f));
EditorGUILayout.EndHorizontal();
}
private static string FormatSeconds(float seconds)
{
return seconds.ToString("F2") + "s";
}
}
}