diff --git a/Editor/Settings/EditorStatusWatcher.cs b/Editor/Settings/EditorStatusWatcher.cs new file mode 100644 index 0000000..7dbe13b --- /dev/null +++ b/Editor/Settings/EditorStatusWatcher.cs @@ -0,0 +1,31 @@ +using HybridCLR.Editor; +using System; +using UnityEditor; +using UnityEditorInternal; + +/// +/// 监听编辑器状态,当编辑器重新 focus 时,重新加载实例,避免某些情景下 svn 、git 等外部修改了数据却无法同步的异常。 +/// +[InitializeOnLoad] +public static class EditorStatusWatcher +{ + public static Action OnEditorFocused; + static bool isFocused; + static EditorStatusWatcher() => EditorApplication.update += Update; + static void Update() + { + //当编辑器 focus 后如果优先发生编译,则等待其完成编译再刷新内部逻辑(猜想&防御) + if (!EditorApplication.isCompiling) + { + if (isFocused != InternalEditorUtility.isApplicationActive) + { + isFocused = InternalEditorUtility.isApplicationActive; + if (isFocused) + { + HybridCLRSettings.LoadOrCreate(); + OnEditorFocused?.Invoke(); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/Settings/EditorStatusWatcher.cs.meta b/Editor/Settings/EditorStatusWatcher.cs.meta new file mode 100644 index 0000000..317bfd7 --- /dev/null +++ b/Editor/Settings/EditorStatusWatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 093a9e6c1e7399244bbcd8983fdbfdee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Settings/HybridCLRSettingProvider.cs b/Editor/Settings/HybridCLRSettingProvider.cs index 0df4d1c..41f2c04 100644 --- a/Editor/Settings/HybridCLRSettingProvider.cs +++ b/Editor/Settings/HybridCLRSettingProvider.cs @@ -2,6 +2,7 @@ using System; using System.Reflection; using UnityEditor; using UnityEditor.Presets; +using UnityEditorInternal; using UnityEngine; using UnityEngine.UIElements; namespace HybridCLR.Editor @@ -27,9 +28,9 @@ namespace HybridCLR.Editor public HybridCLRSettingsProvider() : base("Project/HybridCLR Settings", SettingsScope.Project) { } public override void OnActivate(string searchContext, VisualElement rootElement) { + EditorStatusWatcher.OnEditorFocused += OnEditorFocused; HybridCLRSettings.Instance.Save(); var setting = HybridCLRSettings.Instance; - setting.hideFlags &= ~HideFlags.NotEditable; _serializedObject = _serializedObject ?? new SerializedObject(setting); _enable = _serializedObject.FindProperty("enable"); _useGlobalIl2cpp = _serializedObject.FindProperty("useGlobalIl2cpp"); @@ -46,6 +47,13 @@ namespace HybridCLR.Editor _maxGenericReferenceIteration = _serializedObject.FindProperty("maxGenericReferenceIteration"); _maxMethodBridgeGenericIteration = _serializedObject.FindProperty("maxMethodBridgeGenericIteration"); } + + private void OnEditorFocused() + { + _serializedObject = new SerializedObject(HybridCLRSettings.Instance); + SettingsService.NotifySettingsProviderChanged(); + } + public override void OnTitleBarGUI() { base.OnTitleBarGUI(); @@ -54,7 +62,7 @@ namespace HybridCLR.Editor #region 绘制官方网站跳转按钮 var w = rect.x + rect.width; - rect.x = w - 58; + rect.x = w - 57; rect.y += 6; rect.width = rect.height = 18; var content = EditorGUIUtility.IconContent("_Help"); @@ -64,7 +72,6 @@ namespace HybridCLR.Editor Application.OpenURL("https://focus-creative-games.github.io/hybridclr/"); } #endregion - #region 绘制 Preset rect.x += 19; content = EditorGUIUtility.IconContent("Preset.Context"); @@ -73,26 +80,33 @@ namespace HybridCLR.Editor { var target = HybridCLRSettings.Instance; var receiver = ScriptableObject.CreateInstance(); - receiver.Init(target); + receiver.Init(target, this); PresetSelector.ShowSelector(target, null, true, receiver); } #endregion #region 绘制 Reset rect.x += 19; - content = EditorGUIUtility.IconContent("_Popup"); + content = EditorGUIUtility.IconContent( +#if UNITY_2021_3_OR_NEWER + "pane options" +#else + "_Popup" +#endif + ); content.tooltip = "Reset"; if (GUI.Button(rect, content, buttonStyle)) { - GenericMenu menu = new GenericMenu(); - menu.AddItem(new GUIContent("Reset"), false, () => + GenericMenu menu = new GenericMenu(); + menu.AddItem(new GUIContent("Reset"), false, () => { Undo.RecordObject(HybridCLRSettings.Instance, "Capture Value for Reset"); var dv = ScriptableObject.CreateInstance(); var json = EditorJsonUtility.ToJson(dv); - EditorJsonUtility.FromJsonOverwrite(json,HybridCLRSettings.Instance); + UnityEngine.Object.DestroyImmediate(dv); + EditorJsonUtility.FromJsonOverwrite(json, HybridCLRSettings.Instance); HybridCLRSettings.Instance.Save(); }); - menu.ShowAsContext(); + menu.ShowAsContext(); } #endregion } @@ -100,9 +114,9 @@ namespace HybridCLR.Editor { using (CreateSettingsWindowGUIScope()) { + //防止配置文件意外删除 if (_serializedObject == null || !_serializedObject.targetObject) { - _serializedObject = null; _serializedObject = new SerializedObject(HybridCLRSettings.Instance); } _serializedObject.Update(); @@ -137,6 +151,7 @@ namespace HybridCLR.Editor public override void OnDeactivate() { base.OnDeactivate(); + EditorStatusWatcher.OnEditorFocused -= OnEditorFocused; HybridCLRSettings.Instance.Save(); _serializedObject = null; } diff --git a/Editor/Settings/MenuProvider.cs b/Editor/Settings/MenuProvider.cs index e02c35b..ee8a2c4 100644 --- a/Editor/Settings/MenuProvider.cs +++ b/Editor/Settings/MenuProvider.cs @@ -5,9 +5,17 @@ public static class MenuProvider { [MenuItem("HybridCLR/Settings", priority = 200)] public static void OpenSettings() => SettingsService.OpenProjectSettings("Project/HybridCLR Settings"); - [MenuItem("HybridCLR/About us", priority = 400)] - public static void AboutUs() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/about/"); - - [MenuItem("HybridCLR/Documents", priority = 399)] - public static void OpenDoc() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/Quick Start")] + public static void OpenQuickStart() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/start_up/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/Benchmark")] + public static void OpenBenchmark() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/benchmark/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/FAQ")] + public static void OpenFAQ() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/faq/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/Common Errors")] + public static void OpenCommonErrors() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/common_errors/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/Bug Report")] + public static void OpenBugReport() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/bug_reporter/"); + [MenuItem("HybridCLR/Documents/", menuItem = "HybridCLR/Documents/About HybridCLR")] + public static void OpenAbout() => Application.OpenURL("https://focus-creative-games.github.io/hybridclr/about/"); } + diff --git a/Editor/Settings/ScriptableSignleton.cs b/Editor/Settings/ScriptableSignleton.cs index 6ac2ef9..d5f5bca 100644 --- a/Editor/Settings/ScriptableSignleton.cs +++ b/Editor/Settings/ScriptableSignleton.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using UnityEditor; using UnityEditorInternal; using UnityEngine; @@ -15,18 +16,18 @@ namespace HybridCLR.Editor { if (!s_Instance) { - CreateAndLoad(); + LoadOrCreate(); } return s_Instance; } } - private static void CreateAndLoad() + public static void LoadOrCreate() { string filePath = GetFilePath(); if (!string.IsNullOrEmpty(filePath)) { var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath); - s_Instance = arr.Length > 0 ? arr[0] as T : CreateInstance(); + s_Instance = arr.Length > 0 ? arr[0] as T : s_Instance??CreateInstance(); } else { @@ -34,7 +35,7 @@ namespace HybridCLR.Editor } } - public void Save(bool saveAsText=true) + public void Save(bool saveAsText = true) { if (!s_Instance) { @@ -56,18 +57,10 @@ namespace HybridCLR.Editor } protected static string GetFilePath() { - Type typeFromHandle = typeof(T); - object[] customAttributes = typeFromHandle.GetCustomAttributes(inherit: true); - object[] array = customAttributes; - foreach (object obj in array) - { - if (obj is FilePathAttribute) - { - FilePathAttribute filePathAttribute = obj as FilePathAttribute; - return filePathAttribute.filepath; - } - } - return string.Empty; + return typeof(T).GetCustomAttributes(inherit: true) + .Cast() + .FirstOrDefault(v => v != null) + ?.filepath; } } [AttributeUsage(AttributeTargets.Class)] diff --git a/Editor/Settings/SettingsPresetReceiver.cs b/Editor/Settings/SettingsPresetReceiver.cs index 592ae64..d8556c5 100644 --- a/Editor/Settings/SettingsPresetReceiver.cs +++ b/Editor/Settings/SettingsPresetReceiver.cs @@ -8,11 +8,13 @@ namespace HybridCLR.Editor { private Object m_Target; private Preset m_InitialValue; + private SettingsProvider m_Provider; - internal void Init(Object target) + internal void Init(Object target, SettingsProvider provider) { m_Target = target; m_InitialValue = new Preset(target); + m_Provider = provider; } public override void OnSelectionChanged(Preset selection) { @@ -26,9 +28,7 @@ namespace HybridCLR.Editor Undo.RecordObject(m_Target, "Cancel Preset"); m_InitialValue.ApplyTo(m_Target); } -#if UNITY_2020_1_OR_NEWER - SettingsService.RepaintAllSettingsWindow(); -#endif + m_Provider.Repaint(); } public override void OnSelectionClosed(Preset selection) {