Răsfoiți Sursa

Added render window functionality for minimize/maximize/restore
Added render window functionality to maximize/restore by double clicking on caption area
Hooked up min/max/close buttons on main window

Marko Pintera 11 ani în urmă
părinte
comite
9982b0ebd7

+ 59 - 0
BansheeCore/Include/BsRenderWindow.h

@@ -91,6 +91,11 @@ namespace BansheeEngine
 		 */
 		 */
 		bool isHidden() const { return mHidden; }
 		bool isHidden() const { return mHidden; }
 
 
+		/**
+		 * @brief	Returns true if the window is maximized.
+		 */
+		bool isMaximized() const { return mIsMaximized; }
+
 	protected:
 	protected:
 		friend class RenderWindowCore;
 		friend class RenderWindowCore;
 		friend class RenderWindow;
 		friend class RenderWindow;
@@ -101,6 +106,7 @@ namespace BansheeEngine
 		bool mHasFocus = false;
 		bool mHasFocus = false;
 		bool mHidden = false;
 		bool mHidden = false;
 		bool mIsModal = false;
 		bool mIsModal = false;
+		bool mIsMaximized = false;
 	};
 	};
 
 
 	/**
 	/**
@@ -151,6 +157,22 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void setActive(bool state);
 		virtual void setActive(bool state);
 
 
+		/**
+		 * @brief	Minimizes the window to the taskbar.
+		 */
+		virtual void minimize() { }
+
+		/**
+		 * @brief	Maximizes the window over the entire current screen.
+		 */
+		virtual void maximize() { }
+
+		/**
+		 * @brief	Restores the window to original position and size if it is
+		 *			minimized or maximized.
+		 */
+		virtual void restore() { }
+
         /**
         /**
          * @brief	Change the size of the window.
          * @brief	Change the size of the window.
          */
          */
@@ -187,6 +209,28 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void _windowFocusLost();
 		virtual void _windowFocusLost();
 
 
+		/**
+		 * @brief	Called when window has been maximized.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void _notifyMaximized();
+
+		/**
+		 * @brief	Called when window has been minimized.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void _notifyMinimized();
+
+		/**
+		 * @brief	Called when window has been restored 
+		 *			from minimized or maximized state.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void _notifyRestored();
+
 	protected:
 	protected:
 		friend class RenderWindow;
 		friend class RenderWindow;
 		friend class RenderWindowManager;
 		friend class RenderWindowManager;
@@ -252,6 +296,21 @@ namespace BansheeEngine
 		 */
 		 */
 		void show(CoreAccessor& accessor);
 		void show(CoreAccessor& accessor);
 
 
+		/**
+		 * @copydoc	RenderWindowCore::minimize
+		 */
+		void minimize(CoreAccessor& accessor);
+
+		/**
+		 * @copydoc	RenderWindowCore::maximize
+		 */
+		void maximize(CoreAccessor& accessor);
+
+		/**
+		 * @copydoc	RenderWindowCore::restore
+		 */
+		void restore(CoreAccessor& accessor);
+
 		/**
 		/**
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
 		 */

+ 63 - 0
BansheeCore/Source/BsRenderWindow.cpp

@@ -85,6 +85,36 @@ namespace BansheeEngine
 		RenderWindowManager::instance().notifyFocusLost(this);
 		RenderWindowManager::instance().notifyFocusLost(this);
 	}
 	}
 
 
+	void RenderWindowCore::_notifyMaximized()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
+
+		props.mIsMaximized = true;
+		RenderWindowManager::instance().notifyPropertiesDirty(this);
+	}
+
+	void RenderWindowCore::_notifyMinimized()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
+
+		props.mIsMaximized = false;
+		RenderWindowManager::instance().notifyPropertiesDirty(this);
+	}
+
+	void RenderWindowCore::_notifyRestored()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
+
+		props.mIsMaximized = false;
+		RenderWindowManager::instance().notifyPropertiesDirty(this);
+	}
+
 	const RenderWindowProperties& RenderWindowCore::getProperties() const
 	const RenderWindowProperties& RenderWindowCore::getProperties() const
 	{
 	{
 		return static_cast<const RenderWindowProperties&>(getPropertiesInternal());
 		return static_cast<const RenderWindowProperties&>(getPropertiesInternal());
@@ -147,6 +177,39 @@ namespace BansheeEngine
 		accessor.queueCommand(std::bind(showFunc, getCore()));
 		accessor.queueCommand(std::bind(showFunc, getCore()));
 	}
 	}
 
 
+	void RenderWindow::minimize(CoreAccessor& accessor)
+	{
+		std::function<void(SPtr<RenderWindowCore>)> minimizeFunc =
+			[](SPtr<RenderWindowCore> renderWindow)
+		{
+			renderWindow->minimize();
+		};
+
+		accessor.queueCommand(std::bind(minimizeFunc, getCore()));
+	}
+
+	void RenderWindow::maximize(CoreAccessor& accessor)
+	{
+		std::function<void(SPtr<RenderWindowCore>)> maximizeFunc =
+			[](SPtr<RenderWindowCore> renderWindow)
+		{
+			renderWindow->maximize();
+		};
+
+		accessor.queueCommand(std::bind(maximizeFunc, getCore()));
+	}
+
+	void RenderWindow::restore(CoreAccessor& accessor)
+	{
+		std::function<void(SPtr<RenderWindowCore>)> restoreFunc =
+			[](SPtr<RenderWindowCore> renderWindow)
+		{
+			renderWindow->restore();
+		};
+
+		accessor.queueCommand(std::bind(restoreFunc, getCore()));
+	}
+
 	void RenderWindow::setFullscreen(CoreAccessor& accessor, UINT32 width, UINT32 height,
 	void RenderWindow::setFullscreen(CoreAccessor& accessor, UINT32 width, UINT32 height,
 		float refreshRate, UINT32 monitorIdx)
 		float refreshRate, UINT32 monitorIdx)
 	{
 	{

+ 39 - 1
BansheeCore/Source/Win32/BsPlatformWndProc.cpp

@@ -142,6 +142,14 @@ namespace BansheeEngine
 			break;
 			break;
 		case WM_SIZE:
 		case WM_SIZE:
 			win->_windowMovedOrResized();
 			win->_windowMovedOrResized();
+
+			if (wParam == SIZE_MAXIMIZED)
+				win->_notifyMaximized();
+			else if (wParam == SIZE_MINIMIZED)
+				win->_notifyMinimized();
+			else if (wParam == SIZE_RESTORED)
+				win->_notifyRestored();
+
 			break;
 			break;
 		case WM_SETCURSOR:
 		case WM_SETCURSOR:
 			if(isCursorHidden())
 			if(isCursorHidden())
@@ -180,13 +188,27 @@ namespace BansheeEngine
 			}
 			}
 			return true;
 			return true;
 		case WM_GETMINMAXINFO:
 		case WM_GETMINMAXINFO:
+		{
 			// Prevent the window from going smaller than some minimu size
 			// Prevent the window from going smaller than some minimu size
 			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
 			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
 			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
 			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+
+			// Ensure maximizes window has proper size and doesn't cover the entire screen
+			const POINT ptZero = { 0, 0 };
+			HMONITOR primaryMonitor = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
+
+			MONITORINFO monitorInfo;
+			monitorInfo.cbSize = sizeof(MONITORINFO);
+			GetMonitorInfo(primaryMonitor, &monitorInfo);
+
+			((MINMAXINFO*)lParam)->ptMaxPosition.x = monitorInfo.rcWork.left - monitorInfo.rcMonitor.left;
+			((MINMAXINFO*)lParam)->ptMaxPosition.y = monitorInfo.rcWork.top - monitorInfo.rcMonitor.top;
+			((MINMAXINFO*)lParam)->ptMaxSize.x = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
+			((MINMAXINFO*)lParam)->ptMaxSize.y = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
+		}
 			break;
 			break;
 		case WM_CLOSE:
 		case WM_CLOSE:
 			{
 			{
-				// TODO - Only stop main loop if primary window is closed!!
 				gCoreApplication().stopMainLoop();
 				gCoreApplication().stopMainLoop();
 
 
 				return 0;
 				return 0;
@@ -223,6 +245,22 @@ namespace BansheeEngine
 
 
 				return HTCLIENT;
 				return HTCLIENT;
 			}
 			}
+		case WM_NCLBUTTONDBLCLK:
+			// Maximize/Restore on double-click
+			if (wParam == HTCAPTION)
+			{
+				WINDOWPLACEMENT windowPlacement;
+				windowPlacement.length = sizeof(WINDOWPLACEMENT);
+				GetWindowPlacement(hWnd, &windowPlacement);
+
+				if (windowPlacement.showCmd == SW_MAXIMIZE)
+					ShowWindow(hWnd, SW_RESTORE);
+				else
+					ShowWindow(hWnd, SW_MAXIMIZE);
+
+				return 0;
+			}
+			break;
 		case WM_MOUSELEAVE:
 		case WM_MOUSELEAVE:
 			{
 			{
 				// Note: Right now I track only mouse leaving client area. So it's possible for the "mouse left window" callback
 				// Note: Right now I track only mouse leaving client area. So it's possible for the "mouse left window" callback

+ 15 - 0
BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h

@@ -57,6 +57,21 @@ namespace BansheeEngine
 		 */
 		 */
 		void setActive(bool state);
 		void setActive(bool state);
 
 
+		/**
+		 * @copydoc	RenderWindowCore::minimize
+		 */
+		void minimize();
+
+		/**
+		 * @copydoc	RenderWindowCore::maximize
+		 */
+		void maximize();
+
+		/**
+		 * @copydoc	RenderWindowCore::restore
+		 */
+		void restore();
+
 		/**
 		/**
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
 		 */

+ 24 - 0
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp

@@ -359,6 +359,30 @@ namespace BansheeEngine
 		RenderWindowManager::instance().notifyPropertiesDirty(this);
 		RenderWindowManager::instance().notifyPropertiesDirty(this);
 	}
 	}
 
 
+	void D3D11RenderWindowCore::minimize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+	}
+
+	void D3D11RenderWindowCore::maximize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+	}
+
+	void D3D11RenderWindowCore::restore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+	}
+
 	void D3D11RenderWindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	void D3D11RenderWindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 15 - 0
BansheeD3D9RenderSystem/Include/BsD3D9RenderWindow.h

@@ -53,6 +53,21 @@ namespace BansheeEngine
 		 */
 		 */
 		void setHidden(bool hidden);
 		void setHidden(bool hidden);
 
 
+		/**
+		 * @copydoc	RenderWindowCore::minimize
+		 */
+		void minimize();
+
+		/**
+		 * @copydoc	RenderWindowCore::maximize
+		 */
+		void maximize();
+
+		/**
+		 * @copydoc	RenderWindowCore::restore
+		 */
+		void restore();
+
 		/**
 		/**
 		 * @copydoc RenderWindowCore::move
 		 * @copydoc RenderWindowCore::move
 		 */
 		 */

+ 24 - 0
BansheeD3D9RenderSystem/Source/BsD3D9RenderWindow.cpp

@@ -346,6 +346,30 @@ namespace BansheeEngine
 		RenderWindowManager::instance().notifyPropertiesDirty(this);
 		RenderWindowManager::instance().notifyPropertiesDirty(this);
 	}
 	}
 
 
+	void D3D9RenderWindowCore::minimize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+	}
+
+	void D3D9RenderWindowCore::maximize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+	}
+
+	void D3D9RenderWindowCore::restore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+	}
+
 	void D3D9RenderWindowCore::move(INT32 top, INT32 left)
 	void D3D9RenderWindowCore::move(INT32 top, INT32 left)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 5 - 1
BansheeEditor/Include/BsEditorWidgetLayout.h

@@ -25,14 +25,18 @@ namespace BansheeEngine
 
 
 	public:
 	public:
 		EditorWidgetLayout(const DockManagerLayoutPtr& dockLayout);
 		EditorWidgetLayout(const DockManagerLayoutPtr& dockLayout);
-		EditorWidgetLayout(const PrivatelyConstruct& dummy) { }
+		EditorWidgetLayout(const PrivatelyConstruct& dummy);
 
 
 		Vector<Entry>& getEntries() { return mEntries; }
 		Vector<Entry>& getEntries() { return mEntries; }
 		const DockManagerLayoutPtr& getDockLayout() const { return mDockLayout; }
 		const DockManagerLayoutPtr& getDockLayout() const { return mDockLayout; }
 
 
+		void setIsMainWindowMaximized(bool maximized) { mMaximized = maximized; }
+		bool getIsMainWindowMaximized() const { return mMaximized; }
+
 	private:
 	private:
 		Vector<Entry> mEntries;
 		Vector<Entry> mEntries;
 		DockManagerLayoutPtr mDockLayout;
 		DockManagerLayoutPtr mDockLayout;
+		bool mMaximized;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/

+ 4 - 0
BansheeEditor/Include/BsEditorWidgetLayoutRTTI.h

@@ -18,6 +18,9 @@ namespace BansheeEngine
 		DockManagerLayoutPtr getDockLayout(EditorWidgetLayout* obj) { return obj->mDockLayout; }
 		DockManagerLayoutPtr getDockLayout(EditorWidgetLayout* obj) { return obj->mDockLayout; }
 		void setDockLayout(EditorWidgetLayout* obj, DockManagerLayoutPtr val) { obj->mDockLayout = val; }
 		void setDockLayout(EditorWidgetLayout* obj, DockManagerLayoutPtr val) { obj->mDockLayout = val; }
 
 
+		bool& getIsMainWindowMaximized(EditorWidgetLayout* obj) { return obj->mMaximized; }
+		void setIsMainWindowMaximized(EditorWidgetLayout* obj, bool& val) { obj->mMaximized = val; }
+
 	public:
 	public:
 		EditorWidgetLayoutRTTI()
 		EditorWidgetLayoutRTTI()
 		{
 		{
@@ -25,6 +28,7 @@ namespace BansheeEngine
 				&EditorWidgetLayoutRTTI::setEntry, &EditorWidgetLayoutRTTI::setEntriesArraySize);
 				&EditorWidgetLayoutRTTI::setEntry, &EditorWidgetLayoutRTTI::setEntriesArraySize);
 
 
 			addReflectablePtrField("mDockLayout", 1, &EditorWidgetLayoutRTTI::getDockLayout, &EditorWidgetLayoutRTTI::setDockLayout);
 			addReflectablePtrField("mDockLayout", 1, &EditorWidgetLayoutRTTI::getDockLayout, &EditorWidgetLayoutRTTI::setDockLayout);
+			addPlainField("mMaximized", 2, &EditorWidgetLayoutRTTI::getIsMainWindowMaximized, &EditorWidgetLayoutRTTI::setIsMainWindowMaximized);
 		}
 		}
 
 
 		virtual const String& getRTTIName()
 		virtual const String& getRTTIName()

+ 1 - 1
BansheeEditor/Include/BsEditorWindowBase.h

@@ -35,7 +35,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Returns the render window that this editor window is being rendered to.
 		 * @brief	Returns the render window that this editor window is being rendered to.
 		 */
 		 */
-		RenderWindowPtr _getRenderWindow() const { return mRenderWindow; }
+		RenderWindowPtr getRenderWindow() const { return mRenderWindow; }
 
 
 	protected:
 	protected:
 		EditorWindowBase();
 		EditorWindowBase();

+ 1 - 1
BansheeEditor/Include/BsGUIMenuBar.h

@@ -29,7 +29,7 @@ namespace BansheeEngine
 		RenderWindow* mParentWindow;
 		RenderWindow* mParentWindow;
 		GUIWidget* mParentWidget;
 		GUIWidget* mParentWidget;
 		GUIArea* mMainArea;
 		GUIArea* mMainArea;
-		GUIArea* mBackgroundArea;
+		GUIArea* mBgTextureArea;
 		GUITexture* mBgTexture;
 		GUITexture* mBgTexture;
 		GUITexture* mLogoTexture;
 		GUITexture* mLogoTexture;
 
 

+ 4 - 4
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -96,11 +96,11 @@ namespace BansheeEngine
 	const WString BuiltinEditorResources::WindowCloseButtonNormal = L"WindowCloseBtnNormal.psd";
 	const WString BuiltinEditorResources::WindowCloseButtonNormal = L"WindowCloseBtnNormal.psd";
 	const WString BuiltinEditorResources::WindowCloseButtonHover = L"WindowCloseBtnHover.psd";
 	const WString BuiltinEditorResources::WindowCloseButtonHover = L"WindowCloseBtnHover.psd";
 
 
-	const WString BuiltinEditorResources::WindowMinButtonNormal = L"WindowMaxBtnNormal.psd";
-	const WString BuiltinEditorResources::WindowMinButtonHover = L"WindowMaxBtnHover.psd";
+	const WString BuiltinEditorResources::WindowMinButtonNormal = L"WindowMinBtnNormal.psd"; 
+	const WString BuiltinEditorResources::WindowMinButtonHover = L"WindowMinBtnHover.psd"; 
 
 
-	const WString BuiltinEditorResources::WindowMaxButtonNormal = L"WindowMinBtnNormal.psd";
-	const WString BuiltinEditorResources::WindowMaxButtonHover = L"WindowMinBtnHover.psd";
+	const WString BuiltinEditorResources::WindowMaxButtonNormal = L"WindowMaxBtnNormal.psd";
+	const WString BuiltinEditorResources::WindowMaxButtonHover = L"WindowMaxBtnHover.psd";
 
 
 	const WString BuiltinEditorResources::TabbedBarBtnNormal = L"TabbedButtonNormal.psd";
 	const WString BuiltinEditorResources::TabbedBarBtnNormal = L"TabbedButtonNormal.psd";
 	const WString BuiltinEditorResources::TabbedBarBtnActive = L"TabbedButtonActive.psd";
 	const WString BuiltinEditorResources::TabbedBarBtnActive = L"TabbedButtonActive.psd";

+ 2 - 2
BansheeEditor/Source/BsEditorWidget.cpp

@@ -82,7 +82,7 @@ namespace BansheeEngine
 	Vector2I EditorWidgetBase::screenToWidgetPos(const Vector2I& screenPos) const
 	Vector2I EditorWidgetBase::screenToWidgetPos(const Vector2I& screenPos) const
 	{
 	{
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
-		RenderWindowPtr parentRenderWindow = parentEditorWindow->_getRenderWindow();
+		RenderWindowPtr parentRenderWindow = parentEditorWindow->getRenderWindow();
 
 
 		Vector2I windowPos = parentRenderWindow->screenToWindowPos(screenPos);
 		Vector2I windowPos = parentRenderWindow->screenToWindowPos(screenPos);
 		windowPos.x -= mX;
 		windowPos.x -= mX;
@@ -94,7 +94,7 @@ namespace BansheeEngine
 	Vector2I EditorWidgetBase::widgetToScreenPos(const Vector2I& widgetPos) const
 	Vector2I EditorWidgetBase::widgetToScreenPos(const Vector2I& widgetPos) const
 	{
 	{
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
-		RenderWindowPtr parentRenderWindow = parentEditorWindow->_getRenderWindow();
+		RenderWindowPtr parentRenderWindow = parentEditorWindow->getRenderWindow();
 
 
 		Vector2I windowPos = widgetPos;
 		Vector2I windowPos = widgetPos;
 		windowPos.x += mX;
 		windowPos.x += mX;

+ 5 - 1
BansheeEditor/Source/BsEditorWidgetLayout.cpp

@@ -11,7 +11,11 @@ namespace BansheeEngine
 	{ }
 	{ }
 
 
 	EditorWidgetLayout::EditorWidgetLayout(const DockManagerLayoutPtr& dockLayout)
 	EditorWidgetLayout::EditorWidgetLayout(const DockManagerLayoutPtr& dockLayout)
-		:mDockLayout(dockLayout)
+		:mDockLayout(dockLayout), mMaximized(false)
+	{ }
+
+	EditorWidgetLayout::EditorWidgetLayout(const PrivatelyConstruct& dummy)
+		: mMaximized(false)
 	{ }
 	{ }
 
 
 	/************************************************************************/
 	/************************************************************************/

+ 8 - 2
BansheeEditor/Source/BsEditorWidgetManager.cpp

@@ -11,6 +11,7 @@
 #include "BsRenderWindow.h"
 #include "BsRenderWindow.h"
 #include "BsRenderWindowManager.h"
 #include "BsRenderWindowManager.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
+#include "BsCoreThread.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -180,6 +181,8 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
+		layout->setIsMainWindowMaximized(mainWindow->getRenderWindow()->getProperties().isMaximized());
+
 		return layout;
 		return layout;
 	}
 	}
 
 
@@ -226,6 +229,9 @@ namespace BansheeEngine
 			if(widget->_getParent() == nullptr)
 			if(widget->_getParent() == nullptr)
 				widget->close();
 				widget->close();
 		}
 		}
+
+		if (layout->getIsMainWindowMaximized())
+			mainWindow->getRenderWindow()->maximize(gCoreAccessor());
 	}
 	}
 
 
 	void EditorWidgetManager::onPointerPressed(const PointerEvent& event)
 	void EditorWidgetManager::onPointerPressed(const PointerEvent& event)
@@ -235,7 +241,7 @@ namespace BansheeEngine
 			EditorWidgetBase* widget = widgetData.second;
 			EditorWidgetBase* widget = widgetData.second;
 			EditorWidgetContainer* parentContainer = widget->_getParent();
 			EditorWidgetContainer* parentContainer = widget->_getParent();
 			EditorWindowBase* parentWindow = parentContainer->getParentWindow();
 			EditorWindowBase* parentWindow = parentContainer->getParentWindow();
-			RenderWindowPtr parentRenderWindow = parentWindow->_getRenderWindow();
+			RenderWindowPtr parentRenderWindow = parentWindow->getRenderWindow();
 			const RenderWindowProperties& props = parentRenderWindow->getProperties();
 			const RenderWindowProperties& props = parentRenderWindow->getProperties();
 
 
 			if (!props.hasFocus())
 			if (!props.hasFocus())
@@ -277,7 +283,7 @@ namespace BansheeEngine
 				continue;
 				continue;
 
 
 			EditorWindowBase* parentWindow = parentContainer->getParentWindow();
 			EditorWindowBase* parentWindow = parentContainer->getParentWindow();
-			RenderWindowPtr parentRenderWindow = parentWindow->_getRenderWindow();
+			RenderWindowPtr parentRenderWindow = parentWindow->getRenderWindow();
 
 
 			if (parentRenderWindow.get() != &window)
 			if (parentRenderWindow.get() != &window)
 				continue;
 				continue;

+ 13 - 9
BansheeEditor/Source/BsGUIMenuBar.cpp

@@ -11,20 +11,21 @@
 #include "BsGUIDropDownBoxManager.h"
 #include "BsGUIDropDownBoxManager.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
 #include "BsPlatform.h"
 #include "BsPlatform.h"
+#include "BsCoreThread.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIMenuBar::NUM_ELEMENTS_AFTER_CONTENT = 8;
 	const UINT32 GUIMenuBar::NUM_ELEMENTS_AFTER_CONTENT = 8;
 
 
 	GUIMenuBar::GUIMenuBar(GUIWidget* parent, RenderWindow* parentWindow)
 	GUIMenuBar::GUIMenuBar(GUIWidget* parent, RenderWindow* parentWindow)
-		:mParentWidget(parent), mParentWindow(parentWindow), mMainArea(nullptr), mBackgroundArea(nullptr), 
+		:mParentWidget(parent), mParentWindow(parentWindow), mMainArea(nullptr), mBgTextureArea(nullptr), 
 		mBgTexture(nullptr), mLogoTexture(nullptr), mSubMenuOpen(false), mSubMenuButton(nullptr)
 		mBgTexture(nullptr), mLogoTexture(nullptr), mSubMenuOpen(false), mSubMenuButton(nullptr)
 	{
 	{
-		mBackgroundArea = GUIArea::create(*parent, 0, 0, 1, 13, 9900);
+		mBgTextureArea = GUIArea::create(*parent, 0, 0, 1, 13, 9900);
 		mMainArea = GUIArea::create(*parent, 0, 0, 1, 13, 9899);
 		mMainArea = GUIArea::create(*parent, 0, 0, 1, 13, 9899);
 
 
 		mBgTexture = GUITexture::create(GUIImageScaleMode::StretchToFit, GUIOptions(GUIOption::flexibleWidth(), GUIOption::flexibleHeight()), "MenuBarBg");
 		mBgTexture = GUITexture::create(GUIImageScaleMode::StretchToFit, GUIOptions(GUIOption::flexibleWidth(), GUIOption::flexibleHeight()), "MenuBarBg");
-		mBackgroundArea->getLayout().addElement(mBgTexture);
+		mBgTextureArea->getLayout().addElement(mBgTexture);
 
 
 		mLogoTexture = GUITexture::create(GUIImageScaleMode::StretchToFit, "MenuBarBansheeLogo");
 		mLogoTexture = GUITexture::create(GUIImageScaleMode::StretchToFit, "MenuBarBansheeLogo");
 		GUILayout& mainLayout = mMainArea->getLayout();
 		GUILayout& mainLayout = mMainArea->getLayout();
@@ -70,16 +71,16 @@ namespace BansheeEngine
 		GUIElement::destroy(mLogoTexture);
 		GUIElement::destroy(mLogoTexture);
 
 
 		GUIArea::destroy(mMainArea);
 		GUIArea::destroy(mMainArea);
-		GUIArea::destroy(mBackgroundArea);
+		GUIArea::destroy(mBgTextureArea);
 	}
 	}
 
 
 	void GUIMenuBar::setArea(INT32 x, INT32 y, UINT32 width, UINT32 height)
 	void GUIMenuBar::setArea(INT32 x, INT32 y, UINT32 width, UINT32 height)
 	{
 	{
 		mMainArea->setPosition(x, y);
 		mMainArea->setPosition(x, y);
-		mBackgroundArea->setPosition(x, y);
+		mBgTextureArea->setPosition(x, y);
 
 
 		mMainArea->setSize(width, height);
 		mMainArea->setSize(width, height);
-		mBackgroundArea->setSize(width, height);
+		mBgTextureArea->setSize(width, height);
 
 
 		refreshNonClientAreas();
 		refreshNonClientAreas();
 	}
 	}
@@ -291,17 +292,20 @@ namespace BansheeEngine
 
 
 	void GUIMenuBar::onMinimizeClicked()
 	void GUIMenuBar::onMinimizeClicked()
 	{
 	{
-		// TODO
+		mParentWindow->minimize(gCoreAccessor());
 	}
 	}
 
 
 	void GUIMenuBar::onMaximizeClicked()
 	void GUIMenuBar::onMaximizeClicked()
 	{
 	{
-		// TODO
+		if(mParentWindow->getProperties().isMaximized())
+			mParentWindow->restore(gCoreAccessor());
+		else
+			mParentWindow->maximize(gCoreAccessor());
 	}
 	}
 
 
 	void GUIMenuBar::onCloseClicked()
 	void GUIMenuBar::onCloseClicked()
 	{
 	{
-		// TODO
+		gCoreApplication().stopMainLoop();
 	}
 	}
 
 
 	void GUIMenuBar::refreshNonClientAreas()
 	void GUIMenuBar::refreshNonClientAreas()

+ 1 - 1
BansheeEditor/Source/BsSceneViewHandler.cpp

@@ -114,7 +114,7 @@ namespace BansheeEngine
 
 
 	Vector2I SceneViewHandler::wrapCursorToWindow()
 	Vector2I SceneViewHandler::wrapCursorToWindow()
 	{
 	{
-		RenderWindowPtr parentWindow = mParentWidget->getParentWindow()->_getRenderWindow();
+		RenderWindowPtr parentWindow = mParentWidget->getParentWindow()->getRenderWindow();
 
 
 		Vector2I windowPos = parentWindow->screenToWindowPos(Cursor::instance().getScreenPosition());
 		Vector2I windowPos = parentWindow->screenToWindowPos(Cursor::instance().getScreenPosition());
 		const RenderWindowProperties& rwProps = parentWindow->getProperties();
 		const RenderWindowProperties& rwProps = parentWindow->getProperties();

+ 5 - 0
BansheeEngine/Include/BsGUIButtonBase.h

@@ -68,6 +68,11 @@ namespace BansheeEngine
 		 * @brief	Triggered when pointer that was previously hovering leaves the button.
 		 * @brief	Triggered when pointer that was previously hovering leaves the button.
 		 */
 		 */
 		Event<void()> onOut;
 		Event<void()> onOut;
+
+		/**
+		 * @brief	Triggered when button is clicked twice in rapid succession.
+		 */
+		Event<void()> onDoubleClick;
 	protected:
 	protected:
 		GUIButtonBase(const String& styleName, const GUIContent& content, const GUILayoutOptions& layoutOptions);
 		GUIButtonBase(const String& styleName, const GUIContent& content, const GUILayoutOptions& layoutOptions);
 		virtual ~GUIButtonBase();
 		virtual ~GUIButtonBase();

+ 5 - 0
BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -280,6 +280,11 @@ namespace BansheeEngine
 
 
 			return true;
 			return true;
 		}
 		}
+		else if (ev.getType() == GUIMouseEventType::MouseDoubleClick)
+		{
+			if (!onDoubleClick.empty())
+				onDoubleClick();
+		}
 
 
 		return false;
 		return false;
 	}
 	}

+ 15 - 0
BansheeGLRenderSystem/Include/BsWin32Window.h

@@ -52,6 +52,21 @@ namespace BansheeEngine
 		 */
 		 */
 		void setHidden(bool hidden);
 		void setHidden(bool hidden);
 
 
+		/**
+		 * @copydoc	RenderWindowCore::minimize
+		 */
+		void minimize();
+
+		/**
+		 * @copydoc	RenderWindowCore::maximize
+		 */
+		void maximize();
+
+		/**
+		 * @copydoc	RenderWindowCore::restore
+		 */
+		void restore();
+
 		/**
 		/**
 		 * @copydoc RenderWindowCore::move
 		 * @copydoc RenderWindowCore::move
 		 */
 		 */

+ 24 - 0
BansheeGLRenderSystem/Source/BsWin32Window.cpp

@@ -486,6 +486,30 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void Win32WindowCore::minimize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+	}
+
+	void Win32WindowCore::maximize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+	}
+
+	void Win32WindowCore::restore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mHWnd)
+			SendMessage(mHWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+	}
+
 	void Win32WindowCore::swapBuffers()
 	void Win32WindowCore::swapBuffers()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 3 - 1
TODO.txt

@@ -5,6 +5,9 @@
 When serializing Camera I cannot save the reference to RenderTexture. Make it a Resource?
 When serializing Camera I cannot save the reference to RenderTexture. Make it a Resource?
 Possibly set up automatic refresh in debug mode after initialization? As an ad-hoc unit test
 Possibly set up automatic refresh in debug mode after initialization? As an ad-hoc unit test
 
 
+<<<<<Menu bar issues>>>>>
+Double-clicking the title bar should cause the window to maximize
+
 <<<<Multi-resource saving>>>>:
 <<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Register it in its meta file
  - Register it in its meta file
@@ -21,7 +24,6 @@ I can get mono errors by checking g_print calls in goutput.c
 
 
 Running embedded mono with VS attached causes managed null refs to be registered as access violations
 Running embedded mono with VS attached causes managed null refs to be registered as access violations
 
 
-Crash on GLTextureBuffer::download on shutdown (OpenGL error invalid enum)
 Create a stack allocatable custom vector implementation and make getResourceDependencies and getCoreDependencies use it.
 Create a stack allocatable custom vector implementation and make getResourceDependencies and getCoreDependencies use it.
  - These methods are called often and cause allocations whenever they are.
  - These methods are called often and cause allocations whenever they are.