vampire-like/Assets/Plugins/TimerModule/Editor/TimerComponentEditor.cs

250 lines
9.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}