Просмотр исходного кода

Added drag event
Added window frame with resize cursors

Marko Pintera 12 лет назад
Родитель
Сommit
2e3ec543cc

+ 1 - 1
BansheeEngine/BansheeEngine.vcxproj

@@ -158,6 +158,7 @@
     <ClInclude Include="Include\BsGUISpace.h" />
     <ClInclude Include="Include\BsGUITexture.h" />
     <ClInclude Include="Include\BsGUIToggle.h" />
+    <ClInclude Include="Include\BsGUIWindowFrame.h" />
     <ClInclude Include="Include\BsPrerequisites.h" />
     <ClInclude Include="Include\BsGUIElement.h" />
     <ClInclude Include="Include\BsGUIElementStyle.h" />
@@ -167,7 +168,6 @@
     <ClInclude Include="Include\BsGUIMouseEvent.h" />
     <ClInclude Include="Include\BsGUISkin.h" />
     <ClInclude Include="Include\BsGUIWidget.h" />
-    <ClInclude Include="Include\BsGUIWindowFrame.h" />
     <ClInclude Include="Include\BsImageSprite.h" />
     <ClInclude Include="Include\BsSceneManager.h" />
     <ClInclude Include="Include\BsSprite.h" />

+ 6 - 6
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -63,9 +63,6 @@
     <ClInclude Include="Include\BsGUISkin.h">
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsGUIWindowFrame.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsImageSprite.h">
       <Filter>Header Files\2D</Filter>
     </ClInclude>
@@ -150,6 +147,9 @@
     <ClInclude Include="Include\BsGUIToggle.h">
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGUIWindowFrame.h">
+      <Filter>Header Files\GUI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -212,9 +212,6 @@
     <ClCompile Include="Source\BsGLBuiltinMaterialFactory.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsGUIWindowFrame.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsEngineGUI.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
@@ -245,5 +242,8 @@
     <ClCompile Include="Source\BsGUIToggle.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIWindowFrame.cpp">
+      <Filter>Source Files\GUI</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 5 - 0
BansheeEngine/Include/BsGUIArea.h

@@ -24,6 +24,11 @@ namespace BansheeEngine
 		CM::UINT16 getDepth() const { return mDepth; }
 		void setDepth(CM::UINT16 depth) { mDepth = depth; }
 
+		CM::UINT32 x() const { return mX; }
+		CM::UINT32 y() const { return mY; }
+		CM::UINT32 width() const { return mWidth; }
+		CM::UINT32 height() const { return mHeight; }
+
 		void _update();
 	private:
 		friend class GUIWidget;

+ 1 - 5
BansheeEngine/Include/BsGUIElement.h

@@ -93,6 +93,7 @@ namespace BansheeEngine
 
 		CM::UINT32 _getWidth() const { return mWidth; }
 		CM::UINT32 _getHeight() const { return mHeight; }
+		CM::Int2 _getOffset() const { return mOffset; }
 		virtual CM::UINT32 _getOptimalWidth() const = 0;
 		virtual CM::UINT32 _getOptimalHeight() const = 0;
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const { return _getDepth(); }
@@ -107,11 +108,6 @@ namespace BansheeEngine
 
 		static void _destroyInternal(GUIElement* element);
 
-		//  onMouseMove
-		//	onMousePress
-		//	onMouseReleased
-		//	onKeyPressed
-		//	onKeyReleased
 	protected:
 		virtual void updateRenderElementsInternal() = 0;
 

+ 6 - 1
BansheeEngine/Include/BsGUIManager.h

@@ -41,11 +41,16 @@ namespace BansheeEngine
 		GUIWidget* mMouseOverWidget;
 		GUIElement* mMouseOverElement;
 
+		GUIWidget* mDraggedWidget;
+		GUIElement* mDraggedElement;
+
 		bool mSeparateMeshesByWidget;
 		bool mLastFrameButtonState[CM::MB_Count];
-		CM::Int2 mLastCursorPos;
+		CM::Int2 mLastCursorLocalPos;
 
 		void updateMeshes();
 		void updateInput();
+
+		CM::Int2 getWidgetRelativeCursorPos(const GUIWidget& widget);
 	};
 }

+ 6 - 1
BansheeEngine/Include/BsGUIMouseEvent.h

@@ -12,7 +12,8 @@ namespace BansheeEngine
 		MouseOut,
 		MouseDown,
 		MouseUp,
-		MouseMove
+		MouseMove,
+		MouseDrag
 	};
 
 	class BS_EXPORT GUIMouseEvent
@@ -25,8 +26,12 @@ namespace BansheeEngine
 		const CM::Int2& getPosition() const { return mPosition; }
 		GUIMouseEventType getType() const { return mType; }
 		CM::MouseButton getButton() const { return mButton; }
+		CM::Int2 getDragAmount() const { return mDragAmount; }
+
+		void _setDragAmount(CM::Int2 dragAmount) { mDragAmount = dragAmount; }
 	private:
 		CM::Int2 mPosition;
+		CM::Int2 mDragAmount;
 		GUIMouseEventType mType;
 		CM::MouseButton mButton;
 	};

+ 7 - 1
BansheeEngine/Include/BsGUIWidget.h

@@ -6,6 +6,8 @@
 #include "CmVector3.h"
 #include "CmQuaternion.h"
 
+#include <boost/signals/connection.hpp>
+
 namespace BansheeEngine
 {
 	class BS_EXPORT GUIWidget : public CM::Component
@@ -65,7 +67,8 @@ namespace BansheeEngine
 	private:
 		void updateBounds() const;
 
-		void ownerWindowResized(CM::RenderWindow* window);
+		virtual void ownerWindowResized(CM::RenderWindow* window);
+		virtual void ownerWindowFocusChanged(CM::RenderWindow* window);
 
 		virtual void update();
 
@@ -79,6 +82,9 @@ namespace BansheeEngine
 		CM::Quaternion mLastFrameRotation;
 		CM::Vector3 mLastFrameScale;
 
+		boost::signals::connection mWinResizeConn;
+		boost::signals::connection mWinFocusConn;
+
 		mutable bool mWidgetIsDirty;
 		mutable CM::Rect mBounds;
 		mutable CM::vector<CM::HMesh>::type mCachedMeshes;

+ 3 - 0
BansheeEngine/Include/BsGUIWindowFrame.h

@@ -47,7 +47,10 @@ namespace BansheeEngine
 	private:
 		ImageSprite* mImageSprite;
 		IMAGE_SPRITE_DESC mDesc;
+		bool mResizeCursorSet;
 
 		GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
+
+		virtual bool mouseEvent(const GUIMouseEvent& ev);
 	};
 }

+ 1 - 2
BansheeEngine/Source/BsEngineGUI.cpp

@@ -2,7 +2,6 @@
 #include "BsGUIElementStyle.h"
 
 #include "BsGUILabel.h"
-#include "BsGUIWindowFrame.h"
 #include "BsGUIButton.h"
 #include "BsTextSprite.h"
 #include "BsSpriteTexture.h"
@@ -83,7 +82,7 @@ namespace BansheeEngine
 		windowFrameStyle.border.top = 1;
 		windowFrameStyle.border.bottom = 1;
 
-		mSkin.setStyle(GUIWindowFrame::getGUITypeName(), windowFrameStyle);
+		mSkin.setStyle("WindowFrame", windowFrameStyle);
 
 		// Button
 		HTexture buttonNormalTex = static_resource_cast<Texture>(Importer::instance().import(ButtonNormalTex));

+ 64 - 20
BansheeEngine/Source/BsGUIManager.cpp

@@ -42,7 +42,7 @@ namespace BansheeEngine
 	};
 
 	GUIManager::GUIManager()
-		:mMouseOverElement(nullptr), mMouseOverWidget(nullptr), mSeparateMeshesByWidget(true)
+		:mMouseOverElement(nullptr), mMouseOverWidget(nullptr), mSeparateMeshesByWidget(true), mDraggedElement(nullptr), mDraggedWidget(nullptr)
 	{
 		for(int i = 0; i < MB_Count; i++)
 			mLastFrameButtonState[i] = false;
@@ -416,7 +416,8 @@ namespace BansheeEngine
 #endif
 		GUIWidget* widgetInFocus = nullptr;
 		GUIElement* topMostElement = nullptr;
-		UINT32 topMostDepth = std::numeric_limits<UINT32>::max();
+		Int2 screenPos;
+		Int2 localPos;
 
 		for(auto& widget : mWidgets)
 		{
@@ -429,7 +430,6 @@ namespace BansheeEngine
 			}
 		}
 
-		Int2 screenPos;
 		if(widgetInFocus != nullptr)
 		{
 			const RenderWindow* window = widgetInFocus->getOwnerWindow();
@@ -437,6 +437,7 @@ namespace BansheeEngine
 			screenPos = Cursor::getWindowPosition(*window);
 			Vector4 vecScreenPos((float)screenPos.x, (float)screenPos.y, 0.0f, 1.0f);
 
+			UINT32 topMostDepth = std::numeric_limits<UINT32>::max();
 			for(auto& widget : mWidgets)
 			{
 				if(widget->getOwnerWindow() == window && widget->inBounds(screenPos))
@@ -444,7 +445,7 @@ namespace BansheeEngine
 					const Matrix4& worldTfrm = widget->SO()->getWorldTfrm();
 
 					Vector4 vecLocalPos = worldTfrm.inverse() * vecScreenPos;
-					Int2 localPos(Math::RoundToInt(vecLocalPos.x), Math::RoundToInt(vecLocalPos.y));
+					localPos = Int2(Math::RoundToInt(vecLocalPos.x), Math::RoundToInt(vecLocalPos.y));
 
 					vector<GUIElement*>::type sortedElements = widget->getElements();
 					std::sort(sortedElements.begin(), sortedElements.end(), 
@@ -476,31 +477,52 @@ namespace BansheeEngine
 			if(mMouseOverElement != nullptr)
 			{
 				// Send MouseOut event
-				const RenderWindow* window = mMouseOverWidget->getOwnerWindow();
-				Int2 oldScreenPos = Cursor::getWindowPosition(*window);
+				if(mDraggedElement == nullptr || mMouseOverElement == mDraggedElement)
+				{
+					Int2 curLocalPos = getWidgetRelativeCursorPos(*mMouseOverWidget);
 
-				GUIMouseEvent event(GUIMouseEventType::MouseOut, oldScreenPos); // TODO - This pos will be wrong as it might be related to completely other window
-				mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+					GUIMouseEvent event(GUIMouseEventType::MouseOut, curLocalPos);
+					mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+				}
 			}
 
 			if(topMostElement != nullptr)
 			{
 				// Send MouseOver event
-				GUIMouseEvent event(GUIMouseEventType::MouseOver, screenPos);
-				widgetInFocus->_mouseEvent(topMostElement, event);
+				if(mDraggedElement == nullptr || topMostElement == mDraggedElement)
+				{
+					GUIMouseEvent event(GUIMouseEventType::MouseOver, localPos);
+					widgetInFocus->_mouseEvent(topMostElement, event);
+				}
 			}
+		}
+
+		if(mDraggedElement != nullptr)
+		{
+			Int2 curLocalPos = getWidgetRelativeCursorPos(*mDraggedWidget);
 
-			mMouseOverElement = topMostElement;
-			mMouseOverWidget = widgetInFocus;
+			if(mLastCursorLocalPos != curLocalPos)
+			{
+				GUIMouseEvent event(GUIMouseEventType::MouseDrag, curLocalPos);
+				event._setDragAmount(curLocalPos - mLastCursorLocalPos);
+				mDraggedWidget->_mouseEvent(mDraggedElement, event);
+
+				mLastCursorLocalPos = curLocalPos;
+			}
 		}
 
-		if(mMouseOverElement != nullptr)
+		if(topMostElement != nullptr)
 		{
 			// Send MouseMove event
-			if(mLastCursorPos != screenPos)
+			if(mDraggedElement == nullptr)
 			{
-				GUIMouseEvent event(GUIMouseEventType::MouseMove, screenPos);
-				mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+				if(mLastCursorLocalPos != localPos)
+				{
+					GUIMouseEvent event(GUIMouseEventType::MouseMove, localPos);
+					widgetInFocus->_mouseEvent(topMostElement, event);
+
+					mLastCursorLocalPos = localPos;
+				}
 			}
 
 			// Send MouseDown and MouseUp events
@@ -511,18 +533,40 @@ namespace BansheeEngine
 				{
 					if(buttonDown)
 					{
-						GUIMouseEvent event(GUIMouseEventType::MouseDown, screenPos, (MouseButton)i);
-						mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+						GUIMouseEvent event(GUIMouseEventType::MouseDown, localPos, (MouseButton)i);
+						widgetInFocus->_mouseEvent(topMostElement, event);
+
+						mDraggedElement = topMostElement;
+						mDraggedWidget = widgetInFocus;
 					}
 					else
 					{
-						GUIMouseEvent event(GUIMouseEventType::MouseUp, screenPos, (MouseButton)i);
-						mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+						GUIMouseEvent event(GUIMouseEventType::MouseUp, localPos, (MouseButton)i);
+						widgetInFocus->_mouseEvent(topMostElement, event);
+
+						mDraggedElement = nullptr;
+						mDraggedWidget = nullptr;
 					}
 
 					mLastFrameButtonState[i] = buttonDown;
 				}
 			}
 		}
+
+		mMouseOverElement = topMostElement;
+		mMouseOverWidget = widgetInFocus;
+	}
+
+	Int2 GUIManager::getWidgetRelativeCursorPos(const GUIWidget& widget)
+	{
+		const RenderWindow* window = widget.getOwnerWindow();
+		Int2 screenPos = Cursor::getWindowPosition(*window);
+
+		const Matrix4& worldTfrm = widget.SO()->getWorldTfrm();
+
+		Vector4 vecLocalPos = worldTfrm.inverse() * Vector4((float)screenPos.x, (float)screenPos.y, 0.0f, 1.0f);
+		Int2 curLocalPos(Math::RoundToInt(vecLocalPos.x), Math::RoundToInt(vecLocalPos.y));
+
+		return curLocalPos;
 	}
 }

+ 10 - 1
BansheeEngine/Source/BsGUIWidget.cpp

@@ -46,6 +46,9 @@ namespace BansheeEngine
 		}
 
 		mElements.clear();
+
+		mWinResizeConn.disconnect();
+		mWinFocusConn.disconnect();
 	}
 
 	void GUIWidget::initialize(Viewport* target, const RenderWindow* ownerWindow)
@@ -61,7 +64,8 @@ namespace BansheeEngine
 
 		GUIManager::instance().registerWidget(this);
 
-		mOwnerWindow->onWindowMovedOrResized.connect(boost::bind(&GUIWidget::ownerWindowResized, this, _1));
+		mWinResizeConn = mOwnerWindow->onWindowMovedOrResized.connect(boost::bind(&GUIWidget::ownerWindowResized, this, _1));
+		mWinFocusConn = mOwnerWindow->onWindowFocusChanged.connect(boost::bind(&GUIWidget::ownerWindowFocusChanged, this, _1));
 	}
 
 	void GUIWidget::update()
@@ -244,4 +248,9 @@ namespace BansheeEngine
 			area->notifyWindowResized(window->getWidth(), window->getHeight());
 		}
 	}
+
+	void GUIWidget::ownerWindowFocusChanged(RenderWindow* window)
+	{
+
+	}
 }

+ 115 - 1
BansheeEngine/Source/BsGUIWindowFrame.cpp

@@ -4,6 +4,8 @@
 #include "BsGUISkin.h"
 #include "BsSpriteTexture.h"
 #include "BsGUILayoutOptions.h"
+#include "BsGUIMouseEvent.h"
+#include "CmCursor.h"
 #include "CmTexture.h"
 
 using namespace CamelotFramework;
@@ -17,7 +19,7 @@ namespace BansheeEngine
 	}
 
 	GUIWindowFrame::GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
-		:GUIElement(parent, style, layoutOptions)
+		:GUIElement(parent, style, layoutOptions), mResizeCursorSet(false)
 	{
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 
@@ -113,4 +115,116 @@ namespace BansheeEngine
 	{
 		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, vertexStride, indexStride, renderElementIdx);
 	}
+
+	bool GUIWindowFrame::mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseMove || ev.getType() == GUIMouseEventType::MouseDrag)
+		{
+			Int2 offset = _getOffset();
+			Int2 cursorPos = ev.getPosition();
+
+			INT32 x0 = offset.x;
+			INT32 x1 = offset.x + 3;
+			INT32 x2 = offset.x + _getWidth() - 3;
+			INT32 x3 = offset.x + _getWidth();
+
+			INT32 y0 = offset.y;
+			INT32 y1 = offset.y + 3;
+			INT32 y2 = offset.y + _getHeight() - 3;
+			INT32 y3 = offset.y + _getHeight();
+
+			bool overResizeArea = false;
+			// Top left
+			if(cursorPos.x >= x0 && cursorPos.x < x1 &&
+				cursorPos.y >= y0 && cursorPos.y < y1)
+			{
+				Cursor::setCursor(CursorType::SizeNWSE);
+				overResizeArea = true;
+			}
+
+			// Top center
+			if(cursorPos.x >= x1 && cursorPos.x < x2 &&
+				cursorPos.y >= y0 && cursorPos.y < y1)
+			{
+				Cursor::setCursor(CursorType::SizeNS);
+				overResizeArea = true;
+			}
+
+			// Top right
+			if(cursorPos.x >= x2 && cursorPos.x < x3 &&
+				cursorPos.y >= y0 && cursorPos.y < y1)
+			{
+				Cursor::setCursor(CursorType::SizeNESW);
+				overResizeArea = true;
+			}
+
+			// Middle left
+			if(cursorPos.x >= x0 && cursorPos.x < x1 &&
+				cursorPos.y >= y1 && cursorPos.y < y2)
+			{
+				Cursor::setCursor(CursorType::SizeWE);
+				overResizeArea = true;
+			}
+
+			// Middle center
+			if(cursorPos.x >= x1 && cursorPos.x < x2 &&
+				cursorPos.y >= y1 && cursorPos.y < y2)
+			{
+				Cursor::setCursor(CursorType::Arrow);
+				overResizeArea = false;
+			}
+
+			// Middle right
+			if(cursorPos.x >= x2 && cursorPos.x < x3 &&
+				cursorPos.y >= y1 && cursorPos.y < y2)
+			{
+				Cursor::setCursor(CursorType::SizeWE);
+				overResizeArea = true;
+			}
+
+			// Bottom left
+			if(cursorPos.x >= x0 && cursorPos.x < x1 &&
+				cursorPos.y >= y2 && cursorPos.y < y3)
+			{
+				Cursor::setCursor(CursorType::SizeNESW);
+				overResizeArea = true;
+			}
+
+			// Bottom center
+			if(cursorPos.x >= x1 && cursorPos.x < x2 &&
+				cursorPos.y >= y2 && cursorPos.y < y3)
+			{
+				Cursor::setCursor(CursorType::SizeNS);
+				overResizeArea = true;
+			}
+
+			// Bottom right
+			if(cursorPos.x >= x2 && cursorPos.x < x3 &&
+				cursorPos.y >= y2 && cursorPos.y < y3)
+			{
+				Cursor::setCursor(CursorType::SizeNWSE);
+				overResizeArea = true;
+			}
+
+			if(overResizeArea)
+			{
+				mResizeCursorSet = true;
+
+				return true;
+			}
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			if(mResizeCursorSet)
+			{
+				Cursor::setCursor(CursorType::Arrow);
+				mResizeCursorSet = false;
+
+				return true;
+			}
+		}
+
+		return false;
+	}
 }

+ 4 - 4
CamelotClient/BsGUITabbedTitleBar.cpp

@@ -61,18 +61,18 @@ namespace BansheeEditor
 		GUIWidget::initialize(target, ownerWindow);
 
 		GUIArea* backgroundArea = GUIArea::create(*this, 0, 1, 0, 13, 500);
-		GUITexture* titleBarBg = GUITexture::create(*this, GUIImageScaleMode::StretchToFit, EngineGUI::instance().getSkin().getStyle("TitleBarBackground"));
+		GUITexture* titleBarBg = GUITexture::create(*this, GUIImageScaleMode::StretchToFit, getSkin()->getStyle("TitleBarBackground"));
 		GUIFixedSpace& space1 = backgroundArea->getLayout().addSpace(1);
 		backgroundArea->getLayout().addElement(titleBarBg);
 		GUIFixedSpace& space2 = backgroundArea->getLayout().addSpace(1);
 
 		mMainArea = GUIArea::create(*this, 0, 1, 0, 13, 499);
 
-		GUITexture* dragDropElement = GUITexture::create(*this, GUILayoutOptions::expandableX(13, 20), GUIImageScaleMode::StretchToFit, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));
+		GUITexture* dragDropElement = GUITexture::create(*this, GUILayoutOptions::expandableX(13, 20), GUIImageScaleMode::StretchToFit, getSkin()->getStyle("TabbedBarDropArea"));
 		mLastDropElement = dragDropElement;
 
-		mMinBtn = GUIButton::create(*this, "", EngineGUI::instance().getSkin().getStyle("WinMinimizeBtn"));
-		mCloseBtn = GUIButton::create(*this, "", EngineGUI::instance().getSkin().getStyle("WinCloseBtn"));
+		mMinBtn = GUIButton::create(*this, "", getSkin()->getStyle("WinMinimizeBtn"));
+		mCloseBtn = GUIButton::create(*this, "", getSkin()->getStyle("WinCloseBtn"));
 
 		GUIFixedSpace& space3 = mMainArea->getLayout().addSpace(1);
 		mMainLayout = &mMainArea->getLayout().addLayoutX();

+ 46 - 0
CamelotClient/BsGUIWindowFrameWidget.cpp

@@ -0,0 +1,46 @@
+#include "BsGUIWindowFrameWidget.h"
+#include "BsGUIArea.h"
+#include "BsGUILayout.h"
+#include "BsGUITexture.h"
+#include "BsGUIWindowFrame.h"
+#include "BsEngineGUI.h"
+#include "BsGUIMouseEvent.h"
+#include "CmMath.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	WindowFrameWidget::WindowFrameWidget(const HSceneObject& parent)
+		:GUIWidget(parent), mWindowFrameArea(nullptr)
+	{
+
+	}
+
+	WindowFrameWidget::~WindowFrameWidget()
+	{
+
+	}
+
+	void WindowFrameWidget::initialize(CM::Viewport* target, const CM::RenderWindow* ownerWindow)
+	{
+		GUIWidget::initialize(target, ownerWindow);
+
+		GUIArea* backgroundArea = GUIArea::create(*this, 0, 0, 0, 0, 500);
+		backgroundArea->getLayout().addElement(GUITexture::create(*this, GUILayoutOptions::expandableXY(), GUIImageScaleMode::RepeatToFit, getSkin()->getStyle("WindowBackground")));
+
+		mWindowFrameArea = GUIArea::create(*this, 0, 0, 0, 0, 499);
+		mWindowFrameArea->getLayout().addElement(GUIWindowFrame::create(*this, getSkin()->getStyle("WindowFrame")));
+	}
+
+	void WindowFrameWidget::update()
+	{
+
+	}
+
+	bool WindowFrameWidget::_mouseEvent(GUIElement* element, const GUIMouseEvent& ev)
+	{
+		return GUIWidget::_mouseEvent(element, ev);
+	}
+}

+ 24 - 0
CamelotClient/BsGUIWindowFrameWidget.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIWidget.h"
+#include <boost/signal.hpp>
+
+namespace BansheeEditor
+{
+	class WindowFrameWidget : public BS::GUIWidget
+	{
+	public:
+		WindowFrameWidget(const CM::HSceneObject& parent);
+		virtual ~WindowFrameWidget();
+
+		virtual void initialize(CM::Viewport* target, const CM::RenderWindow* ownerWindow);
+
+	protected:
+		BS::GUIArea* mWindowFrameArea;
+
+		virtual void update();
+
+		virtual bool _mouseEvent(BS::GUIElement* element, const BS::GUIMouseEvent& ev);
+	};
+}

+ 2 - 0
CamelotClient/CamelotClient.vcxproj

@@ -168,6 +168,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="BsGUITabbedTitleBar.h" />
+    <ClInclude Include="BsGUIWindowFrameWidget.h" />
     <ClInclude Include="CmDebugCamera.h" />
     <ClInclude Include="CmEditorWindow.h" />
     <ClInclude Include="CmTestTextSprite.h" />
@@ -176,6 +177,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="BsGUITabbedTitleBar.cpp" />
+    <ClCompile Include="BsGUIWindowFrameWidget.cpp" />
     <ClCompile Include="CamelotClient.cpp" />
     <ClCompile Include="CmDebugCamera.cpp" />
     <ClCompile Include="CmEditorWindow.cpp" />

+ 6 - 0
CamelotClient/CamelotClient.vcxproj.filters

@@ -36,6 +36,9 @@
     <ClInclude Include="BsGUITabbedTitleBar.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="BsGUIWindowFrameWidget.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
@@ -56,5 +59,8 @@
     <ClCompile Include="BsGUITabbedTitleBar.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="BsGUIWindowFrameWidget.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 17 - 11
CamelotClient/CmEditorWindow.cpp

@@ -6,7 +6,7 @@
 #include "BsGUIManager.h"
 #include "BsGUIWidget.h"
 #include "BsGUILabel.h"
-#include "BsGUIWindowFrame.h"
+#include "BsGUIWindowFrameWidget.h"
 #include "BsGUIButton.h"
 #include "BsGUITexture.h"
 #include "BsGUISkin.h"
@@ -53,16 +53,22 @@ namespace BansheeEditor
 		mGUI->setSkin(&EngineGUI::instance().getSkin());
 
 		GameObjectHandle<TabbedTitleBar> titleBar = so->addComponent<TabbedTitleBar>();
+		titleBar->setSkin(&EngineGUI::instance().getSkin());
 		titleBar->initialize(camera->getViewport().get(), mRenderWindow.get());
 		titleBar->setDepth(127);
 
+		GameObjectHandle<WindowFrameWidget> frame = so->addComponent<WindowFrameWidget>();
+		frame->setSkin(&EngineGUI::instance().getSkin());
+		frame->initialize(camera->getViewport().get(), mRenderWindow.get());
+		frame->setDepth(129);
+
 		//// DEBUG
 		
-		GUIArea* dbgArea = GUIArea::create(*mGUI, 0, 13, 0, 0, 1998);
-		GUILayout& layout = dbgArea->getLayout();
-		
-		mDbgLabel = GUILabel::create(*mGUI, "Testing test");
-		layout.addElement(mDbgLabel);
+		//GUIArea* dbgArea = GUIArea::create(*mGUI, 0, 13, 0, 0, 1998);
+		//GUILayout& layout = dbgArea->getLayout();
+		//
+		//mDbgLabel = GUILabel::create(*mGUI, "Testing test");
+		//layout.addElement(mDbgLabel);
 
 		
 		//GUIFlexibleSpace& space4 = otherLayout.addFlexibleSpace();
@@ -75,11 +81,11 @@ namespace BansheeEditor
 		//otherLayout.addElement(GUIButton::create(*mGUI, "Test"));
 		//otherLayout.addElement(GUIWindowFrame::create(*mGUI));
 		
-		GUIArea* backgroundArea = GUIArea::create(*mGUI, 0, 0, 0, 0, 2000);
-		backgroundArea->getLayout().addElement(GUITexture::create(*mGUI, GUILayoutOptions::expandableXY(), GUIImageScaleMode::RepeatToFit, mGUI->getSkin()->getStyle("WindowBackground")));
+		//GUIArea* backgroundArea = GUIArea::create(*mGUI, 0, 0, 0, 0, 2000);
+		//backgroundArea->getLayout().addElement(GUITexture::create(*mGUI, GUILayoutOptions::expandableXY(), GUIImageScaleMode::RepeatToFit, mGUI->getSkin()->getStyle("WindowBackground")));
 
-		GUIArea* windowFrameArea = GUIArea::create(*mGUI, 0, 0, 0, 0, 1999);
-		windowFrameArea->getLayout().addElement(GUIWindowFrame::create(*mGUI));
+		//GUIArea* windowFrameArea = GUIArea::create(*mGUI, 0, 0, 0, 0, 1999);
+		//windowFrameArea->getLayout().addElement(GUIWindowFrame::create(*mGUI));
 
 		//GUIArea* titleBarBackgroundArea = GUIArea::create(*mGUI, 0, 1, 0, 11, 1999);
 		//titleBarBackgroundArea->getLayout().addSpace(1);
@@ -96,7 +102,7 @@ namespace BansheeEditor
 	{
 		Int2 cursorPos = Cursor::getWindowPosition(*mRenderWindow);
 		
-		mDbgLabel->setText("Position: " + toString(cursorPos.x) + ", " + toString(cursorPos.y));
+		//mDbgLabel->setText("Position: " + toString(cursorPos.x) + ", " + toString(cursorPos.y));
 		
 	}
 }

+ 0 - 2
CamelotClient/CmTestTextSprite.cpp

@@ -7,7 +7,6 @@
 #include "CmFont.h"
 #include "CmMaterial.h"
 #include "BsGUILabel.h"
-#include "BsGUIWindowFrame.h"
 #include "BsGUISkin.h"
 #include "BsOverlayManager.h"
 #include "BsSpriteTexture.h"
@@ -31,7 +30,6 @@ namespace CamelotFramework
 		setSkin(&EngineGUI::instance().getSkin());
 
 		GUILabel::create(*this, text);
-		GUIWindowFrame::create(*this);
 	}
 
 	void TestTextSprite::update()

+ 0 - 4
CamelotCore/Include/CmRenderTarget.h

@@ -174,9 +174,6 @@ namespace CamelotFramework
 		 */
 		void setVSync(bool vsync)  { mVSync = vsync; }
 
-		void setHasFocus(bool focus) { mHasFocus = focus; }
-		bool hasFocus() const { return mHasFocus; }
-
     protected:
 		RenderTarget();
 
@@ -189,7 +186,6 @@ namespace CamelotFramework
         unsigned int mHeight;
         unsigned int mColorDepth;
 
-		bool mHasFocus;
         bool mActive;
 		// Hardware sRGB gamma conversion done on write?
 		bool mHwGamma;

+ 6 - 1
CamelotCore/Include/CmRenderWindow.h

@@ -176,8 +176,12 @@ namespace CamelotFramework
           */
         void setDeactivateOnFocusChange(bool deactivate);
 
+		void setHasFocus(bool focus);
+		bool hasFocus() const { return mHasFocus; }
+
 		mutable boost::signal<void(RenderWindow*)> onWindowMovedOrResized;
-		
+		mutable boost::signal<void(RenderWindow*)> onWindowFocusChanged;
+
 		virtual void destroy();
 
 		static RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow = nullptr);
@@ -192,6 +196,7 @@ namespace CamelotFramework
 		bool mAutoDeactivatedOnFocusChange;
 		int mLeft;
 		int mTop;
+		bool mHasFocus;
 
 		RENDER_WINDOW_DESC mDesc;
     };

+ 0 - 1
CamelotCore/Source/CmRenderTarget.cpp

@@ -38,7 +38,6 @@ namespace CamelotFramework {
 		mActive(true),
 		mHwGamma(false), 
 		mVSync(false),
-		mHasFocus(false),
 		mFSAA(0)
     {
     }

+ 9 - 0
CamelotCore/Source/CmRenderWindow.cpp

@@ -35,6 +35,7 @@ namespace CamelotFramework
         : RenderTarget()
 		, mIsFullScreen(false)
 		, mDesc(desc)
+		, mHasFocus(false)
     {
         mAutoDeactivatedOnFocusChange = false;
     }
@@ -76,6 +77,14 @@ namespace CamelotFramework
 			onWindowMovedOrResized(this);
 	}
 
+	void RenderWindow::setHasFocus(bool focus)
+	{ 
+		mHasFocus = focus; 
+
+		if(!onWindowFocusChanged.empty())
+			onWindowFocusChanged(this);
+	}
+
 	void RenderWindow::destroy()
 	{
 		RenderWindowManager::instance().windowDestroyed(this);