unity/EditorPlugin/Profiler/ProfilerWindowEventsHandler.cs (116 lines of code) (raw):

#nullable enable using System; using JetBrains.Collections.Viewable; using JetBrains.Diagnostics; using JetBrains.Lifetimes; using JetBrains.Rider.Model.Unity.BackendUnity; using JetBrains.Rider.PathLocator; using JetBrains.Rider.Unity.Editor.Profiler.Adapters.Interfaces; using JetBrains.Rider.Unity.Editor.Profiler.SnapshotAnalysis; using JetBrains.Rider.Unity.Editor.Profiler.SnapshotNavigation; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; namespace JetBrains.Rider.Unity.Editor.Profiler { public static class ProfilerWindowEventsHandler { private static readonly ILog ourLogger = Log.GetLog(nameof(ProfilerWindowEventsHandler)); private static IProfilerAdaptersFactory? ourProfilerAdaptersFactory; private static IProfilerWindowTypeChecker? ourProfilerWindwowTypeChecker; private static EditorWindow? ourLastProfilerWindow; private static EditorWindow? ourProfilerWindow; private static IProfilerWindowSelectionDataProvider? ourProfilerWindowDataProvider; private static ISnapshotCollectorDaemon? ourSnapshotCollectorDaemon; private static readonly ISignal<SampleStackInfo> ourOnTimeSampleSelectedSignal = new SignalBase<SampleStackInfo>(); private static void InternalUpdate() { if (ourProfilerWindowDataProvider is not { IsSupportingCurrentUnityVersion: true }) return; UpdateFocusedProfilerWindow(); ourSnapshotCollectorDaemon?.Update(ourLastProfilerWindow); } private static void UpdateFocusedProfilerWindow() { var profilerWindow = TryGetProfilerWindow(EditorWindow.focusedWindow); #if UNITY_2022_3_OR_NEWER if (!EditorApplication.isFocused && ourProfilerWindow == null) return; #else if(EditorWindow.focusedWindow == null && ourProfilerWindow == null) return; #endif if (ourProfilerWindow != profilerWindow) { DeinitCurrentProfilerWindowEventHandling(); if (profilerWindow != null) ourProfilerWindowDataProvider?.Init(profilerWindow, OnTimeSampleSelected); if (ourProfilerWindowDataProvider is { IsInitialized: true }) ourProfilerWindow = profilerWindow; } if (ourProfilerWindow != null) ourLastProfilerWindow = ourProfilerWindow; } private static void DeinitCurrentProfilerWindowEventHandling() { ourLogger.Verbose("DeinitCurrentProfilerWindowEventHandling"); if (ourProfilerWindow != null) { ourProfilerWindowDataProvider?.Deinit(ourProfilerWindow, OnTimeSampleSelected); ourProfilerWindow = null; } } private static EditorWindow? TryGetProfilerWindow(EditorWindow? focusedWindow) { return ourProfilerWindwowTypeChecker?.IsProfilerWindow(focusedWindow) == true ? focusedWindow : null; } private static void OnTimeSampleSelected(string sampleName, string callStack) { ourLogger.Verbose($"OnTimeSampleSelected: {sampleName}, {callStack}"); ourOnTimeSampleSelectedSignal.Fire(new SampleStackInfo(sampleName, callStack)); //In case if no rider instance is running - just open solution, //this option is temporary turned off for better times // PluginEntryPoint.OpenAssetHandler.OnOpenedAsset("", 0); } public static void Initialize(Lifetime appDomainLifetime) { appDomainLifetime.Bracket(() => { ourProfilerAdaptersFactory = #if UNITY_2022_3_OR_NEWER new JetBrains.Rider.Unity.Editor.Profiler.Adapters.UnityApiBasedAdapters.UnityApiBasedFactory(); #else new JetBrains.Rider.Unity.Editor.Profiler.Adapters.ReflectionBasedAdapters.ReflectionBasedAdaptersFactory(); #endif ourLogger.Verbose("ProfilerWindowEventsHandler.Initialize"); ourProfilerWindowDataProvider = ourProfilerAdaptersFactory!.CreateProfilerWindowFacade(); ourProfilerWindwowTypeChecker = ourProfilerAdaptersFactory!.CreateProfilerWindowTypeChecker(); ourSnapshotCollectorDaemon = new SnapshotCollectorDaemon(ourProfilerAdaptersFactory, appDomainLifetime); //find an already opened profiler window var profilerWindowObjects = ourProfilerWindwowTypeChecker?.FindProfilerWindows() ?? Array.Empty<Object>(); ourLastProfilerWindow = profilerWindowObjects.Length > 0 ? profilerWindowObjects[0] as EditorWindow : null; EditorApplication.update += InternalUpdate; }, () => { ourLogger.Verbose("ProfilerWindowEventsHandler.Deinitialize"); EditorApplication.update -= InternalUpdate; DeinitCurrentProfilerWindowEventHandling(); ourSnapshotCollectorDaemon?.Deinit(); ourSnapshotCollectorDaemon = null; ourLastProfilerWindow = null; }); } //There could be multiple connections from different rider instances to single Unity editor public static void Advise(Lifetime connectionLifetime, UnityProfilerModel model, BackendUnityModel backendUnityModel) { ourLogger.Verbose("ProfilerWindowEventsHandler.Advise"); ourOnTimeSampleSelectedSignal.Advise(connectionLifetime, info => { var myOpener = new RiderFileOpener(RiderPathProvider.RiderPathLocator.RiderLocatorEnvironment); int? processId = backendUnityModel.RiderProcessId.HasValue() ? backendUnityModel.RiderProcessId.Value : null; myOpener.AllowSetForegroundWindow(processId); model.OpenFileBySampleInfo.Start(connectionLifetime, info); }); ourSnapshotCollectorDaemon?.Advise(connectionLifetime, model); } } }