using System; using UnityEditor; using UnityEditorInternal; namespace Unity.PlasticSCM.Editor { internal static class Execute { // Executes action once when the editor is not updating or compiling. // Use this for quick actions that need to wait for the current import/compile to finish. internal static void WhenEditorIsReady(Action action) { if (PlasticApp.IsUnitTesting) { action(); return; } EditorApplication.update += RunOnceWhenEditorIsReady; bool IsEditorBusy() { return EditorApplication.isUpdating || EditorApplication.isCompiling; } void RunOnceWhenEditorIsReady() { if (IsEditorBusy()) return; EditorApplication.update -= RunOnceWhenEditorIsReady; action(); } } // Executes action once the editor has been idle for a sustained period of time. // Checks: isUpdating, isCompiling, Progress.running (background tasks), // and isApplicationActive (editor must be in foreground, otherwise background tasks are deferred). // Use this for operations that need all editor activity to settle first, // such as workspace creation from the Hub where late file modifications // could cause files to appear as "changed" in pending changes. internal static void AfterEditorIsIdleForSeconds(double delaySeconds, Action action) { if (PlasticApp.IsUnitTesting) { action(); return; } double lastBusyTime = EditorApplication.timeSinceStartup; EditorApplication.update += RunOnceAfterEditorIsIdle; bool IsEditorInBackground() { return !InternalEditorUtility.isApplicationActive; } bool IsEditorBusy() { return EditorApplication.isUpdating || EditorApplication.isCompiling || Progress.running; } void RunOnceAfterEditorIsIdle() { double currentTime = EditorApplication.timeSinceStartup; if (IsEditorInBackground() || IsEditorBusy()) { lastBusyTime = currentTime; return; } if (currentTime - lastBusyTime < delaySeconds) return; EditorApplication.update -= RunOnceAfterEditorIsIdle; action(); } } } }