250 lines
9.0 KiB
C#
250 lines
9.0 KiB
C#
using System;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
|
||
namespace SepCore.Timer.Editor
|
||
{
|
||
[CustomEditor(typeof(TimerComponent))]
|
||
public sealed class TimerComponentEditor : UnityEditor.Editor
|
||
{
|
||
private TimerComponent _timer;
|
||
private Vector2 _scrollPosition;
|
||
private bool _showDebugControls = true;
|
||
|
||
private void OnEnable()
|
||
{
|
||
_timer = (TimerComponent)target;
|
||
EditorApplication.update += Repaint;
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
EditorApplication.update -= Repaint;
|
||
}
|
||
|
||
public override void OnInspectorGUI()
|
||
{
|
||
base.OnInspectorGUI();
|
||
|
||
if (!Application.isPlaying)
|
||
{
|
||
EditorGUILayout.HelpBox("运行时显示任务列表和调试信息", MessageType.Info);
|
||
return;
|
||
}
|
||
|
||
DrawStatistics();
|
||
DrawDebugControls();
|
||
DrawTaskList();
|
||
}
|
||
|
||
private void DrawStatistics()
|
||
{
|
||
TimerTaskSnapshot[] tasks = _timer.GetTaskSnapshots();
|
||
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.LabelField("统计信息", EditorStyles.boldLabel);
|
||
|
||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||
{
|
||
int scaledCount = 0;
|
||
int unscaledCount = 0;
|
||
int errorCount = 0;
|
||
int infiniteCount = 0;
|
||
|
||
foreach (TimerTaskSnapshot task in tasks)
|
||
{
|
||
if (task.TimeMode == TimerTimeMode.Scaled)
|
||
scaledCount++;
|
||
else
|
||
unscaledCount++;
|
||
|
||
if (task.HasError)
|
||
errorCount++;
|
||
|
||
if (task.RemainingRepeatCount < 0)
|
||
infiniteCount++;
|
||
}
|
||
|
||
using (new EditorGUILayout.HorizontalScope())
|
||
{
|
||
EditorGUILayout.LabelField("活跃任务", $"{tasks.Length}", GUILayout.Width(120));
|
||
EditorGUILayout.LabelField("Scaled", $"{scaledCount}", GUILayout.Width(80));
|
||
EditorGUILayout.LabelField("Unscaled", $"{unscaledCount}", GUILayout.Width(80));
|
||
}
|
||
|
||
using (new EditorGUILayout.HorizontalScope())
|
||
{
|
||
EditorGUILayout.LabelField("无限循环", $"{infiniteCount}", GUILayout.Width(120));
|
||
EditorGUILayout.LabelField("异常任务", $"{errorCount}", errorCount > 0 ? GetErrorLabelStyle() : GUIStyle.none, GUILayout.Width(80));
|
||
EditorGUILayout.LabelField("全局状态", _timer.IsPaused ? "<color=orange>已暂停</color>" : "<color=green>运行中</color>", GetRichLabelStyle());
|
||
}
|
||
}
|
||
}
|
||
|
||
private void DrawDebugControls()
|
||
{
|
||
EditorGUILayout.Space();
|
||
_showDebugControls = EditorGUILayout.Foldout(_showDebugControls, "调试控制", true);
|
||
|
||
if (!_showDebugControls)
|
||
return;
|
||
|
||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||
{
|
||
using (new EditorGUILayout.HorizontalScope())
|
||
{
|
||
if (GUILayout.Button(_timer.IsPaused ? "恢复全部" : "暂停全部", GUILayout.Height(25)))
|
||
{
|
||
if (_timer.IsPaused)
|
||
_timer.Resume();
|
||
else
|
||
_timer.Pause();
|
||
}
|
||
|
||
if (GUILayout.Button("清理全部", GUILayout.Height(25)))
|
||
{
|
||
if (EditorUtility.DisplayDialog("确认", "确定要清除所有定时任务吗?", "确定", "取消"))
|
||
{
|
||
_timer.ClearAll();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void DrawTaskList()
|
||
{
|
||
TimerTaskSnapshot[] tasks = _timer.GetTaskSnapshots();
|
||
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.LabelField($"活跃任务列表 ({tasks.Length})", EditorStyles.boldLabel);
|
||
|
||
if (tasks.Length == 0)
|
||
{
|
||
EditorGUILayout.HelpBox("当前没有活跃的定时任务", MessageType.Info);
|
||
return;
|
||
}
|
||
|
||
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
||
|
||
foreach (TimerTaskSnapshot task in tasks)
|
||
{
|
||
DrawTaskItem(task);
|
||
}
|
||
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
|
||
private void DrawTaskItem(TimerTaskSnapshot task)
|
||
{
|
||
Color originalColor = GUI.backgroundColor;
|
||
|
||
if (task.HasError)
|
||
GUI.backgroundColor = new Color(1f, 0.3f, 0.3f, 0.3f);
|
||
|
||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||
{
|
||
if (task.HasError)
|
||
{
|
||
EditorGUILayout.LabelField("⚠ 该任务回调曾抛出异常", GetErrorLabelStyle());
|
||
}
|
||
|
||
// 头部:ID + 时间模式 + 取消按钮
|
||
using (new EditorGUILayout.HorizontalScope())
|
||
{
|
||
EditorGUILayout.LabelField($"ID: #{task.Id}", GUILayout.Width(60));
|
||
|
||
string modeLabel = task.TimeMode == TimerTimeMode.Scaled ? "Scaled" : "Unscaled";
|
||
Color modeColor = task.TimeMode == TimerTimeMode.Scaled ? Color.cyan : Color.yellow;
|
||
EditorGUILayout.LabelField($"<color=#{ColorUtility.ToHtmlStringRGB(modeColor)}>{modeLabel}</color>", GetRichLabelStyle(), GUILayout.Width(60));
|
||
|
||
string repeatLabel = task.RemainingRepeatCount < 0 ? "∞" : $"{task.RemainingRepeatCount}";
|
||
EditorGUILayout.LabelField($"剩余: {repeatLabel} 次", GUILayout.Width(80));
|
||
|
||
GUILayout.FlexibleSpace();
|
||
|
||
if (GUILayout.Button("取消", GUILayout.Width(50)))
|
||
{
|
||
_timer.Cancel(new TimerHandle(task.Id));
|
||
}
|
||
}
|
||
|
||
// 进度条
|
||
DrawProgressBar(task);
|
||
|
||
// 回调信息
|
||
EditorGUILayout.LabelField("回调:", task.CallbackMethod, EditorStyles.miniLabel);
|
||
|
||
// 归属对象(可点击 Ping)
|
||
using (new EditorGUILayout.HorizontalScope())
|
||
{
|
||
EditorGUILayout.LabelField("归属:", GUILayout.Width(40));
|
||
if (task.Owner is UnityEngine.Object unityObject && unityObject != null)
|
||
{
|
||
if (GUILayout.Button(unityObject.name, EditorStyles.linkLabel))
|
||
{
|
||
EditorGUIUtility.PingObject(unityObject);
|
||
Selection.activeObject = unityObject;
|
||
}
|
||
}
|
||
else if (task.Owner != null)
|
||
{
|
||
EditorGUILayout.LabelField(task.Owner.ToString(), EditorStyles.miniLabel);
|
||
}
|
||
else
|
||
{
|
||
EditorGUILayout.LabelField("(无归属对象)", EditorStyles.miniLabel);
|
||
}
|
||
}
|
||
}
|
||
|
||
GUI.backgroundColor = originalColor;
|
||
EditorGUILayout.Space(2);
|
||
}
|
||
|
||
private void DrawProgressBar(TimerTaskSnapshot task)
|
||
{
|
||
float progress;
|
||
string label;
|
||
|
||
if (task.Interval <= 0f || task.RemainingRepeatCount == 1)
|
||
{
|
||
// 一次性任务:显示延迟进度
|
||
float totalTime = Mathf.Max(task.Interval, task.RemainingTime);
|
||
progress = totalTime > 0f ? 1f - (task.RemainingTime / totalTime) : 1f;
|
||
label = $"剩余 {task.RemainingTime:F2}s (一次性)";
|
||
}
|
||
else if (task.RemainingRepeatCount < 0)
|
||
{
|
||
// 无限循环:显示当前周期进度
|
||
progress = 1f - (task.RemainingTime / task.Interval);
|
||
label = $"剩余 {task.RemainingTime:F2}s (无限循环)";
|
||
}
|
||
else
|
||
{
|
||
// 有限循环:显示当前周期进度
|
||
progress = 1f - (task.RemainingTime / task.Interval);
|
||
label = $"剩余 {task.RemainingTime:F2}s (周期进度)";
|
||
}
|
||
|
||
Rect rect = EditorGUILayout.GetControlRect(false, 18);
|
||
EditorGUI.ProgressBar(rect, Mathf.Clamp01(progress), label);
|
||
}
|
||
|
||
private static GUIStyle GetRichLabelStyle()
|
||
{
|
||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||
style.richText = true;
|
||
return style;
|
||
}
|
||
|
||
private static GUIStyle GetErrorLabelStyle()
|
||
{
|
||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||
style.normal.textColor = Color.red;
|
||
style.fontStyle = FontStyle.Bold;
|
||
return style;
|
||
}
|
||
}
|
||
}
|