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 ? "已暂停" : "运行中", 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($"{modeLabel}", 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;
}
}
}