ProjectDDD/Packages/com.singularitygroup.hotreload/Editor/Helpers/EditorWindowHelper.cs
2025-07-08 19:46:31 +09:00

102 lines
4.3 KiB
C#

using System;
using System.Text.RegularExpressions;
using UnityEngine;
using System.Threading.Tasks;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
namespace SingularityGroup.HotReload.Editor {
internal static class EditorWindowHelper {
#if UNITY_2020_1_OR_NEWER
public static bool supportsNotifications = true;
#else
public static bool supportsNotifications = false;
#endif
private static readonly Regex ValidEmailRegex = new Regex(@"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
+ @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
+ @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$", RegexOptions.IgnoreCase);
public static bool IsValidEmailAddress(string email) {
return ValidEmailRegex.IsMatch(email);
}
public static bool IsHumanControllingUs() {
if (Application.isBatchMode) {
return false;
}
var isCI = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI"));
return !isCI;
}
internal enum NotificationStatus {
None,
Patching,
NeedsRecompile
}
private static readonly Dictionary<NotificationStatus, GUIContent> notificationContent = new Dictionary<NotificationStatus, GUIContent> {
{ NotificationStatus.Patching, new GUIContent("[Hot Reload] Applying patches...")},
{ NotificationStatus.NeedsRecompile, new GUIContent("[Hot Reload] Unsupported Changes detected! Recompiling...")},
};
static Type gameViewT;
private static EditorWindow[] gameViewWindows {
get {
gameViewT = gameViewT ?? typeof(EditorWindow).Assembly.GetType("UnityEditor.GameView");
return Resources.FindObjectsOfTypeAll(gameViewT).Cast<EditorWindow>().ToArray();
}
}
private static EditorWindow[] sceneWindows {
get {
return Resources.FindObjectsOfTypeAll(typeof(SceneView)).Cast<EditorWindow>().ToArray();
}
}
private static EditorWindow[] notificationWindows {
get {
return gameViewWindows.Concat(sceneWindows).ToArray();
}
}
static NotificationStatus lastNotificationStatus;
private static DateTime? latestNotificationStartedAt;
private static bool notificationShownRecently => latestNotificationStartedAt != null && DateTime.UtcNow - latestNotificationStartedAt < TimeSpan.FromSeconds(1);
internal static void ShowNotification(NotificationStatus notificationType, float maxDuration = 3) {
// Patch status goes from Unsupported changes to patching rapidly when making unsupported change
// patching also shows right before unsupported changes sometimes
// so we don't override NeedsRecompile notification ever
bool willOverrideNeedsCompileNotification = notificationType != NotificationStatus.NeedsRecompile && notificationShownRecently || lastNotificationStatus == NotificationStatus.NeedsRecompile && notificationShownRecently;
if (!supportsNotifications || willOverrideNeedsCompileNotification) {
return;
}
foreach (EditorWindow notificationWindow in notificationWindows) {
notificationWindow.ShowNotification(notificationContent[notificationType], maxDuration);
notificationWindow.Repaint();
}
latestNotificationStartedAt = DateTime.UtcNow;
lastNotificationStatus = notificationType;
}
internal static void RemoveNotification() {
if (!supportsNotifications) {
return;
}
// only patching notifications should be removed after showing less than 1 second
if (notificationShownRecently && lastNotificationStatus != NotificationStatus.Patching) {
return;
}
foreach (EditorWindow notificationWindow in notificationWindows) {
notificationWindow.RemoveNotification();
notificationWindow.Repaint();
}
latestNotificationStartedAt = null;
lastNotificationStatus = NotificationStatus.None;
}
}
}