2
0
Эх сурвалжийг харах

Feature: Added a warning window when attempting to close the editor or unload a project while resource import is in progress

BearishSun 6 жил өмнө
parent
commit
6c491c1da1

+ 75 - 27
Source/EditorManaged/General/EditorApplication.cs

@@ -291,6 +291,9 @@ namespace bs.Editor
         private static bool unitTestsExecuted;
         private static EditorPersistentData persistentData;
 
+        private static bool delayUnloadProject;
+        private static Action delayUnloadCallback;
+
         #pragma warning disable 0414
         private static EditorApplication instance;
         #pragma warning restore 0414
@@ -373,6 +376,15 @@ namespace bs.Editor
             // Update managers
             ProjectLibrary.Update();
             codeManager.Update();
+
+            if (delayUnloadProject)
+            {
+                delayUnloadProject = false;
+                UnloadProject();
+
+                delayUnloadCallback?.Invoke();
+                delayUnloadCallback = null;
+            }
         }
 
         /// <summary>
@@ -730,9 +742,9 @@ namespace bs.Editor
             }
 
             if (IsProjectLoaded)
-                UnloadProject();
-
-            Internal_LoadProject(path); // Triggers Internal_OnProjectLoaded when done
+                TryUnloadProject(() => Internal_LoadProject(path));
+            else
+                Internal_LoadProject(path); // Triggers Internal_OnProjectLoaded when done
         }
 
         /// <summary>
@@ -828,47 +840,83 @@ namespace bs.Editor
         }
 
         /// <summary>
-        /// Unloads the currently loaded project. Offers the user a chance to save the current scene if it is modified.
-        /// Automatically saves all project data before unloading.
+        /// Attempts to unload the currently loaded project. Offers the user a chance to save the current scene if it is
+        /// modified. Automatically saves all project data before unloading.
         /// </summary>
-        private static void UnloadProject()
+        /// <param name="onDone">Callback to trigger when project project unload is done.</param>
+        private static void TryUnloadProject(Action onDone)
         {
-            Action continueUnload =
-                () =>
-                {
-                    Scene.Clear();
+            if (delayUnloadProject)
+                return;
 
-                    if (monitor != null)
+            AskToSaveSceneAndContinue(
+                    () =>
+                {
+                    if (ProjectLibrary.ImportInProgress)
                     {
-                        monitor.Destroy();
-                        monitor = null;
+                        ConfirmImportInProgressWindow.Show();
+                        delayUnloadCallback = onDone;
+                        delayUnloadProject = true;
                     }
+                    else
+                    {
+                        UnloadProject();
+                        onDone?.Invoke();
+                    }
+                });
+        }
 
-                    LibraryWindow window = EditorWindow.GetWindow<LibraryWindow>();
-                    if(window != null)
-                        window.Reset();
-
-                    SetSceneDirty(false);
-                    Internal_UnloadProject();
-                    SetStatusProject(false);
-                };
+        /// <summary>
+        /// Unloads the currently loaded project, without making any checks or requiring confirmation.
+        /// </summary>
+        private static void UnloadProject()
+        {
+            Scene.Clear();
 
-            Action<DialogBox.ResultType> dialogCallback =
-            (result) =>
+            if (monitor != null)
             {
-                if (result == DialogBox.ResultType.Yes)
-                    SaveScene();
+                monitor.Destroy();
+                monitor = null;
+            }
+
+            LibraryWindow window = EditorWindow.GetWindow<LibraryWindow>();
+            if (window != null)
+                window.Reset();
+
+            SetSceneDirty(false);
+            Internal_UnloadProject();
+            SetStatusProject(false);
+        }
 
-                continueUnload();
+        /// <summary>
+        /// Checks if the current scene is modified and asks the user to save the scene if it is. Triggers the
+        /// <see cref="next"/> callback when done, unless user cancels the operation.
+        /// </summary>
+        /// <param name="next">Callback to trigger after this method finishes.</param>
+        internal static void AskToSaveSceneAndContinue(Action next)
+        {
+            Action trySaveScene = null;
+            trySaveScene = () =>
+            {
+                SaveScene(next, trySaveScene);
             };
 
+            Action<DialogBox.ResultType> dialogCallback =
+                (result) =>
+                {
+                    if (result == DialogBox.ResultType.Yes)
+                        trySaveScene();
+                    else if (result == DialogBox.ResultType.No)
+                        next?.Invoke();
+                };
+
             if (IsSceneModified())
             {
                 DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?",
                     DialogBox.Type.YesNoCancel, dialogCallback);
             }
             else
-                continueUnload();
+                next?.Invoke();
         }
 
         /// <summary>

+ 24 - 32
Source/EditorManaged/General/Program.cs

@@ -92,6 +92,7 @@ namespace bs.Editor
     class Program
     {
         private static EditorApplication app;
+        private static bool delayQuit;
 
         /// <summary>
         /// Called by the runtime whenever the editor assembly is loaded. This means initially when editor is started
@@ -134,21 +135,17 @@ namespace bs.Editor
         /// </summary>
         static void OnEditorUpdate()
         {
-            app.OnEditorUpdate();
-        }
-
-        /// <summary>
-        /// Attempts to save the current scene, and keeps retrying if failed or until user cancels.
-        /// </summary>
-        static void TrySaveSceneOnQuit()
-        {
-            Action success = () =>
+            if (delayQuit && !ProjectLibrary.ImportInProgress)
             {
+                ConfirmImportInProgressWindow.Hide();
+                
                 EditorApplication.SaveProject();
                 EditorApplication.Quit();
-            };
 
-            EditorApplication.SaveScene(success, TrySaveSceneOnQuit);
+                delayQuit = false;
+            }
+
+            app.OnEditorUpdate();
         }
 
         /// <summary>
@@ -157,28 +154,23 @@ namespace bs.Editor
         /// </summary>
         static void OnEditorQuitRequested()
         {
-            Action<DialogBox.ResultType> dialogCallback =
-            (result) =>
-            {
-                if (result == DialogBox.ResultType.Yes)
-                    TrySaveSceneOnQuit();
-                else if (result == DialogBox.ResultType.No)
-                {
-                    EditorApplication.SaveProject();
-                    EditorApplication.Quit();
-                }
-            };
+            if (delayQuit)
+                return;
 
-            if (EditorApplication.IsSceneModified())
-            {
-                DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?",
-                    DialogBox.Type.YesNoCancel, dialogCallback);
-            }
-            else
-            {
-                EditorApplication.SaveProject();
-                EditorApplication.Quit();
-            }
+            EditorApplication.AskToSaveSceneAndContinue(
+                () => 
+                {
+                    if (ProjectLibrary.ImportInProgress)
+                    {
+                        ConfirmImportInProgressWindow.Show();
+                        delayQuit = true;
+                    }
+                    else
+                    {
+                        EditorApplication.SaveProject();
+                        EditorApplication.Quit();
+                    }
+                });
         }
     }
 

+ 104 - 0
Source/EditorManaged/Windows/ConfirmImportInProgressWindow.cs

@@ -0,0 +1,104 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2019 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using bs;
+
+namespace bs.Editor
+{
+    /** @addtogroup Windows
+     *  @{
+     */
+
+    /// <summary>
+    /// A modal window that notifies the user that resource import is in the progress and allows him to wait until it
+    /// finishes or to cancel import.
+    /// </summary>
+    public class ConfirmImportInProgressWindow : ModalWindow
+    {
+        private static ConfirmImportInProgressWindow instance;
+
+        private GUIProgressBar progressBar;
+        private GUILabel messageLabel;
+        private GUIButton cancelImport;
+
+        /// <summary>
+        /// Shows the window.
+        /// </summary>
+        public static void Show()
+        {
+            if (instance == null)
+            {
+                instance = new ConfirmImportInProgressWindow();
+                instance.BuildGUI();
+            }
+        }
+
+        /// <summary>
+        /// Hides the window.
+        /// </summary>
+        public static void Hide()
+        {
+            if (instance != null)
+                instance.Close();
+
+            instance = null;
+        }
+
+        /// <summary>
+        /// Creates a window.
+        /// </summary>
+        protected ConfirmImportInProgressWindow()
+            : base(false)
+        {
+            Width = 350;
+            Height = 180;
+            Title = "Import still in progress";
+        }
+
+        private void BuildGUI()
+        {
+            progressBar = new GUIProgressBar();
+            messageLabel = new GUILabel("", EditorStyles.MultiLineLabelCentered, GUIOption.FixedHeight(60));
+            cancelImport = new GUIButton(new LocEdString("Cancel import"));
+            cancelImport.OnClick += () =>
+            {
+                ProjectLibrary.CancelImport();
+                cancelImport.Disabled = true;
+            };
+
+            GUILayoutY layoutY = GUI.AddLayoutY();
+
+            layoutY.AddFlexibleSpace();
+            GUILayoutX messageLayout = layoutY.AddLayoutX();
+            messageLayout.AddSpace(15);
+            messageLayout.AddElement(messageLabel);
+            messageLayout.AddSpace(15);
+
+            layoutY.AddSpace(10);
+
+            GUILayoutX barLayout = layoutY.AddLayoutX();
+            barLayout.AddSpace(30);
+            barLayout.AddElement(progressBar);
+            barLayout.AddSpace(30);
+
+            layoutY.AddSpace(20);
+
+            GUILayoutX buttonLayout = layoutY.AddLayoutX();
+            buttonLayout.AddFlexibleSpace();
+            buttonLayout.AddElement(cancelImport);
+            buttonLayout.AddFlexibleSpace();
+
+            layoutY.AddFlexibleSpace();
+
+            messageLabel.SetContent(new LocEdString("Resource import is still in progress. You can wait until it " +
+                "finishes or cancel import. \n\nNote that even when cancelling you will need to wait for active import threads to finish."));
+        }
+
+        private void OnEditorUpdate()
+        {
+            progressBar.Percent = ProjectLibrary.ImportProgressPercent;
+        }
+    }
+
+    /** @} */
+}

+ 7 - 0
Source/EditorManaged/Windows/Library/ProjectLibrary.cs

@@ -56,6 +56,11 @@ namespace bs.Editor
         /// </summary>
         internal static int InProgressImportCount { get { return Internal_GetInProgressImportCount(); } }
 
+        /// <summary>
+        /// Gets the import progress of all files currently being imported. Returns 0 if no import in progress.
+        /// </summary>
+        internal static float ImportProgressPercent { get; private set; }
+
         private static int totalFilesToImport;
 
         /// <summary>
@@ -321,11 +326,13 @@ namespace bs.Editor
                 if(totalFilesToImport > 0)
                     pct = numRemaining / (float)totalFilesToImport;
 
+                ImportProgressPercent = pct;
                 EditorApplication.SetStatusImporting(true, pct);
             }
             else
             {
                 totalFilesToImport = 0;
+                ImportProgressPercent = 0.0f;
                 EditorApplication.SetStatusImporting(false, 0.0f);
             }
         }