Sfoglia il codice sorgente

Save project on editor exit
Ask to save scene on editor exit
Selection highlight now shows properly on previously pinged entries in Library
You can now browse through Library folders without losing the object you are currently inspecting

BearishSun 10 anni fa
parent
commit
3209476868

+ 6 - 0
BansheeCore/Include/BsCoreApplication.h

@@ -49,6 +49,12 @@ namespace BansheeEngine
 			 */
 			 */
 			void stopMainLoop();
 			void stopMainLoop();
 
 
+			/**
+			 * @brief	Issues a request for the application to close. Application may choose to ignore the request
+			 * 			depending on the circumstances and the implementation.
+			 */
+			virtual void quitRequested();
+
 			/**
 			/**
 			 * @brief	Returns the main window that was created on application start-up.
 			 * @brief	Returns the main window that was created on application start-up.
 			 */
 			 */

+ 5 - 0
BansheeCore/Source/BsCoreApplication.cpp

@@ -259,6 +259,11 @@ namespace BansheeEngine
 		// a race condition we might run the loop one extra iteration which is acceptable
 		// a race condition we might run the loop one extra iteration which is acceptable
 	}
 	}
 
 
+	void CoreApplication::quitRequested()
+	{
+		stopMainLoop();
+	}
+
 	void CoreApplication::frameRenderingFinishedCallback()
 	void CoreApplication::frameRenderingFinishedCallback()
 	{
 	{
 		BS_LOCK_MUTEX(mFrameRenderingFinishedMutex);
 		BS_LOCK_MUTEX(mFrameRenderingFinishedMutex);

+ 1 - 1
BansheeCore/Source/Win32/BsWin32Platform.cpp

@@ -722,7 +722,7 @@ namespace BansheeEngine
 			break;
 			break;
 		case WM_CLOSE:
 		case WM_CLOSE:
 			{
 			{
-				gCoreApplication().stopMainLoop();
+				gCoreApplication().quitRequested();
 
 
 				return 0;
 				return 0;
 			}
 			}

+ 7 - 2
BansheeEditor/Include/BsEditorApplication.h

@@ -125,15 +125,20 @@ namespace BansheeEngine
 		virtual void onShutDown() override;
 		virtual void onShutDown() override;
 
 
 		/**
 		/**
-		 * @copydoc	Module::preUpdate
+		 * @copydoc	CoreApplication::preUpdate
 		 */
 		 */
 		virtual void preUpdate() override;
 		virtual void preUpdate() override;
 
 
 		/**
 		/**
-		 * @copydoc	Module::postUpdate
+		 * @copydoc	CoreApplication::postUpdate
 		 */
 		 */
 		virtual void postUpdate() override;
 		virtual void postUpdate() override;
 
 
+		/**
+		 * @copydoc	CoreApplication::quitRequested
+		 */
+		virtual void quitRequested() override;
+
 		/**
 		/**
 		 * @copydoc	Application::loadScriptSystem
 		 * @copydoc	Application::loadScriptSystem
 		 */
 		 */

+ 11 - 8
BansheeEditor/Source/BsEditorApplication.cpp

@@ -25,9 +25,7 @@
 #include "BsResources.h"
 #include "BsResources.h"
 #include "BsCoreSceneManager.h"
 #include "BsCoreSceneManager.h"
 #include "BsSplashScreen.h"
 #include "BsSplashScreen.h"
-
-// DEBUG ONLY
-#include "BsShader.h"
+#include "BsDynLib.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -102,11 +100,6 @@ namespace BansheeEngine
 
 
 		MainEditorWindow* mainWindow = MainEditorWindow::create(getPrimaryWindow());
 		MainEditorWindow* mainWindow = MainEditorWindow::create(getPrimaryWindow());
 		ScriptManager::instance().initialize();
 		ScriptManager::instance().initialize();
-
-#if BS_DEBUG_MODE
-		HShader dummyParsedShader = Importer::instance().import<Shader>(RUNTIME_DATA_PATH + "Raw\\Engine\\Shaders\\TestFX.bsl");
-		assert(dummyParsedShader != nullptr); // Ad hoc unit test
-#endif
 	}
 	}
 
 
 	void EditorApplication::onShutDown()
 	void EditorApplication::onShutDown()
@@ -160,6 +153,16 @@ namespace BansheeEngine
 		SplashScreen::hide();
 		SplashScreen::hide();
 	}
 	}
 
 
+	void EditorApplication::quitRequested()
+	{
+		typedef void(*QuitRequestedFunc)();
+
+		QuitRequestedFunc quitRequestedCall = (QuitRequestedFunc)mSBansheeEditorPlugin->getSymbol("quitRequested");
+
+		if (quitRequestedCall != nullptr)
+			quitRequestedCall();
+	}
+
 	Path EditorApplication::getEditorAssemblyPath() const
 	Path EditorApplication::getEditorAssemblyPath() const
 	{
 	{
 		Path assemblyPath = getBuiltinAssemblyFolder();
 		Path assemblyPath = getBuiltinAssemblyFolder();

+ 1 - 1
BansheeEditor/Source/BsGUIMenuBar.cpp

@@ -522,7 +522,7 @@ namespace BansheeEngine
 
 
 	void GUIMenuBar::onCloseClicked()
 	void GUIMenuBar::onCloseClicked()
 	{
 	{
-		gCoreApplication().stopMainLoop();
+		gCoreApplication().quitRequested();
 	}
 	}
 
 
 	void GUIMenuBar::refreshNonClientAreas()
 	void GUIMenuBar::refreshNonClientAreas()

+ 41 - 8
MBansheeEditor/EditorApplication.cs

@@ -223,41 +223,53 @@ namespace BansheeEditor
         /// Opens a dialog to allows the user to select a location where to save the current scene. If scene was previously
         /// Opens a dialog to allows the user to select a location where to save the current scene. If scene was previously
         /// saved it is instead automatically saved at the last location.
         /// saved it is instead automatically saved at the last location.
         /// </summary>
         /// </summary>
-        [MenuItem("File/Save Scene", ButtonModifier.Ctrl, ButtonCode.S, 10049)]
-        [ToolbarItem("Save Scene", ToolbarIcon.SaveScene, "", 1998)]
-        private static void SaveScene()
+        public static void SaveScene(Action onSuccess = null, Action onFailure = null)
         {
         {
             if (!string.IsNullOrEmpty(Scene.ActiveSceneUUID))
             if (!string.IsNullOrEmpty(Scene.ActiveSceneUUID))
             {
             {
                 string scenePath = ProjectLibrary.GetPath(Scene.ActiveSceneUUID);
                 string scenePath = ProjectLibrary.GetPath(Scene.ActiveSceneUUID);
                 SaveScene(scenePath);
                 SaveScene(scenePath);
+
+                if (onSuccess != null)
+                    onSuccess();
             }
             }
             else
             else
-                SaveSceneAs();
+                SaveSceneAs(onSuccess, onFailure);
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Opens a dialog to allows the user to select a location where to save the current scene.
         /// Opens a dialog to allows the user to select a location where to save the current scene.
         /// </summary>
         /// </summary>
-        [MenuItem("File/Save Scene As", 10048)]
-        private static void SaveSceneAs()
+        public static void SaveSceneAs(Action onSuccess = null, Action onFailure = null)
         {
         {
             string scenePath = "";
             string scenePath = "";
             if (BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "*.prefab", out scenePath))
             if (BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "*.prefab", out scenePath))
             {
             {
                 if (!PathEx.IsPartOf(scenePath, ProjectLibrary.ResourceFolder))
                 if (!PathEx.IsPartOf(scenePath, ProjectLibrary.ResourceFolder))
+                {
                     DialogBox.Open("Error", "The location must be inside the Resources folder of the project.",
                     DialogBox.Open("Error", "The location must be inside the Resources folder of the project.",
-                        DialogBox.Type.OK);
+                        DialogBox.Type.OK,
+                        x =>
+                        {
+                            if (onFailure != null)
+                                onFailure();
+                        });
+                }
                 else
                 else
                 {
                 {
                     // TODO - If path points to an existing non-scene asset or folder I should delete it otherwise
                     // TODO - If path points to an existing non-scene asset or folder I should delete it otherwise
                     //        Internal_SaveScene will silently fail.
                     //        Internal_SaveScene will silently fail.
 
 
                     scenePath += ".prefab";
                     scenePath += ".prefab";
-
                     SaveScene(scenePath);
                     SaveScene(scenePath);
                 }
                 }
             }
             }
+            else
+            {
+                // User canceled, so technically a success
+                if (onSuccess != null)
+                    onSuccess();
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -335,6 +347,25 @@ namespace BansheeEditor
             Internal_CreateProject(path);
             Internal_CreateProject(path);
         }
         }
 
 
+        /// <summary>
+        /// Wrapper for menu items for <see cref="SaveScene(Action, Action)"/> method
+        /// </summary>
+        [MenuItem("File/Save Scene", ButtonModifier.Ctrl, ButtonCode.S, 10049)]
+        [ToolbarItem("Save Scene", ToolbarIcon.SaveScene, "", 1998)]
+        private static void SaveSceneMenu()
+        {
+            SaveScene();
+        }
+
+        /// <summary>
+        /// Wrapper for menu items for <see cref="SaveSceneAs(Action, Action)"/> method
+        /// </summary>
+        [MenuItem("File/Save Scene As", 10048)]
+        private static void SaveSceneAsMenu()
+        {
+            SaveSceneAs();
+        }
+
         /// <summary>
         /// <summary>
         /// Opens a Project Window allowing you to browse for or create a project.
         /// Opens a Project Window allowing you to browse for or create a project.
         /// </summary>
         /// </summary>
@@ -352,11 +383,13 @@ namespace BansheeEditor
         [ToolbarItem("Save Project", ToolbarIcon.SaveProject, "", 1999)]
         [ToolbarItem("Save Project", ToolbarIcon.SaveProject, "", 1999)]
         public static void SaveProject()
         public static void SaveProject()
         {
         {
+            Debug.Log("Save project");
             foreach (var resourceUUID in dirtyResources)
             foreach (var resourceUUID in dirtyResources)
             {
             {
                 string path = ProjectLibrary.GetPath(resourceUUID);
                 string path = ProjectLibrary.GetPath(resourceUUID);
                 Resource resource = ProjectLibrary.Load<Resource>(path);
                 Resource resource = ProjectLibrary.Load<Resource>(path);
 
 
+                Debug.Log("Save project item: " + path + " - " + (resource != null));
                 if(resource != null)
                 if(resource != null)
                     ProjectLibrary.Save(resource);
                     ProjectLibrary.Save(resource);
             }
             }

+ 9 - 0
MBansheeEditor/Library/LibraryGUIContent.cs

@@ -243,6 +243,15 @@ namespace BansheeEditor
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Called every frame.
+        /// </summary>
+        public void Update()
+        {
+            for (int i = 0; i < entries.Length; i++)
+                entries[i].Update();
+        }
+
         /// <summary>
         /// <summary>
         /// Changes the visual representation of an element at the specified path as being hovered over.
         /// Changes the visual representation of an element at the specified path as being hovered over.
         /// </summary>
         /// </summary>

+ 44 - 10
MBansheeEditor/Library/LibraryGUIEntry.cs

@@ -40,6 +40,17 @@ namespace BansheeEditor
         private UnderlayState underlayState;
         private UnderlayState underlayState;
         private GUITextBox renameTextBox;
         private GUITextBox renameTextBox;
 
 
+        private bool delayedSelect;
+        private float delayedSelectTime;
+
+        /// <summary>
+        /// Bounds of the entry relative to part content area.
+        /// </summary>
+        public Rect2I Bounds
+        {
+            get { return bounds; }
+        }
+
         /// <summary>
         /// <summary>
         /// Constructs a new resource tile entry.
         /// Constructs a new resource tile entry.
         /// </summary>
         /// </summary>
@@ -112,11 +123,15 @@ namespace BansheeEditor
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Bounds of the entry relative to part content area.
+        /// Called every frame.
         /// </summary>
         /// </summary>
-        public Rect2I Bounds
+        public void Update()
         {
         {
-            get { return bounds; }
+            if (delayedSelect && Time.Elapsed > delayedSelectTime)
+            {
+                owner.Window.Select(path);
+                delayedSelect = false;
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -144,11 +159,13 @@ namespace BansheeEditor
             {
             {
                 CreateUnderlay();
                 CreateUnderlay();
                 underlay.SetTint(SELECTION_COLOR);
                 underlay.SetTint(SELECTION_COLOR);
+                underlayState = UnderlayState.Selected;
             }
             }
             else
             else
+            {
                 ClearUnderlay();
                 ClearUnderlay();
-
-            underlayState = UnderlayState.Selected;
+                underlayState = UnderlayState.None;
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -164,11 +181,13 @@ namespace BansheeEditor
             {
             {
                 CreateUnderlay();
                 CreateUnderlay();
                 underlay.SetTint(PING_COLOR);
                 underlay.SetTint(PING_COLOR);
+                underlayState = UnderlayState.Pinged;
             }
             }
             else
             else
+            {
                 ClearUnderlay();
                 ClearUnderlay();
-
-            underlayState = UnderlayState.Pinged;
+                underlayState = UnderlayState.None;
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -184,11 +203,13 @@ namespace BansheeEditor
             {
             {
                 CreateUnderlay();
                 CreateUnderlay();
                 underlay.SetTint(HOVER_COLOR);
                 underlay.SetTint(HOVER_COLOR);
+                underlayState = UnderlayState.Hovered;
             }
             }
             else
             else
+            {
                 ClearUnderlay();
                 ClearUnderlay();
-
-            underlayState = UnderlayState.Hovered;
+                underlayState = UnderlayState.None;
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -270,7 +291,18 @@ namespace BansheeEditor
         /// <param name="path">Project library path of the clicked entry.</param>
         /// <param name="path">Project library path of the clicked entry.</param>
         private void OnEntryClicked(string path)
         private void OnEntryClicked(string path)
         {
         {
-            owner.Window.Select(path);
+            LibraryEntry entry = ProjectLibrary.GetEntry(path);
+            if (entry != null && entry.Type == LibraryEntryType.Directory)
+            {
+                // If entry is a directory delay selection as it might be a double-click, in which case we want to keep
+                // whatever selection is active currently so that user can perform drag and drop with its inspector
+                // from the folder he is browsing to.
+
+                delayedSelect = true;
+                delayedSelectTime = Time.Elapsed + 0.5f;
+            }
+            else
+                owner.Window.Select(path);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -279,6 +311,8 @@ namespace BansheeEditor
         /// <param name="path">Project library path of the double-clicked entry.</param>
         /// <param name="path">Project library path of the double-clicked entry.</param>
         private void OnEntryDoubleClicked(string path)
         private void OnEntryDoubleClicked(string path)
         {
         {
+            delayedSelect = false;
+
             LibraryEntry entry = ProjectLibrary.GetEntry(path);
             LibraryEntry entry = ProjectLibrary.GetEntry(path);
             if (entry != null)
             if (entry != null)
             {
             {

+ 3 - 2
MBansheeEditor/Library/LibraryWindow.cs

@@ -350,6 +350,7 @@ namespace BansheeEditor
                 Refresh();
                 Refresh();
 
 
             dropTarget.Update();
             dropTarget.Update();
+            content.Update();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -583,6 +584,7 @@ namespace BansheeEditor
             }
             }
 
 
             selectionPaths = paths;
             selectionPaths = paths;
+            Ping("");
 
 
             if (selectionPaths != null)
             if (selectionPaths != null)
             {
             {
@@ -590,7 +592,6 @@ namespace BansheeEditor
                     content.MarkAsSelected(path, true);
                     content.MarkAsSelected(path, true);
             }
             }
 
 
-            Ping("");
             StopRename();
             StopRename();
 
 
             if (!onlyInternal)
             if (!onlyInternal)
@@ -610,7 +611,7 @@ namespace BansheeEditor
         internal void EnterDirectory(string directory)
         internal void EnterDirectory(string directory)
         {
         {
             currentDirectory = directory;
             currentDirectory = directory;
-            DeselectAll();
+            DeselectAll(true);
 
 
             Refresh();
             Refresh();
         }
         }

+ 45 - 1
MBansheeEditor/Program.cs

@@ -23,7 +23,7 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Called by the runtime when the editor is first started. Called after <see cref="OnInitialize"/>.
         /// Called by the runtime when the editor is first started. Called after <see cref="OnInitialize"/>.
         /// </summary>
         /// </summary>
-        static void OnEditorLoad()
+        static void OnEditorStartUp()
         {
         {
             if (EditorSettings.AutoLoadLastProject)
             if (EditorSettings.AutoLoadLastProject)
             {
             {
@@ -54,5 +54,49 @@ namespace BansheeEditor
         {
         {
             app.OnEditorUpdate();
             app.OnEditorUpdate();
         }
         }
+
+        /// <summary>
+        /// Attempts to save the current scene, and keeps retrying if failed or until user cancels.
+        /// </summary>
+        static void TrySaveScene()
+        {
+            Action success = () =>
+            {
+                EditorApplication.SaveProject();
+                EditorApplication.Quit();
+            };
+
+            EditorApplication.SaveScene(success, TrySaveScene);
+        }
+
+        /// <summary>
+        /// Called when the user requests that the editor shuts down. You must manually close the editor from this
+        /// method if you choose to accept the users request.
+        /// </summary>
+        static void OnEditorQuitRequested()
+        {
+            Action<DialogBox.ResultType> dialogCallback =
+            (result) =>
+            {
+                if (result == DialogBox.ResultType.Yes)
+                    TrySaveScene();
+                else if (result == DialogBox.ResultType.No)
+                {
+                    EditorApplication.SaveProject();
+                    EditorApplication.Quit();
+                }
+            };
+
+            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();
+            }
+        }
     }
     }
 }
 }

+ 7 - 0
SBansheeEditor/Include/BsEditorScriptManager.h

@@ -21,6 +21,13 @@ namespace BansheeEngine
 		 */
 		 */
 		void update();
 		void update();
 
 
+		/**
+		 * @brief	Called when the user requests the application to close.
+		 *
+		 * @note	Internal method.
+		 */
+		void quitRequested();
+
 	private:
 	private:
 		/**
 		/**
 		 * @brief	Triggers Program::OnInitialize callback. Should be called
 		 * @brief	Triggers Program::OnInitialize callback. Should be called

+ 10 - 3
SBansheeEditor/Source/BsEditorScriptManager.cpp

@@ -51,9 +51,9 @@ namespace BansheeEngine
 		mOnAssemblyRefreshDoneConn = ScriptObjectManager::instance().onRefreshComplete.connect(std::bind(&EditorScriptManager::onAssemblyRefreshDone, this));
 		mOnAssemblyRefreshDoneConn = ScriptObjectManager::instance().onRefreshComplete.connect(std::bind(&EditorScriptManager::onAssemblyRefreshDone, this));
 		triggerOnInitialize();
 		triggerOnInitialize();
 
 
-		// Trigger OnEditorLoad
-		const String EDITOR_ON_LOAD = "Program::OnEditorLoad";
-		mEditorAssembly->invoke(EDITOR_ON_LOAD);
+		// Trigger OnEditorStartUp
+		const String EDITOR_ON_STARTUP = "Program::OnEditorStartUp";
+		mEditorAssembly->invoke(EDITOR_ON_STARTUP);
 
 
 		// Initial update
 		// Initial update
 		mLastUpdateTime = gTime().getTime();
 		mLastUpdateTime = gTime().getTime();
@@ -97,6 +97,13 @@ namespace BansheeEngine
 		ScriptEditorApplication::update();
 		ScriptEditorApplication::update();
 	}
 	}
 
 
+	void EditorScriptManager::quitRequested()
+	{
+		// Trigger OnEditorQuitRequested
+		const String EDITOR_ON_QUITREQUESTED = "Program::OnEditorQuitRequested";
+		mEditorAssembly->invoke(EDITOR_ON_QUITREQUESTED);
+	}
+
 	void EditorScriptManager::triggerOnInitialize()
 	void EditorScriptManager::triggerOnInitialize()
 	{
 	{
 		const String ASSEMBLY_ENTRY_POINT = "Program::OnInitialize";
 		const String ASSEMBLY_ENTRY_POINT = "Program::OnInitialize";

+ 5 - 0
SBansheeEditor/Source/BsScriptEditorPlugin.cpp

@@ -23,4 +23,9 @@ namespace BansheeEngine
 	{
 	{
 		EditorScriptManager::instance().update();
 		EditorScriptManager::instance().update();
 	}
 	}
+
+	extern "C" BS_SCR_BED_EXPORT void quitRequested()
+	{
+		EditorScriptManager::instance().quitRequested();
+	}
 }
 }