Bläddra i källkod

Fixed an issue with drag and drop and SetCapture

Marko Pintera 12 år sedan
förälder
incheckning
09f3759d15

+ 3 - 0
CamelotClient/Include/BsEditorWidgetContainer.h

@@ -15,6 +15,8 @@ namespace BansheeEditor
 		void remove(EditorWidget& widget);
 		void insert(CM::UINT32 idx, EditorWidget& widget);
 
+		void hide(EditorWidget& widget);
+
 		void setSize(CM::UINT32 width, CM::UINT32 height);
 		void setPosition(CM::INT32 x, CM::INT32 y);
 
@@ -24,6 +26,7 @@ namespace BansheeEditor
 		void _notifyWidgetDestroyed(EditorWidget* widget);
 
 		boost::signal<void()> onWidgetClosed;
+		boost::signal<void()> onWidgetHidden;
 	private:
 		GUITabbedTitleBar* mTitleBar;
 		BS::GUIWidget* mParent;

+ 1 - 0
CamelotClient/Include/BsEditorWindow.h

@@ -24,5 +24,6 @@ namespace BansheeEditor
 
 		void updateSize();
 		void widgetRemoved();
+		void widgetHidden();
 	};
 }

+ 1 - 0
CamelotClient/Include/BsEditorWindowBase.h

@@ -20,6 +20,7 @@ namespace BansheeEditor
 		CM::UINT32 getHeight() const;
 
 		virtual void close();
+		void hide();
 	protected:
 		EditorWindowBase();
 		EditorWindowBase(CM::RenderWindowPtr renderWindow);

+ 3 - 0
CamelotClient/Include/CmTestTextSprite.h

@@ -15,5 +15,8 @@ namespace CamelotFramework
 		virtual void update();
 
 		void init(const BS::HCamera& camera, const String& text, CM::RenderTexturePtr sceneView);
+
+	private:
+		BS::GUILabel* mLabel;
 	};
 }

+ 51 - 6
CamelotClient/Source/BsEditorWidgetContainer.cpp

@@ -89,6 +89,37 @@ namespace BansheeEditor
 			widget._disable();
 	}
 
+	// Note: Hiding is used for a special purpose right now and there is no way to unhide a widget
+	// (But such functionally may be easily added)
+	void EditorWidgetContainer::hide(EditorWidget& widget)
+	{
+		INT32 widgetIdx = -1;
+		UINT32 curIdx = 0;
+		for(auto& curWidget : mWidgets)
+		{
+			if(curWidget == &widget)
+			{
+				widgetIdx = curIdx;
+				break;
+			}
+
+			curIdx++;
+		}
+
+		if(widgetIdx == -1)
+			return;
+
+		mTitleBar->removeTab(widgetIdx);
+
+		if(widgetIdx == mActiveWidget)
+		{
+			if(mWidgets.size() > 0)
+			{
+				setActiveWidget(0);
+			}
+		}
+	}
+
 	void EditorWidgetContainer::setSize(UINT32 width, UINT32 height)
 	{
 		// TODO - Title bar is always TitleBarHeight size, so what happens when the container area is smaller than that?
@@ -161,13 +192,18 @@ namespace BansheeEditor
 	void EditorWidgetContainer::tabDraggedOff(CM::UINT32 idx)
 	{
 		EditorWidget* widget = mWidgets[idx];
-		remove(*widget);
-		
+		hide(*widget);
+
 		// TODO - Hook up drag and drop texture
 		DragAndDropManager::instance().startDrag(HTexture(), (UINT32)DragAndDropType::EditorWidget, (void*)widget, boost::bind(&EditorWidgetContainer::tabDroppedCallback, this, _1));
 
-		if(!onWidgetClosed.empty())
-			onWidgetClosed();
+		// We don't want to remove the widget just yet. For now mark it as hidden in case
+		// user just drops it somewhere else.
+		// Note: This is primarily implemented because Windows doesn't like me destroying a window
+		// while I'm capturing mouse input (required for drag and drop outside of window borders). 
+		// So instead I just hide it and do the destroying after drag and drop is done.
+		if(!onWidgetHidden.empty())
+			onWidgetHidden();
 	}
 
 	void EditorWidgetContainer::tabDraggedOn(CM::UINT32 idx)
@@ -187,11 +223,20 @@ namespace BansheeEditor
 
 	void EditorWidgetContainer::tabDroppedCallback(bool wasDragProcessed)
 	{
-		if(!wasDragProcessed && DragAndDropManager::instance().getDragTypeId() == (UINT32)DragAndDropType::EditorWidget)
+		if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
+			return;
+
+		EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
+		draggedWidget->_changeParent(nullptr); // To ensure it doesn't get destroyed with the parent window
+		remove(*draggedWidget);
+
+		if(!onWidgetClosed.empty())
+			onWidgetClosed();
+
+		if(!wasDragProcessed)
 		{
 			EditorWindow* newWindow = EditorWindow::create();
 
-			EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
 			newWindow->widgets().add(*draggedWidget);
 
 			Int2 mousePos = Input::instance().getMousePosition();

+ 7 - 0
CamelotClient/Source/BsEditorWindow.cpp

@@ -13,6 +13,7 @@ namespace BansheeEditor
 		updateSize();
 
 		mWidgets->onWidgetClosed.connect(boost::bind(&EditorWindow::widgetRemoved, this));
+		mWidgets->onWidgetHidden.connect(boost::bind(&EditorWindow::widgetHidden, this));
 	}
 
 	EditorWindow::~EditorWindow()
@@ -43,6 +44,12 @@ namespace BansheeEditor
 			close();
 	}
 
+	void EditorWindow::widgetHidden()
+	{
+		if(mWidgets->getNumWidgets() == 1)
+			hide();
+	}
+
 	EditorWindow* EditorWindow::create()
 	{
 		return EditorWindowManager::instance().create();

+ 5 - 1
CamelotClient/Source/BsEditorWindowBase.cpp

@@ -4,7 +4,6 @@
 #include "CmRenderWindow.h"
 #include "CmRenderWindowManager.h"
 
-
 #include "BsEditorWindowManager.h"
 #include "BsCamera.h"
 #include "BsGUIWindowFrameWidget.h"
@@ -58,6 +57,11 @@ namespace BansheeEditor
 		EditorWindowManager::instance().destroy(this);
 	}
 
+	void EditorWindowBase::hide()
+	{
+		gMainSyncedCA().hideWindow(mRenderWindow);
+	}
+
 	void EditorWindowBase::construct(CM::RenderWindowPtr renderWindow)
 	{
 		mRenderWindow = renderWindow;

+ 6 - 0
CamelotClient/Source/CmTestTextSprite.cpp

@@ -16,6 +16,8 @@
 #include "BsGUILayout.h"
 #include "BsGUIViewport.h"
 #include "BsCamera.h"
+#include "CmInput.h"
+#include "CmPlatform.h"
 
 using namespace BansheeEngine;
 
@@ -38,10 +40,14 @@ namespace CamelotFramework
 
 		SpriteTexturePtr spriteTex = std::make_shared<SpriteTexture>(sceneView->getBindableColorTexture());
 		area->getLayout().addElement(GUITexture::create(*this, GUILayoutOptions::fixed(800, 600), spriteTex));
+		mLabel = GUILabel::create(*this, L"");
+		area->getLayout().addElement(mLabel);
 	}
 
 	void TestTextSprite::update()
 	{
+		WString value = toWString(toString(Input::instance().getMousePosition().x) + " - " + toString(Input::instance().getMousePosition().y));
 
+		mLabel->setText(value);
 	}
 }

+ 10 - 0
CamelotCore/Include/CmCoreThreadAccessor.h

@@ -272,6 +272,16 @@ namespace CamelotFramework
 			mCommandQueue->queue(boost::bind(&RenderWindow::endMove, renderWindow.get()));
 		}
 
+		void hideWindow(RenderWindowPtr& renderWindow)
+		{
+			mCommandQueue->queue(boost::bind(&RenderWindow::setHidden, renderWindow.get(), true));
+		}
+
+		void showWindow(RenderWindowPtr& renderWindow)
+		{
+			mCommandQueue->queue(boost::bind(&RenderWindow::setHidden, renderWindow.get(), false));
+		}
+
 		/**
 		 * @brief	Makes all the currently queued commands available to the core thread. They will be executed
 		 * 			as soon as the core thread is ready.

+ 2 - 1
CamelotCore/Include/CmRenderWindow.h

@@ -94,7 +94,7 @@ namespace CamelotFramework
         /**
          * @brief	Core method. Set the visibility state.
          */
-        virtual void setVisible(bool visible);
+        virtual void setHidden(bool hidden);
 
         /**
          * @brief	Core method. Alter the size of the window.
@@ -177,6 +177,7 @@ namespace CamelotFramework
 		INT32 mLeft;
 		INT32 mTop;
 		bool mHasFocus;
+		bool mHidden;
 
 		RENDER_WINDOW_DESC mDesc;
     };

+ 2 - 2
CamelotCore/Source/CmRenderWindow.cpp

@@ -33,7 +33,7 @@ THE SOFTWARE.
 namespace CamelotFramework 
 {
     RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc)
-        : RenderTarget(), mIsFullScreen(false), mDesc(desc), mHasFocus(false), mLeft(0), mTop(0)
+        : RenderTarget(), mIsFullScreen(false), mDesc(desc), mHasFocus(false), mLeft(0), mTop(0), mHidden(false)
     {
 
     }
@@ -43,7 +43,7 @@ namespace CamelotFramework
 		
 	}
 
-	void RenderWindow::setVisible(bool visible)
+	void RenderWindow::setHidden(bool hidden)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 	}

+ 0 - 1
CamelotD3D11RenderSystem/Include/CmD3D11RenderWindow.h

@@ -118,7 +118,6 @@ namespace CamelotFramework
 		bool	mIsExternal;
 		bool	mSizing;
 		bool	mClosed;
-		bool	mHidden;
 
 		// -------------------------------------------------------
 		// DirectX-specific

+ 4 - 1
CamelotD3D11RenderSystem/Source/CmD3D11RenderWindow.cpp

@@ -25,7 +25,6 @@ namespace CamelotFramework
 		, mIsExternal(false)
 		, mSizing(false)
 		, mClosed(false)
-		, mHidden(false)
 		, mSwitchingFullscreen(false)
 		, mDisplayFrequency(0)
 		, mRenderTargetView(nullptr)
@@ -555,6 +554,8 @@ namespace CamelotFramework
 
 	void D3D11RenderWindow::startResize(WindowResizeDirection direction)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		WPARAM dir = HTLEFT;
 		switch(direction)
 		{
@@ -598,6 +599,8 @@ namespace CamelotFramework
 
 	void D3D11RenderWindow::startMove()
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
 		HACK_SendLMBUpEvent();
 	}

+ 5 - 0
CamelotD3D9Renderer/Include/CmD3D9RenderWindow.h

@@ -43,6 +43,11 @@ namespace CamelotFramework
 		 */
 		void setFullscreen(bool fullScreen, UINT32 width, UINT32 height);
 
+		/**
+		 * @copydoc RenderWindow::setHidden
+		 */
+		void setHidden(bool hidden);
+
 		/**
 		 * @copydoc RenderWindow::isActive
 		 */

+ 18 - 0
CamelotD3D9Renderer/Source/CmD3D9RenderWindow.cpp

@@ -359,6 +359,20 @@ namespace CamelotFramework
 		}
 	} 
 
+	void D3D9RenderWindow::setHidden(bool hidden)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mHidden = hidden;
+		if (!mIsExternal)
+		{
+			if (hidden)
+				ShowWindow(mHWnd, SW_HIDE);
+			else
+				ShowWindow(mHWnd, SW_SHOWNORMAL);
+		}
+	}
+
 	bool D3D9RenderWindow::isActive() const
 	{
 		if (isFullScreen())
@@ -485,6 +499,8 @@ namespace CamelotFramework
 
 	void D3D9RenderWindow::startResize(WindowResizeDirection direction)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		WPARAM dir = HTLEFT;
 		switch(direction)
 		{
@@ -525,6 +541,8 @@ namespace CamelotFramework
 
 	void D3D9RenderWindow::startMove()
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
 		HACK_SendLMBUpEvent();
 	}

+ 5 - 0
CamelotGLRenderer/Include/CmWin32Window.h

@@ -43,6 +43,11 @@ namespace CamelotFramework
 		 */
 		void setFullscreen(bool fullScreen, UINT32 width, UINT32 height);
 
+		/**
+		 * @copydoc RenderWindow::setHidden
+		 */
+		void setHidden(bool hidden);
+
 		/**
 		 * @copydoc RenderWindow::isActive
 		 */

+ 18 - 0
CamelotGLRenderer/Source/CmWin32Window.cpp

@@ -731,8 +731,24 @@ namespace CamelotFramework
 		}
 	}
 
+	void Win32Window::setHidden(bool hidden)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mHidden = hidden;
+		if (!mIsExternal)
+		{
+			if (hidden)
+				ShowWindow(mHWnd, SW_HIDE);
+			else
+				ShowWindow(mHWnd, SW_SHOWNORMAL);
+		}
+	}
+
 	void Win32Window::startResize(WindowResizeDirection direction)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		WPARAM dir = HTLEFT;
 		switch(direction)
 		{
@@ -773,6 +789,8 @@ namespace CamelotFramework
 
 	void Win32Window::startMove()
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
 		HACK_SendLMBUpEvent();
 	}