소스 검색

Fixed modal windows so they stay in front even if new non-modal windows spawn

Marko Pintera 11 년 전
부모
커밋
a45a814ea7

+ 1 - 1
BansheeCore/Include/Win32/BSWin32PlatformData.h

@@ -30,7 +30,7 @@ namespace BansheeEngine
 		Map<const RenderWindowCore*, WindowNonClientAreaData> mNonClientAreas;
 
 		bool mIsTrackingMouse = false;
-		Stack<RenderWindowCore*> mModalWindowStack;
+		Vector<RenderWindowCore*> mModalWindowStack;
 
 		NativeDropTargetData mDropTargets;
 

+ 26 - 19
BansheeCore/Source/Win32/BsWin32Platform.cpp

@@ -583,7 +583,7 @@ namespace BansheeEngine
 			{
 				if(!mData->mModalWindowStack.empty())
 				{
-					RenderWindowCore* curModalWindow = mData->mModalWindowStack.top();
+					RenderWindowCore* curModalWindow = mData->mModalWindowStack.back();
 
 					UINT64 curHwnd;
 					curModalWindow->getCustomAttribute("WINDOW", &curHwnd);
@@ -603,7 +603,24 @@ namespace BansheeEngine
 					}
 				}
 
-				mData->mModalWindowStack.push(newWindow);
+				mData->mModalWindowStack.push_back(newWindow);
+			}
+			else
+			{
+				// A non-modal window was opened while another modal one is open:
+				// immediately deactivate it and make sure the modal windows stay on top
+				if (!mData->mModalWindowStack.empty())
+				{
+					EnableWindow((HWND)hWnd, FALSE);
+
+					for (auto window : mData->mModalWindowStack)
+					{
+						UINT64 curHwnd;
+						window->getCustomAttribute("WINDOW", &curHwnd);
+
+						BringWindowToTop((HWND)curHwnd);
+					}
+				}
 			}
 
 			return 0;
@@ -630,31 +647,21 @@ namespace BansheeEngine
 				bool reenableWindows = false;
 				if (!mData->mModalWindowStack.empty())
 				{
-					if (mData->mModalWindowStack.top() == win) // This is the most common case, top-most modal was closed
-					{
-						mData->mModalWindowStack.pop();
-					}
-					else // Possibly some other window was closed somehow, see if it was modal and remove from stack if it is
+					// Start from back because the most common case is closing the top-most modal window
+					for (auto iter = mData->mModalWindowStack.rbegin(); iter != mData->mModalWindowStack.rend(); ++iter)
 					{
-						Stack<RenderWindowCore*> newStack;
-
-						while (!mData->mModalWindowStack.empty())
+						if (*iter == win)
 						{
-							RenderWindowCore* curWindow = mData->mModalWindowStack.top();
-							mData->mModalWindowStack.pop();
+							auto iterFwd = std::next(iter).base(); // erase doesn't accept reverse iter, so convert
 
-							if(curWindow == win)
-								continue;
-
-							newStack.push(curWindow);
+							mData->mModalWindowStack.erase(iterFwd);
+							break;
 						}
-
-						mData->mModalWindowStack = newStack;
 					}
 
 					if (!mData->mModalWindowStack.empty()) // Enable next modal window
 					{
-						RenderWindowCore* curModalWindow = mData->mModalWindowStack.top();
+						RenderWindowCore* curModalWindow = mData->mModalWindowStack.back();
 
 						UINT64 curHwnd;
 						curModalWindow->getCustomAttribute("WINDOW", &curHwnd);

+ 2 - 0
MBansheeEditor/EditorApplication.cs

@@ -95,6 +95,8 @@ namespace BansheeEditor
             SceneObject gizmoDbgObject = new SceneObject("GizmoDebug");
             gizmoDbgObject.AddComponent<DbgGizmoComponent>();
 
+            ModalWindow.Open<ProgressBar>();
+
             // DEBUG ONLY END
         }
 

+ 1 - 0
SBansheeEditor/Include/BsScriptModalWindow.h

@@ -57,6 +57,7 @@ namespace BansheeEngine
 		bool createManagedInstance();
 		void releaseManagedInstance();
 
+		void initialize(ScriptModalWindow* parent);
 		void update();
 		void reloadMonoTypes(MonoClass* windowClass);
 		void triggerOnInitialize();

+ 8 - 1
SBansheeEditor/Source/BsScriptModalWindow.cpp

@@ -47,6 +47,7 @@ namespace BansheeEngine
 
 		ManagedModalWindow* modalWindow = bs_new<ManagedModalWindow>(strNamespace, strTypeName);
 		ScriptModalWindow* nativeInstance = new (bs_alloc<ScriptModalWindow>()) ScriptModalWindow(modalWindow);
+		modalWindow->initialize(nativeInstance);
 
 		mono_runtime_object_init(modalWindow->getManagedInstance()); // Construct it
 		modalWindow->triggerOnInitialize();
@@ -157,7 +158,8 @@ namespace BansheeEngine
 
 	ManagedModalWindow::ManagedModalWindow(const String& ns, const String& type)
 		:ModalWindow(), mNamespace(ns), mTypename(type), mUpdateThunk(nullptr), mManagedInstance(nullptr), 
-		mOnInitializeThunk(nullptr), mOnDestroyThunk(nullptr), mOnWindowResizedMethod(nullptr), mGCHandle(0)
+		mOnInitializeThunk(nullptr), mOnDestroyThunk(nullptr), mOnWindowResizedMethod(nullptr), mGCHandle(0),
+		mScriptParent(nullptr)
 	{
 		createManagedInstance();
 	}
@@ -228,6 +230,11 @@ namespace BansheeEngine
 		}
 	}
 
+	void ManagedModalWindow::initialize(ScriptModalWindow* parent)
+	{
+		mScriptParent = parent;
+	}
+
 	void ManagedModalWindow::update()
 	{
 		if (mUpdateThunk != nullptr && mManagedInstance != nullptr)