Prechádzať zdrojové kódy

A lot more work on title bar drag and drop (currently not functional)

Marko Pintera 12 rokov pred
rodič
commit
07b6d5d4ef

+ 0 - 2
BansheeEngine/BansheeEngine.vcxproj

@@ -255,7 +255,6 @@
     <ClInclude Include="Include\BsGUIToggleGroup.h" />
     <ClInclude Include="Include\BsGUIToggleGroup.h" />
     <ClInclude Include="Include\BsGUIViewport.h" />
     <ClInclude Include="Include\BsGUIViewport.h" />
     <ClInclude Include="Include\BsGUIWindowFrame.h" />
     <ClInclude Include="Include\BsGUIWindowFrame.h" />
-    <ClInclude Include="Include\BsGUIWindowMover.h" />
     <ClInclude Include="Include\BsPrerequisites.h" />
     <ClInclude Include="Include\BsPrerequisites.h" />
     <ClInclude Include="Include\BsGUIElement.h" />
     <ClInclude Include="Include\BsGUIElement.h" />
     <ClInclude Include="Include\BsGUIElementStyle.h" />
     <ClInclude Include="Include\BsGUIElementStyle.h" />
@@ -315,7 +314,6 @@
     <ClCompile Include="Source\BsGUIToggleGroup.cpp" />
     <ClCompile Include="Source\BsGUIToggleGroup.cpp" />
     <ClCompile Include="Source\BsGUIWidget.cpp" />
     <ClCompile Include="Source\BsGUIWidget.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
-    <ClCompile Include="Source\BsGUIWindowMover.cpp" />
     <ClCompile Include="Source\BsImageSprite.cpp" />
     <ClCompile Include="Source\BsImageSprite.cpp" />
     <ClCompile Include="Source\BsSceneManager.cpp" />
     <ClCompile Include="Source\BsSceneManager.cpp" />
     <ClCompile Include="Source\BsGUIScrollArea.cpp" />
     <ClCompile Include="Source\BsGUIScrollArea.cpp" />

+ 0 - 6
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -150,9 +150,6 @@
     <ClInclude Include="Include\BsGUIInputBox.h">
     <ClInclude Include="Include\BsGUIInputBox.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\BsGUIWindowMover.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsGUICommandEvent.h">
     <ClInclude Include="Include\BsGUICommandEvent.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
@@ -302,9 +299,6 @@
     <ClCompile Include="Source\BsGUIMouseEvent.cpp">
     <ClCompile Include="Source\BsGUIMouseEvent.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="Source\BsGUIWindowMover.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsGUIButtonEvent.cpp">
     <ClCompile Include="Source\BsGUIButtonEvent.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>

+ 1 - 1
BansheeEngine/Include/BsDragAndDropManager.h

@@ -5,7 +5,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	class DragAndDropManager : public CM::Module<DragAndDropManager>
+	class BS_EXPORT DragAndDropManager : public CM::Module<DragAndDropManager>
 	{
 	{
 	public:
 	public:
 		DragAndDropManager();
 		DragAndDropManager();

+ 6 - 5
BansheeEngine/Include/BsGUIToggle.h

@@ -28,7 +28,7 @@ namespace BansheeEngine
 
 
 		boost::signal<void(bool)> onToggled;
 		boost::signal<void(bool)> onToggled;
 	protected:
 	protected:
-		~GUIToggle();
+		virtual ~GUIToggle();
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::getNumRenderElements()
 		 * @copydoc GUIElement::getNumRenderElements()
@@ -65,6 +65,11 @@ namespace BansheeEngine
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 
 
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const;
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const;
+	protected:
+		GUIToggle(GUIWidget& parent, const GUIElementStyle* style, const CM::WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUILayoutOptions& layoutOptions);
+
+		virtual bool mouseEvent(const GUIMouseEvent& ev);
+
 	private:
 	private:
 		std::shared_ptr<GUIToggleGroup> mToggleGroup;
 		std::shared_ptr<GUIToggleGroup> mToggleGroup;
 		ImageSprite* mImageSprite;
 		ImageSprite* mImageSprite;
@@ -74,9 +79,5 @@ namespace BansheeEngine
 
 
 		IMAGE_SPRITE_DESC mImageDesc;
 		IMAGE_SPRITE_DESC mImageDesc;
 		CM::WString mText;
 		CM::WString mText;
-
-		GUIToggle(GUIWidget& parent, const GUIElementStyle* style, const CM::WString& text, std::shared_ptr<GUIToggleGroup> toggleGroup, const GUILayoutOptions& layoutOptions);
-
-		virtual bool mouseEvent(const GUIMouseEvent& ev);
 	};
 	};
 }
 }

+ 0 - 1
BansheeEngine/Include/BsPrerequisites.h

@@ -34,7 +34,6 @@ namespace BansheeEngine
 	class GUITexture;
 	class GUITexture;
 	class GUIToggle;
 	class GUIToggle;
 	class GUIWindowFrame;
 	class GUIWindowFrame;
-	class GUIWindowMover;
 	class GUIInputBox;
 	class GUIInputBox;
 	class GUIScrollBarHandle;
 	class GUIScrollBarHandle;
 	class GUIScrollBarVert;
 	class GUIScrollBarVert;

+ 3 - 1
BansheeEngine/Source/BsGUIElement.cpp

@@ -200,6 +200,8 @@ namespace BansheeEngine
 	{
 	{
 		element->mParent.unregisterElement(element);
 		element->mParent.unregisterElement(element);
 
 
-		cm_delete<PoolAlloc>(element);
+		// Destroy at beginning of next frame, because we can't be sure that something isn't currently referencing
+		// this element (e..g GUIManager)
+		deferredCall(std::bind(&cm_delete<PoolAlloc, GUIElement>, element));
 	}
 	}
 }
 }

+ 8 - 2
CamelotClient/CamelotClient.cpp

@@ -43,6 +43,11 @@ using namespace CamelotFramework;
 using namespace BansheeEditor;
 using namespace BansheeEditor;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
 
 
+void editorUpdate()
+{
+	EditorWindowManager::instance().update();
+}
+
 int CALLBACK WinMain(
 int CALLBACK WinMain(
 	_In_  HINSTANCE hInstance,
 	_In_  HINSTANCE hInstance,
 	_In_  HINSTANCE hPrevInstance,
 	_In_  HINSTANCE hPrevInstance,
@@ -276,6 +281,8 @@ int CALLBACK WinMain(
 	MainEditorWindow* mainWindow = cm_new<MainEditorWindow>(gApplication().getPrimaryWindow());
 	MainEditorWindow* mainWindow = cm_new<MainEditorWindow>(gApplication().getPrimaryWindow());
 	EditorWindowManager::startUp(cm_new<EditorWindowManager>());
 	EditorWindowManager::startUp(cm_new<EditorWindowManager>());
 
 
+	CM::gApplication().mainLoopCallback.connect(&editorUpdate);
+
 	/************************************************************************/
 	/************************************************************************/
 	/* 							  EDITOR INIT END                    		*/
 	/* 							  EDITOR INIT END                    		*/
 	/************************************************************************/
 	/************************************************************************/
@@ -331,5 +338,4 @@ int CALLBACK WinMain(
 	gBansheeApp().shutDown();
 	gBansheeApp().shutDown();
 
 
 	return 0;
 	return 0;
-}
-
+}

+ 4 - 0
CamelotClient/CamelotClient.vcxproj

@@ -263,7 +263,9 @@
     <ClInclude Include="Include\BsEditorWindowBase.h" />
     <ClInclude Include="Include\BsEditorWindowBase.h" />
     <ClInclude Include="Include\BsEditorWindowManager.h" />
     <ClInclude Include="Include\BsEditorWindowManager.h" />
     <ClInclude Include="Include\BsGUITabbedTitleBar.h" />
     <ClInclude Include="Include\BsGUITabbedTitleBar.h" />
+    <ClInclude Include="Include\BsGUITabButton.h" />
     <ClInclude Include="Include\BsGUIWindowFrameWidget.h" />
     <ClInclude Include="Include\BsGUIWindowFrameWidget.h" />
+    <ClInclude Include="Include\BsGUIWindowMover.h" />
     <ClInclude Include="Include\BsMainEditorWindow.h" />
     <ClInclude Include="Include\BsMainEditorWindow.h" />
     <ClInclude Include="Include\CmDebugCamera.h" />
     <ClInclude Include="Include\CmDebugCamera.h" />
     <ClInclude Include="Include\CmTestTextSprite.h" />
     <ClInclude Include="Include\CmTestTextSprite.h" />
@@ -281,7 +283,9 @@
     <ClCompile Include="Source\BsEditorWindowBase.cpp" />
     <ClCompile Include="Source\BsEditorWindowBase.cpp" />
     <ClCompile Include="Source\BsEditorWindowManager.cpp" />
     <ClCompile Include="Source\BsEditorWindowManager.cpp" />
     <ClCompile Include="Source\BsGUITabbedTitleBar.cpp" />
     <ClCompile Include="Source\BsGUITabbedTitleBar.cpp" />
+    <ClCompile Include="Source\BsGUITabButton.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrameWidget.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrameWidget.cpp" />
+    <ClCompile Include="Source\BsGUIWindowMover.cpp" />
     <ClCompile Include="Source\BsMainEditorWindow.cpp" />
     <ClCompile Include="Source\BsMainEditorWindow.cpp" />
     <ClCompile Include="Source\CmDebugCamera.cpp" />
     <ClCompile Include="Source\CmDebugCamera.cpp" />
     <ClCompile Include="Source\CmTestTextSprite.cpp" />
     <ClCompile Include="Source\CmTestTextSprite.cpp" />

+ 12 - 0
CamelotClient/CamelotClient.vcxproj.filters

@@ -72,6 +72,12 @@
     <ClInclude Include="Include\CmDebugCamera.h">
     <ClInclude Include="Include\CmDebugCamera.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsGUITabButton.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGUIWindowMover.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
     <ClCompile Include="stdafx.cpp">
@@ -119,5 +125,11 @@
     <ClCompile Include="Source\CmDebugCamera.cpp">
     <ClCompile Include="Source\CmDebugCamera.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsGUITabButton.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGUIWindowMover.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 7 - 0
CamelotClient/Include/BsEditorPrerequisites.h

@@ -10,7 +10,14 @@ namespace BansheeEditor
 	class EditorWidget;
 	class EditorWidget;
 	class EditorWidgetContainer;
 	class EditorWidgetContainer;
 	class GUITabbedTitleBar;
 	class GUITabbedTitleBar;
+	class GUITabButton;
+	class GUIWindowMover;
 	class EditorWindowManager;
 	class EditorWindowManager;
 	class DockManager;
 	class DockManager;
 	class MainEditorWindow;
 	class MainEditorWindow;
+
+	enum class DragAndDropType
+	{
+		EditorWidget = 10000
+	};
 }
 }

+ 5 - 1
CamelotClient/Include/BsEditorWidgetContainer.h

@@ -13,7 +13,7 @@ namespace BansheeEditor
 
 
 		void add(EditorWidget& widget);
 		void add(EditorWidget& widget);
 		void remove(EditorWidget& widget);
 		void remove(EditorWidget& widget);
-		void move(EditorWidget& widget, CM::UINT32 newPosition);
+		void insert(CM::UINT32 idx, EditorWidget& widget);
 
 
 		void setSize(CM::UINT32 width, CM::UINT32 height);
 		void setSize(CM::UINT32 width, CM::UINT32 height);
 		void setPosition(CM::INT32 x, CM::INT32 y);
 		void setPosition(CM::INT32 x, CM::INT32 y);
@@ -37,5 +37,9 @@ namespace BansheeEditor
 		void setActiveWidget(CM::UINT32 idx);
 		void setActiveWidget(CM::UINT32 idx);
 		void tabActivated(CM::UINT32 idx);
 		void tabActivated(CM::UINT32 idx);
 		void tabClosed(CM::UINT32 idx);
 		void tabClosed(CM::UINT32 idx);
+		void tabDraggedOff(CM::UINT32 idx);
+		void tabDraggedOn(CM::UINT32 idx);
+
+		void tabDroppedCallback(bool wasDragProcessed);
 	};
 	};
 }
 }

+ 1 - 1
CamelotClient/Include/BsEditorWindow.h

@@ -10,7 +10,7 @@ namespace BansheeEditor
 	public:
 	public:
 		virtual ~EditorWindow();
 		virtual ~EditorWindow();
 
 
-		EditorWidgetContainer& getWidgets() const { return *mWidgets; }
+		EditorWidgetContainer& widgets() const { return *mWidgets; }
 
 
 		static EditorWindow* create();
 		static EditorWindow* create();
 
 

+ 2 - 0
CamelotClient/Include/BsEditorWindowManager.h

@@ -14,7 +14,9 @@ namespace BansheeEditor
 		EditorWindow* create();
 		EditorWindow* create();
 		void destroy(EditorWindowBase* window);
 		void destroy(EditorWindowBase* window);
 
 
+		void update();
 	protected:
 	protected:
 		CM::Vector<EditorWindowBase*>::type mEditorWindows;
 		CM::Vector<EditorWindowBase*>::type mEditorWindows;
+		CM::Vector<EditorWindowBase*>::type mScheduledForDestruction;
 	};
 	};
 }
 }

+ 34 - 0
CamelotClient/Include/BsGUITabButton.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIToggle.h"
+#include "BsGUIToggleGroup.h"
+#include "BsImageSprite.h"
+#include "boost/signal.hpp"
+
+namespace BansheeEditor
+{
+	class GUITabButton : public BS::GUIToggle
+	{
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUITabButton* create(BS::GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUIElementStyle* style = nullptr);
+		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUIElementStyle* style = nullptr);
+	
+		CM::UINT32 getIndex() const { return mIndex; }
+
+		boost::signal<void(CM::UINT32)> onDragged;
+	protected:
+		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
+
+	private:
+		GUITabbedTitleBar* mTitleBar;
+		CM::UINT32 mIndex;
+		CM::Int2 mDragStartPosition;
+
+		static const CM::UINT32 DRAG_MIN_DISTANCE;
+
+		GUITabButton(BS::GUIWidget& parent, const BS::GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const CM::WString& text, const BS::GUILayoutOptions& layoutOptions);
+	};
+}

+ 9 - 15
CamelotClient/Include/BsGUITabbedTitleBar.h

@@ -1,22 +1,12 @@
 #pragma once
 #pragma once
 
 
-#include "BsPrerequisites.h"
+#include "BsEditorPrerequisites.h"
 #include <boost/signal.hpp>
 #include <boost/signal.hpp>
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
 	class GUITabbedTitleBar
 	class GUITabbedTitleBar
 	{
 	{
-		struct Tab
-		{
-			Tab(BS::GUIToggle* _toggle, CM::UINT32 _index)
-				:toggle(_toggle), index(_index)
-			{ }
-
-			BS::GUIToggle* toggle;
-			CM::UINT32 index;
-		};
-
 	public:
 	public:
 		GUITabbedTitleBar(BS::GUIWidget* parent);
 		GUITabbedTitleBar(BS::GUIWidget* parent);
 		virtual ~GUITabbedTitleBar();
 		virtual ~GUITabbedTitleBar();
@@ -30,9 +20,11 @@ namespace BansheeEditor
 
 
 		boost::signal<void(CM::UINT32)> onTabActivated;
 		boost::signal<void(CM::UINT32)> onTabActivated;
 		boost::signal<void(CM::UINT32)> onTabClosed;
 		boost::signal<void(CM::UINT32)> onTabClosed;
+		boost::signal<void(CM::UINT32)> onTabDraggedOff;
+		boost::signal<void(CM::UINT32)> onTabDraggedOn;
 	protected:
 	protected:
-		CM::Vector<BS::GUIWindowMover*>::type mDragDropElements;
-		CM::Vector<Tab>::type mTabButtons;
+		CM::Vector<GUIWindowMover*>::type mDragDropElements;
+		CM::Vector<GUITabButton*>::type mTabButtons;
 
 
 		CM::UINT32 mUniqueTabIdx;
 		CM::UINT32 mUniqueTabIdx;
 		CM::UINT32 mActiveTabIdx;
 		CM::UINT32 mActiveTabIdx;
@@ -42,11 +34,13 @@ namespace BansheeEditor
 		BS::GUILayout* mMainLayout;
 		BS::GUILayout* mMainLayout;
 		BS::GUIButton* mMinBtn;
 		BS::GUIButton* mMinBtn;
 		BS::GUIButton* mCloseBtn;
 		BS::GUIButton* mCloseBtn;
-		BS::GUIWindowMover* mLastDropElement;
+		GUIWindowMover* mLastDropElement;
 
 
 		void tabToggled(CM::UINT32 tabIdx);
 		void tabToggled(CM::UINT32 tabIdx);
 		void tabClosed();
 		void tabClosed();
+		void tabDraggedOff(CM::UINT32 tabIdx);
+		void tabDraggedOn(CM::UINT32 tabIdx);
 
 
-		CM::INT32 uniqueIdxToIdx(CM::UINT32 uniqueIdx) const;
+		CM::INT32 uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const;
 	};
 	};
 }
 }

+ 65 - 0
CamelotClient/Include/BsGUIWindowMover.h

@@ -0,0 +1,65 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElement.h"
+#include "BsImageSprite.h"
+#include <boost/signals.hpp>
+
+namespace BansheeEditor
+{
+	class GUIWindowMover : public BS::GUIElement
+	{
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIWindowMover* create(BS::GUIWidget& parent, const BS::GUIElementStyle* style = nullptr);
+		static GUIWindowMover* create(BS::GUIWidget& parent, const BS::GUILayoutOptions& layoutOptions, const BS::GUIElementStyle* style = nullptr);
+
+		void setFocused(bool focused);
+
+		boost::signal<void()> onDraggedItemDropped;
+	protected:
+		~GUIWindowMover();
+
+		/**
+		 * @copydoc GUIElement::getNumRenderElements()
+		 */
+		virtual CM::UINT32 getNumRenderElements() const;
+
+		/**
+		 * @copydoc GUIElement::getMaterial()
+		 */
+		virtual const CM::HMaterial& getMaterial(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::getNumQuads()
+		 */
+		virtual CM::UINT32 getNumQuads(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::fillBuffer()
+		 */
+		virtual void fillBuffer(CM::UINT8* vertices, CM::UINT8* uv, CM::UINT32* indices, CM::UINT32 startingQuad, 
+			CM::UINT32 maxNumQuads, CM::UINT32 vertexStride, CM::UINT32 indexStride, CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::updateRenderElementsInternal()
+		 */
+		virtual void updateRenderElementsInternal();
+
+		/**
+		 * @copydoc GUIElement::updateBounds()
+		 */
+		virtual void updateBounds();
+
+		virtual CM::UINT32 _getOptimalWidth() const;
+		virtual CM::UINT32 _getOptimalHeight() const;
+	private:
+		BS::ImageSprite* mImageSprite;
+		BS::IMAGE_SPRITE_DESC mDesc;
+
+		GUIWindowMover(BS::GUIWidget& parent, const BS::GUIElementStyle* style, const BS::GUILayoutOptions& layoutOptions);
+
+		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
+	};
+}

+ 8 - 3
CamelotClient/Source/BsEditorWidget.cpp

@@ -49,10 +49,15 @@ namespace BansheeEditor
 	{
 	{
 		if(mParent != parent) 
 		if(mParent != parent) 
 		{
 		{
-			if(mParent == nullptr)
-				mContent = GUIArea::create(parent->getParentWidget(), 0, 0, 0, 0, 10000);
+			if(parent != nullptr)
+			{
+				if(mParent == nullptr)
+					mContent = GUIArea::create(parent->getParentWidget(), 0, 0, 0, 0, 10000);
+				else
+					mContent->changeParentWidget(parent->getParentWidget());
+			}
 			else
 			else
-				mContent->changeParentWidget(parent->getParentWidget());
+				mContent = nullptr;
 
 
 			mParent = parent;
 			mParent = parent;
 		}
 		}

+ 66 - 16
CamelotClient/Source/BsEditorWidgetContainer.cpp

@@ -1,6 +1,10 @@
 #include "BsEditorWidgetContainer.h"
 #include "BsEditorWidgetContainer.h"
 #include "BsGUITabbedTitleBar.h"
 #include "BsGUITabbedTitleBar.h"
 #include "BsEditorWidget.h"
 #include "BsEditorWidget.h"
+#include "BsDragAndDropManager.h"
+#include "BsEditorWindow.h"
+#include "CmMath.h"
+#include "CmInput.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
@@ -15,6 +19,8 @@ namespace BansheeEditor
 		mTitleBar = cm_new<GUITabbedTitleBar>(parent);
 		mTitleBar = cm_new<GUITabbedTitleBar>(parent);
 		mTitleBar->onTabActivated.connect(boost::bind(&EditorWidgetContainer::tabActivated, this, _1));
 		mTitleBar->onTabActivated.connect(boost::bind(&EditorWidgetContainer::tabActivated, this, _1));
 		mTitleBar->onTabClosed.connect(boost::bind(&EditorWidgetContainer::tabClosed, this, _1));
 		mTitleBar->onTabClosed.connect(boost::bind(&EditorWidgetContainer::tabClosed, this, _1));
+		mTitleBar->onTabDraggedOff.connect(boost::bind(&EditorWidgetContainer::tabDraggedOff, this, _1));
+		mTitleBar->onTabDraggedOn.connect(boost::bind(&EditorWidgetContainer::tabDraggedOn, this, _1));
 	}
 	}
 
 
 	EditorWidgetContainer::~EditorWidgetContainer()
 	EditorWidgetContainer::~EditorWidgetContainer()
@@ -29,20 +35,7 @@ namespace BansheeEditor
 
 
 	void EditorWidgetContainer::add(EditorWidget& widget)
 	void EditorWidgetContainer::add(EditorWidget& widget)
 	{
 	{
-		for(auto& curWidget : mWidgets)
-		{
-			if(curWidget == &widget)
-				return;
-		}
-
-		mTitleBar->addTab(widget.getName());
-		mWidgets.push_back(&widget);
-		widget._changeParent(this);
-
-		if(mActiveWidget == -1)
-			setActiveWidget((UINT32)mWidgets.size() - 1);
-		else
-			widget._disable();
+		insert((UINT32)mWidgets.size(), widget);
 	}
 	}
 
 
 	void EditorWidgetContainer::remove(EditorWidget& widget)
 	void EditorWidgetContainer::remove(EditorWidget& widget)
@@ -65,6 +58,7 @@ namespace BansheeEditor
 
 
 		mWidgets.erase(mWidgets.begin() + widgetIdx);
 		mWidgets.erase(mWidgets.begin() + widgetIdx);
 		mTitleBar->removeTab((UINT32)widgetIdx);
 		mTitleBar->removeTab((UINT32)widgetIdx);
+		widget._changeParent(nullptr);
 
 
 		if(widgetIdx == mActiveWidget)
 		if(widgetIdx == mActiveWidget)
 		{
 		{
@@ -75,9 +69,24 @@ namespace BansheeEditor
 		}
 		}
 	}
 	}
 
 
-	void EditorWidgetContainer::move(EditorWidget& widget, UINT32 newPosition)
+	void EditorWidgetContainer::insert(CM::UINT32 idx, EditorWidget& widget)
 	{
 	{
-		// TODO
+		for(auto& curWidget : mWidgets)
+		{
+			if(curWidget == &widget)
+				return;
+		}
+
+		idx = Math::Clamp(idx, 0U, (UINT32)mWidgets.size());
+
+		mTitleBar->insertTab(idx, widget.getName());
+		mWidgets.insert(mWidgets.begin() + idx, &widget);
+		widget._changeParent(this);
+
+		if(mActiveWidget == -1)
+			setActiveWidget((UINT32)mWidgets.size() - 1);
+		else
+			widget._disable();
 	}
 	}
 
 
 	void EditorWidgetContainer::setSize(UINT32 width, UINT32 height)
 	void EditorWidgetContainer::setSize(UINT32 width, UINT32 height)
@@ -149,6 +158,47 @@ namespace BansheeEditor
 			onWidgetClosed();
 			onWidgetClosed();
 	}
 	}
 
 
+	void EditorWidgetContainer::tabDraggedOff(CM::UINT32 idx)
+	{
+		EditorWidget* widget = mWidgets[idx];
+		remove(*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();
+	}
+
+	void EditorWidgetContainer::tabDraggedOn(CM::UINT32 idx)
+	{
+#if CM_DEBUG_MODE
+		if(!DragAndDropManager::instance().isDragInProgress())
+			CM_EXCEPT(InternalErrorException, "Tab drag and drop reported but no drag in progress.");
+
+		if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
+			CM_EXCEPT(InternalErrorException, "Tab drag and drop reported but drag type is invalid.");
+#endif
+
+		EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
+
+		insert(idx, *draggedWidget);
+	}
+
+	void EditorWidgetContainer::tabDroppedCallback(bool wasDragProcessed)
+	{
+		if(!wasDragProcessed)
+		{
+			EditorWindow* newWindow = EditorWindow::create();
+
+			EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
+			newWindow->widgets().add(*draggedWidget);
+
+			Int2 mousePos = Input::instance().getMousePosition();
+			newWindow->setPosition(mousePos.x, mousePos.y);
+		}
+	}
+
 	void EditorWidgetContainer::_notifyWidgetDestroyed(EditorWidget* widget)
 	void EditorWidgetContainer::_notifyWidgetDestroyed(EditorWidget* widget)
 	{
 	{
 		for(auto& curWidget : mWidgets)
 		for(auto& curWidget : mWidgets)

+ 18 - 1
CamelotClient/Source/BsEditorWindowManager.cpp

@@ -28,7 +28,24 @@ namespace BansheeEditor
 		if(iterFind == end(mEditorWindows))
 		if(iterFind == end(mEditorWindows))
 			CM_EXCEPT(InternalErrorException, "Trying to destroy an editor window that's not registered in the window manager.");
 			CM_EXCEPT(InternalErrorException, "Trying to destroy an editor window that's not registered in the window manager.");
 
 
+		auto iterFind2 = std::find(begin(mScheduledForDestruction), end(mScheduledForDestruction), window);
+		
+		if(iterFind2 == end(mScheduledForDestruction))
+			mScheduledForDestruction.push_back(window);
+
 		mEditorWindows.erase(iterFind);
 		mEditorWindows.erase(iterFind);
-		cm_delete(window);
+	}
+
+	void EditorWindowManager::update()
+	{
+		// Editor window destroy is deferred to this point, otherwise we risk
+		// destroying a window while it's still being used (situation that was happening with GUIManager)
+		
+		for(auto& windowToDestroy : mScheduledForDestruction)
+		{
+			cm_delete(windowToDestroy);
+		}
+
+		mScheduledForDestruction.clear();
 	}
 	}
 }
 }

+ 72 - 0
CamelotClient/Source/BsGUITabButton.cpp

@@ -0,0 +1,72 @@
+#include "BsGUITabButton.h"
+#include "BsGUIWidget.h"
+#include "BsGUISkin.h"
+#include "BsGUILayoutOptions.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUITabbedTitleBar.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	const CM::UINT32 GUITabButton::DRAG_MIN_DISTANCE = 3;
+
+	const String& GUITabButton::getGUITypeName()
+	{
+		static String name = "TabButton";
+		return name;
+	}
+
+	GUITabButton::GUITabButton(GUIWidget& parent, const GUIElementStyle* style, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUILayoutOptions& layoutOptions)
+		:GUIToggle(parent, style, text, nullptr, layoutOptions), mTitleBar(titleBar), mIndex(index)
+	{
+
+	}
+
+	GUITabButton* GUITabButton::create(GUIWidget& parent, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, text, getDefaultLayoutOptions(style));
+	}
+
+	GUITabButton* GUITabButton::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, GUITabbedTitleBar* titleBar, CM::UINT32 index, const WString& text, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, titleBar, index, text, layoutOptions);
+	}
+
+	bool GUITabButton::mouseEvent(const GUIMouseEvent& ev)
+	{
+		bool eventProcessed = GUIToggle::mouseEvent(ev);
+
+		if(ev.getType() == GUIMouseEventType::MouseDragStart)
+		{
+			mDragStartPosition = ev.getPosition();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDrag)
+		{
+			UINT32 dist = mDragStartPosition.manhattanDist(ev.getPosition());
+
+			if(dist > DRAG_MIN_DISTANCE)
+			{
+				if(!onDragged.empty())
+					onDragged(mIndex);
+			}
+		}
+
+		return eventProcessed;
+	}
+}

+ 33 - 10
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -3,7 +3,7 @@
 #include "BsGUILayout.h"
 #include "BsGUILayout.h"
 #include "BsGUITexture.h"
 #include "BsGUITexture.h"
 #include "BsGUIButton.h"
 #include "BsGUIButton.h"
-#include "BsGUIToggle.h"
+#include "BsGUITabButton.h"
 #include "BsGUISpace.h"
 #include "BsGUISpace.h"
 #include "BsGUIWindowMover.h"
 #include "BsGUIWindowMover.h"
 #include "BsEngineGUI.h"
 #include "BsEngineGUI.h"
@@ -55,7 +55,7 @@ namespace BansheeEditor
 
 
 		for(auto& tabButton : mTabButtons)
 		for(auto& tabButton : mTabButtons)
 		{
 		{
-			GUIElement::destroy(tabButton.toggle);
+			GUIElement::destroy(tabButton);
 		}
 		}
 
 
 		for(auto& dragDropButton : mDragDropElements)
 		for(auto& dragDropButton : mDragDropElements)
@@ -71,14 +71,17 @@ namespace BansheeEditor
 
 
 	void GUITabbedTitleBar::insertTab(UINT32 idx, const CM::WString& name)
 	void GUITabbedTitleBar::insertTab(UINT32 idx, const CM::WString& name)
 	{
 	{
-		GUIToggle* newTabToggle = GUIToggle::create(*mParentWidget, name, EngineGUI::instance().getSkin().getStyle("TabbedBarBtn"));
+		GUITabButton* newTabToggle = GUITabButton::create(*mParentWidget, this, mUniqueTabIdx, name, EngineGUI::instance().getSkin().getStyle("TabbedBarBtn"));
 		GUIWindowMover* newDragDropElement = GUIWindowMover::create(*mParentWidget, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));
 		GUIWindowMover* newDragDropElement = GUIWindowMover::create(*mParentWidget, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));
 
 
 		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size());
 		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size());
 
 
 		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
 		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
+		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOff, this, _1));
 
 
-		mTabButtons.insert(mTabButtons.begin() + idx, Tab(newTabToggle, mUniqueTabIdx));
+		newDragDropElement->onDraggedItemDropped.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOn, this, mUniqueTabIdx));
+
+		mTabButtons.insert(mTabButtons.begin() + idx, newTabToggle);
 		mDragDropElements.insert(mDragDropElements.begin() + idx, newDragDropElement);
 		mDragDropElements.insert(mDragDropElements.begin() + idx, newDragDropElement);
 
 
 		mMainLayout->insertElement(idx * 2, newTabToggle);
 		mMainLayout->insertElement(idx * 2, newTabToggle);
@@ -94,7 +97,7 @@ namespace BansheeEditor
 
 
 		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size() - 1);
 		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size() - 1);
 
 
-		GUIElement::destroy(mTabButtons[idx].toggle);
+		GUIElement::destroy(mTabButtons[idx]);
 		GUIElement::destroy(mDragDropElements[idx]);
 		GUIElement::destroy(mDragDropElements[idx]);
 
 
 		mTabButtons.erase(mTabButtons.begin() + idx);
 		mTabButtons.erase(mTabButtons.begin() + idx);
@@ -115,7 +118,7 @@ namespace BansheeEditor
 
 
 	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
 	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
 	{
 	{
-		INT32 idx = uniqueIdxToIdx(tabIdx);
+		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
 		if(idx != -1)
 		if(idx != -1)
 		{
 		{
 			if(!onTabActivated.empty())
 			if(!onTabActivated.empty())
@@ -127,25 +130,45 @@ namespace BansheeEditor
 
 
 	void GUITabbedTitleBar::tabClosed()
 	void GUITabbedTitleBar::tabClosed()
 	{
 	{
-		INT32 idx = uniqueIdxToIdx(mActiveTabIdx);
+		INT32 idx = uniqueIdxToSeqIdx(mActiveTabIdx);
 		if(idx != -1)
 		if(idx != -1)
 		{
 		{
 			removeTab(idx);
 			removeTab(idx);
 
 
 			if(mTabButtons.size() > 0)
 			if(mTabButtons.size() > 0)
-				mActiveTabIdx = mTabButtons[0].index;
+				mActiveTabIdx = mTabButtons[0]->getIndex();
 
 
 			if(!onTabClosed.empty())
 			if(!onTabClosed.empty())
 				onTabClosed(idx);
 				onTabClosed(idx);
 		}
 		}
 	}
 	}
 
 
-	CM::INT32 GUITabbedTitleBar::uniqueIdxToIdx(CM::UINT32 uniqueIdx) const
+	void GUITabbedTitleBar::tabDraggedOff(CM::UINT32 tabIdx)
+	{
+		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
+		if(idx != -1)
+		{
+			if(!onTabDraggedOff.empty())
+				onTabDraggedOff(idx);
+		}
+	}
+
+	void GUITabbedTitleBar::tabDraggedOn(CM::UINT32 tabIdx)
+	{
+		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
+		if(idx != -1)
+		{
+			if(!onTabDraggedOn.empty())
+				onTabDraggedOn(idx + 1);
+		}
+	}
+
+	CM::INT32 GUITabbedTitleBar::uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const
 	{
 	{
 		UINT32 idx = 0;
 		UINT32 idx = 0;
 		for(auto& tab : mTabButtons)
 		for(auto& tab : mTabButtons)
 		{
 		{
-			if(tab.index == uniqueIdx)
+			if(tab->getIndex() == uniqueIdx)
 				return idx;
 				return idx;
 
 
 			idx++;
 			idx++;

+ 154 - 0
CamelotClient/Source/BsGUIWindowMover.cpp

@@ -0,0 +1,154 @@
+#include "BsGUIWindowMover.h"
+#include "CmApplication.h"
+#include "CmTexture.h"
+#include "BsGUIWidget.h"
+#include "BsGUISkin.h"
+#include "BsSpriteTexture.h"
+#include "BsGUILayoutOptions.h"
+#include "BsGUIMouseEvent.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	const String& GUIWindowMover::getGUITypeName()
+	{
+		static String name = "WindowMover";
+		return name;
+	}
+
+	GUIWindowMover::GUIWindowMover(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
+		:GUIElement(parent, style, layoutOptions)
+	{
+		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
+
+		mDesc.texture = mStyle->normal.texture;
+
+		if(mDesc.texture != nullptr)
+		{
+			mDesc.width = mDesc.texture->getTexture()->getWidth();
+			mDesc.height = mDesc.texture->getTexture()->getHeight();
+		}
+
+		mDesc.borderLeft = mStyle->border.left;
+		mDesc.borderRight = mStyle->border.right;
+		mDesc.borderTop = mStyle->border.top;
+		mDesc.borderBottom = mStyle->border.bottom;
+	}
+
+	GUIWindowMover::~GUIWindowMover()
+	{
+		cm_delete<PoolAlloc>(mImageSprite);
+	}
+
+	GUIWindowMover* GUIWindowMover::create(GUIWidget& parent, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIWindowMover, PoolAlloc>()) GUIWindowMover(parent, style, getDefaultLayoutOptions(style));
+	}
+
+	GUIWindowMover* GUIWindowMover::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIWindowMover, PoolAlloc>()) GUIWindowMover(parent, style, layoutOptions);
+	}
+
+	UINT32 GUIWindowMover::getNumRenderElements() const
+	{
+		return mImageSprite->getNumRenderElements();
+	}
+
+	const HMaterial& GUIWindowMover::getMaterial(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getMaterial(renderElementIdx);
+	}
+
+	UINT32 GUIWindowMover::getNumQuads(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getNumQuads(renderElementIdx);
+	}
+
+	void GUIWindowMover::updateRenderElementsInternal()
+	{		
+		mDesc.width = mWidth;
+		mDesc.height = mHeight;
+
+		mImageSprite->update(mDesc);
+		
+		GUIElement::updateRenderElementsInternal();
+	}
+
+	void GUIWindowMover::updateBounds()
+	{
+		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+	}
+
+	UINT32 GUIWindowMover::_getOptimalWidth() const
+	{
+		if(mDesc.texture != nullptr)
+		{
+			return mDesc.texture->getTexture()->getWidth();
+		}
+
+		return 0;
+	}
+
+	UINT32 GUIWindowMover::_getOptimalHeight() const
+	{
+		if(mDesc.texture != nullptr)
+		{
+			return mDesc.texture->getTexture()->getHeight();
+		}
+
+		return 0;
+	}
+
+	void GUIWindowMover::fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, vertexStride, indexStride, renderElementIdx, mOffset, mClipRect);
+	}
+
+	void GUIWindowMover::setFocused(bool focused)
+	{
+		if(focused)
+			mDesc.texture = mStyle->focused.texture;
+		else
+			mDesc.texture = mStyle->normal.texture;
+
+		markContentAsDirty();
+	}
+
+	bool GUIWindowMover::mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseDown)
+		{
+			RenderWindow* window = _getParentWidget().getOwnerWindow();
+			RenderWindowPtr windowPtr = std::static_pointer_cast<RenderWindow>(window->getThisPtr());
+
+			gMainCA().startMove(windowPtr);
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragAndDropDropped)
+		{
+			if(!onDraggedItemDropped.empty())
+				onDraggedItemDropped();
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 1 - 1
CamelotClient/Source/DbgEditorWidget1.cpp

@@ -97,7 +97,7 @@ namespace BansheeEditor
 		EditorWindow* newWindow = EditorWindow::create();
 		EditorWindow* newWindow = EditorWindow::create();
 
 
 		DbgEditorWidget1* newWidget = new (cm_alloc<DbgEditorWidget1>()) DbgEditorWidget1();
 		DbgEditorWidget1* newWidget = new (cm_alloc<DbgEditorWidget1>()) DbgEditorWidget1();
-		newWindow->getWidgets().add(*newWidget);
+		newWindow->widgets().add(*newWidget);
 		newWidget->initialize();
 		newWidget->initialize();
 		Instance = newWidget;
 		Instance = newWidget;
 
 

+ 1 - 1
CamelotClient/Source/DbgEditorWidget2.cpp

@@ -57,7 +57,7 @@ namespace BansheeEditor
 		EditorWindow* newWindow = EditorWindow::create();
 		EditorWindow* newWindow = EditorWindow::create();
 
 
 		DbgEditorWidget2* newWidget = new (cm_alloc<DbgEditorWidget2>()) DbgEditorWidget2();
 		DbgEditorWidget2* newWidget = new (cm_alloc<DbgEditorWidget2>()) DbgEditorWidget2();
-		newWindow->getWidgets().add(*newWidget);
+		newWindow->widgets().add(*newWidget);
 		newWidget->initialize();
 		newWidget->initialize();
 		Instance = newWidget;
 		Instance = newWidget;
 
 

+ 5 - 0
CamelotUtility/Include/CmInt2.h

@@ -43,6 +43,11 @@ namespace CamelotFramework
 			std::swap(y, other.y);
 			std::swap(y, other.y);
 		}
 		}
 
 
+		inline unsigned int manhattanDist(const Int2& other)
+		{
+			return (unsigned int)fabs(float(other.x - x)) + (unsigned int)fabs(float(other.y - y));
+		}
+
 		inline int operator [] ( const size_t i ) const
 		inline int operator [] ( const size_t i ) const
         {
         {
             assert( i < 2 );
             assert( i < 2 );

+ 10 - 35
EditorWindowDock.txt

@@ -1,25 +1,12 @@
-DockManager implementation plan:
- - DockManager main class
-   - When empty make sure it has a GUIElement that covers its entire space so it can catch and drop events. Will likely need a special transparent GUIElement?
-   - Has a reference to one DockContainer, which is initially empty
-      - DockContainer can have two DockContainer children, or one EditorWidgetContainer child (maybe make a container base class? - optional)
-	  - DockContainer should probably contain a GUIElement which can receieve events
-	     - This would mean extending GUIManager so it can send events to top level elements, and if they don't process them, send them one level lower?
-	  - Resizing a DockContainer resizes all child DockContainers recursively (and EditorWidgetContainers)
-	  - If DockContainer has DockContainer children then it also contains a  GUIElement resizer (just an empty space, in the direction of the split)
-	    - Moving the element allows you to resize the two child DockContainers
- - When last element is removed from EditorWidgetContainer make sure to notify the parent
- - Make main render window frameless
-   - Implement MainEditorWindow from EditorWindowBase
-   - Make sure MainEditorWindow holds a DockManager reference and resizes it with the window
-
-DockContainer biggest issues:
- - How do I draw the drag and drop overlay??
- - How do I detect mouse input yet still let it through to child widget
-
-FIRST CREATE DOCK CONTAINER WITHOUT DRAG AND DROP SUPPORT
-
-Make sure to test everything thoroughly - right now I have tested very little
+Add icons to drag and drop
+Move WindowMover to BansheeEditor
+
+end drag doesn't get called unless mouse is released over a window
+When I do drop it over a window an exception with layout happens
+
+Add highlight to WindowMover so I can know when I'm mousing over it with a dragged window in hand
+
+
 Drag and drop manager currently ignores the provided icon, but it should use it as a cursor
 Drag and drop manager currently ignores the provided icon, but it should use it as a cursor
 
 
 Prevent docking if available size is less than 20 pixels, otherwise there might be some weirdness
 Prevent docking if available size is less than 20 pixels, otherwise there might be some weirdness
@@ -27,19 +14,7 @@ Prevent docking if available size is less than 20 pixels, otherwise there might
 GUIViewport:
 GUIViewport:
  - MAJOR TODO - GUIViewport updateRenderElementsInternal only gets called when contents change, but viewport should update even if 
  - MAJOR TODO - GUIViewport updateRenderElementsInternal only gets called when contents change, but viewport should update even if 
     only its offset changes (normally that just marks the mesh as modified, which doesn't result in a call to updateRenderElementsInternal)
     only its offset changes (normally that just marks the mesh as modified, which doesn't result in a call to updateRenderElementsInternal)
-
- Make the drop overlays a transparent gray
- - Their opacity increases when highlighted
- - Make their borders use polygon AA (or line AA with a different color)
-
-Figure out how to render the overlay on top of all viewports, even when main window viewport gets rendered first.
- - I'm guessing the DockManager will require its own Camera (doesn't make sense it would require camera, but it's fairly lightweight so it would be an okay solution)
- - Then the camera viewport and target change as the dock overlay moves
- - OR
- - Have the inner camera viewport render first onto a render target, and then draw the main GUI
-   - This MIGHT be the proper way to do it. Otherwise my game viewport is always limited to whatever format is the main window render target set to.
- - OR
- - Render inner camera viewport first, and use stencil to mark the area as non-renderable?
+	- UPDATE: I don't use GUIViewport anymore
 
 
 ------------------------
 ------------------------